@@ -34,7 +34,7 @@ use failure::LOCAL_STDERR;
34
34
use fmt;
35
35
use io:: { Reader , Writer , IoResult , IoError , OtherIoError , Buffer ,
36
36
standard_error, EndOfFile , LineBufferedWriter , BufferedReader } ;
37
- use kinds:: Send ;
37
+ use kinds:: { Sync , Send } ;
38
38
use libc;
39
39
use mem;
40
40
use option:: Option ;
@@ -98,26 +98,34 @@ thread_local! {
98
98
}
99
99
}
100
100
101
+ struct RaceBox ( BufferedReader < StdReader > ) ;
102
+
103
+ unsafe impl Send for RaceBox { }
104
+ unsafe impl Sync for RaceBox { }
105
+
101
106
/// A synchronized wrapper around a buffered reader from stdin
102
107
#[ deriving( Clone ) ]
103
108
pub struct StdinReader {
104
- inner : Arc < Mutex < BufferedReader < StdReader > > > ,
109
+ inner : Arc < Mutex < RaceBox > > ,
105
110
}
106
111
112
+ unsafe impl Send for StdinReader { }
113
+ unsafe impl Sync for StdinReader { }
114
+
107
115
/// A guard for exclusive access to `StdinReader`'s internal `BufferedReader`.
108
116
pub struct StdinReaderGuard < ' a > {
109
- inner : MutexGuard < ' a , BufferedReader < StdReader > > ,
117
+ inner : MutexGuard < ' a , RaceBox > ,
110
118
}
111
119
112
120
impl < ' a > Deref < BufferedReader < StdReader > > for StdinReaderGuard < ' a > {
113
121
fn deref ( & self ) -> & BufferedReader < StdReader > {
114
- & * self . inner
122
+ & self . inner . 0
115
123
}
116
124
}
117
125
118
126
impl < ' a > DerefMut < BufferedReader < StdReader > > for StdinReaderGuard < ' a > {
119
127
fn deref_mut ( & mut self ) -> & mut BufferedReader < StdReader > {
120
- & mut * self . inner
128
+ & mut self . inner . 0
121
129
}
122
130
}
123
131
@@ -147,53 +155,53 @@ impl StdinReader {
147
155
/// The read is performed atomically - concurrent read calls in other
148
156
/// threads will not interleave with this one.
149
157
pub fn read_line ( & mut self ) -> IoResult < String > {
150
- self . inner . lock ( ) . read_line ( )
158
+ self . inner . lock ( ) . 0 . read_line ( )
151
159
}
152
160
153
161
/// Like `Buffer::read_until`.
154
162
///
155
163
/// The read is performed atomically - concurrent read calls in other
156
164
/// threads will not interleave with this one.
157
165
pub fn read_until ( & mut self , byte : u8 ) -> IoResult < Vec < u8 > > {
158
- self . inner . lock ( ) . read_until ( byte)
166
+ self . inner . lock ( ) . 0 . read_until ( byte)
159
167
}
160
168
161
169
/// Like `Buffer::read_char`.
162
170
///
163
171
/// The read is performed atomically - concurrent read calls in other
164
172
/// threads will not interleave with this one.
165
173
pub fn read_char ( & mut self ) -> IoResult < char > {
166
- self . inner . lock ( ) . read_char ( )
174
+ self . inner . lock ( ) . 0 . read_char ( )
167
175
}
168
176
}
169
177
170
178
impl Reader for StdinReader {
171
179
fn read ( & mut self , buf : & mut [ u8 ] ) -> IoResult < uint > {
172
- self . inner . lock ( ) . read ( buf)
180
+ self . inner . lock ( ) . 0 . read ( buf)
173
181
}
174
182
175
183
// We have to manually delegate all of these because the default impls call
176
184
// read more than once and we don't want those calls to interleave (or
177
185
// incur the costs of repeated locking).
178
186
179
187
fn read_at_least ( & mut self , min : uint , buf : & mut [ u8 ] ) -> IoResult < uint > {
180
- self . inner . lock ( ) . read_at_least ( min, buf)
188
+ self . inner . lock ( ) . 0 . read_at_least ( min, buf)
181
189
}
182
190
183
191
fn push_at_least ( & mut self , min : uint , len : uint , buf : & mut Vec < u8 > ) -> IoResult < uint > {
184
- self . inner . lock ( ) . push_at_least ( min, len, buf)
192
+ self . inner . lock ( ) . 0 . push_at_least ( min, len, buf)
185
193
}
186
194
187
195
fn read_to_end ( & mut self ) -> IoResult < Vec < u8 > > {
188
- self . inner . lock ( ) . read_to_end ( )
196
+ self . inner . lock ( ) . 0 . read_to_end ( )
189
197
}
190
198
191
199
fn read_le_uint_n ( & mut self , nbytes : uint ) -> IoResult < u64 > {
192
- self . inner . lock ( ) . read_le_uint_n ( nbytes)
200
+ self . inner . lock ( ) . 0 . read_le_uint_n ( nbytes)
193
201
}
194
202
195
203
fn read_be_uint_n ( & mut self , nbytes : uint ) -> IoResult < u64 > {
196
- self . inner . lock ( ) . read_be_uint_n ( nbytes)
204
+ self . inner . lock ( ) . 0 . read_be_uint_n ( nbytes)
197
205
}
198
206
}
199
207
@@ -221,7 +229,7 @@ pub fn stdin() -> StdinReader {
221
229
BufferedReader :: new ( stdin_raw ( ) )
222
230
} ;
223
231
let stdin = StdinReader {
224
- inner : Arc :: new ( Mutex :: new ( stdin) )
232
+ inner : Arc :: new ( Mutex :: new ( RaceBox ( stdin) ) )
225
233
} ;
226
234
STDIN = mem:: transmute ( box stdin) ;
227
235
@@ -426,6 +434,9 @@ pub struct StdWriter {
426
434
inner : StdSource
427
435
}
428
436
437
+ unsafe impl Send for StdWriter { }
438
+ unsafe impl Sync for StdWriter { }
439
+
429
440
impl StdWriter {
430
441
/// Gets the size of this output window, if possible. This is typically used
431
442
/// when the writer is attached to something like a terminal, this is used
0 commit comments