@@ -13,9 +13,9 @@ use std::raw::TraitObject;
13
13
use std:: str:: SendStr ;
14
14
use std:: collections:: HashMap ;
15
15
use std:: collections:: hash_map:: { Entries , Occupied , Vacant } ;
16
- use std:: sync:: RWLock ;
17
16
use std:: { hash, mem} ;
18
17
18
+ use mucell:: MuCell ;
19
19
use uany:: { UncheckedAnyDowncast , UncheckedAnyMutDowncast } ;
20
20
21
21
use http:: { mod, LineEnding } ;
@@ -98,7 +98,7 @@ fn header_name<T: Header>() -> &'static str {
98
98
/// A map of header fields on requests and responses.
99
99
#[ deriving( Clone ) ]
100
100
pub struct Headers {
101
- data : HashMap < CaseInsensitive , RWLock < Item > >
101
+ data : HashMap < CaseInsensitive , MuCell < Item > >
102
102
}
103
103
104
104
impl Headers {
@@ -118,12 +118,12 @@ impl Headers {
118
118
Some ( ( name, value) ) => {
119
119
debug ! ( "raw header: {}={}" , name, value[ ] . to_ascii( ) ) ;
120
120
let name = CaseInsensitive ( Owned ( name) ) ;
121
- let item = match headers. data . entry ( name) {
122
- Vacant ( entry) => entry. set ( RWLock :: new ( Item :: raw ( vec ! [ ] ) ) ) ,
121
+ let mut item = match headers. data . entry ( name) {
122
+ Vacant ( entry) => entry. set ( MuCell :: new ( Item :: raw ( vec ! [ ] ) ) ) ,
123
123
Occupied ( entry) => entry. into_mut ( )
124
124
} ;
125
125
126
- match & mut item. write ( ) . raw {
126
+ match & mut item. borrow_mut ( ) . raw {
127
127
& Some ( ref mut raw) => raw. push ( value) ,
128
128
// Unreachable
129
129
_ => { }
@@ -140,7 +140,7 @@ impl Headers {
140
140
/// The field is determined by the type of the value being set.
141
141
pub fn set < H : Header + HeaderFormat > ( & mut self , value : H ) {
142
142
self . data . insert ( CaseInsensitive ( Borrowed ( header_name :: < H > ( ) ) ) ,
143
- RWLock :: new ( Item :: typed ( box value as Box < HeaderFormat + Send + Sync > ) ) ) ;
143
+ MuCell :: new ( Item :: typed ( box value as Box < HeaderFormat + Send + Sync > ) ) ) ;
144
144
}
145
145
146
146
/// Access the raw value of a header.
@@ -159,15 +159,19 @@ impl Headers {
159
159
// FIXME(reem): Find a better way to do this lookup without find_equiv.
160
160
. get ( & CaseInsensitive ( Borrowed ( unsafe { mem:: transmute :: < & str , & str > ( name) } ) ) )
161
161
. and_then ( |item| {
162
- let lock = item. read ( ) ;
163
- if let Some ( ref raw) = lock. raw {
162
+ if let Some ( ref raw) = item. borrow ( ) . raw {
164
163
return unsafe { mem:: transmute ( Some ( raw[ ] ) ) } ;
165
164
}
166
165
167
- let mut lock = item. write ( ) ;
168
- let raw = vec ! [ lock. typed. as_ref( ) . unwrap( ) . to_string( ) . into_bytes( ) ] ;
169
- lock. raw = Some ( raw) ;
170
- unsafe { mem:: transmute ( Some ( lock. raw . as_ref ( ) . unwrap ( ) [ ] ) ) }
166
+ let worked = item. try_mutate ( |item| {
167
+ let raw = vec ! [ item. typed. as_ref( ) . unwrap( ) . to_string( ) . into_bytes( ) ] ;
168
+ item. raw = Some ( raw) ;
169
+ } ) ;
170
+ debug_assert ! ( worked, "item.try_mutate should return true" ) ;
171
+
172
+ let item = item. borrow ( ) ;
173
+ let raw = item. raw . as_ref ( ) . unwrap ( ) ;
174
+ unsafe { mem:: transmute ( Some ( raw[ ] ) ) }
171
175
} )
172
176
}
173
177
@@ -181,29 +185,31 @@ impl Headers {
181
185
/// headers.set_raw("content-length", vec!["5".as_bytes().to_vec()]);
182
186
/// ```
183
187
pub fn set_raw < K : IntoCow < ' static , String , str > > ( & mut self , name : K , value : Vec < Vec < u8 > > ) {
184
- self . data . insert ( CaseInsensitive ( name. into_cow ( ) ) , RWLock :: new ( Item :: raw ( value) ) ) ;
188
+ self . data . insert ( CaseInsensitive ( name. into_cow ( ) ) , MuCell :: new ( Item :: raw ( value) ) ) ;
185
189
}
186
190
187
191
/// Get a reference to the header field's value, if it exists.
188
192
pub fn get < H : Header + HeaderFormat > ( & self ) -> Option < & H > {
189
193
self . get_or_parse :: < H > ( ) . map ( |item| {
190
194
unsafe {
191
- mem:: transmute :: < & H , & H > ( downcast ( & * item. read ( ) ) )
195
+ mem:: transmute :: < & H , & H > ( downcast ( & * item. borrow ( ) ) )
192
196
}
193
197
} )
194
198
}
195
199
196
200
/// Get a mutable reference to the header field's value, if it exists.
197
201
pub fn get_mut < H : Header + HeaderFormat > ( & mut self ) -> Option < & mut H > {
198
- self . get_or_parse :: < H > ( ) . map ( |item| {
199
- unsafe {
200
- mem:: transmute :: < & mut H , & mut H > ( downcast_mut ( & mut * item. write ( ) ) )
201
- }
202
+ self . get_or_parse_mut :: < H > ( ) . map ( |item| {
203
+ unsafe { downcast_mut ( item. borrow_mut ( ) ) }
202
204
} )
203
205
}
204
206
205
- fn get_or_parse < H : Header + HeaderFormat > ( & self ) -> Option < & RWLock < Item > > {
206
- self . data . get ( & CaseInsensitive ( Borrowed ( header_name :: < H > ( ) ) ) ) . and_then ( |item| get_or_parse :: < H > ( item) )
207
+ fn get_or_parse < H : Header + HeaderFormat > ( & self ) -> Option < & MuCell < Item > > {
208
+ self . data . get ( & CaseInsensitive ( Borrowed ( header_name :: < H > ( ) ) ) ) . and_then ( get_or_parse :: < H > )
209
+ }
210
+
211
+ fn get_or_parse_mut < H : Header + HeaderFormat > ( & mut self ) -> Option < & mut MuCell < Item > > {
212
+ self . data . get_mut ( & CaseInsensitive ( Borrowed ( header_name :: < H > ( ) ) ) ) . and_then ( get_or_parse_mut :: < H > )
207
213
}
208
214
209
215
/// Returns a boolean of whether a certain header is in the map.
@@ -255,7 +261,7 @@ impl fmt::Show for Headers {
255
261
256
262
/// An `Iterator` over the fields in a `Headers` map.
257
263
pub struct HeadersItems < ' a > {
258
- inner : Entries < ' a , CaseInsensitive , RWLock < Item > >
264
+ inner : Entries < ' a , CaseInsensitive , MuCell < Item > >
259
265
}
260
266
261
267
impl < ' a > Iterator < HeaderView < ' a > > for HeadersItems < ' a > {
@@ -268,7 +274,7 @@ impl<'a> Iterator<HeaderView<'a>> for HeadersItems<'a> {
268
274
}
269
275
270
276
/// Returned with the `HeadersItems` iterator.
271
- pub struct HeaderView < ' a > ( & ' a CaseInsensitive , & ' a RWLock < Item > ) ;
277
+ pub struct HeaderView < ' a > ( & ' a CaseInsensitive , & ' a MuCell < Item > ) ;
272
278
273
279
impl < ' a > HeaderView < ' a > {
274
280
/// Check if a HeaderView is a certain Header.
@@ -288,21 +294,21 @@ impl<'a> HeaderView<'a> {
288
294
pub fn value < H : Header + HeaderFormat > ( & self ) -> Option < & ' a H > {
289
295
get_or_parse :: < H > ( self . 1 ) . map ( |item| {
290
296
unsafe {
291
- mem:: transmute :: < & H , & H > ( downcast ( & * item. read ( ) ) )
297
+ mem:: transmute :: < & H , & H > ( downcast ( & * item. borrow ( ) ) )
292
298
}
293
299
} )
294
300
}
295
301
296
302
/// Get just the header value as a String.
297
303
#[ inline]
298
304
pub fn value_string ( & self ) -> String {
299
- ( * self . 1 . read ( ) ) . to_string ( )
305
+ ( * self . 1 . borrow ( ) ) . to_string ( )
300
306
}
301
307
}
302
308
303
309
impl < ' a > fmt:: Show for HeaderView < ' a > {
304
310
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
305
- write ! ( f, "{}: {}" , self . 0 , * self . 1 . read ( ) )
311
+ write ! ( f, "{}: {}" , self . 0 , * self . 1 . borrow ( ) )
306
312
}
307
313
}
308
314
@@ -345,8 +351,8 @@ impl Item {
345
351
346
352
}
347
353
348
- fn get_or_parse < H : Header + HeaderFormat > ( item : & RWLock < Item > ) -> Option < & RWLock < Item > > {
349
- match item. read ( ) . typed {
354
+ fn get_or_parse < H : Header + HeaderFormat > ( item : & MuCell < Item > ) -> Option < & MuCell < Item > > {
355
+ match item. borrow ( ) . typed {
350
356
Some ( ref typed) if typed. is :: < H > ( ) => return Some ( item) ,
351
357
Some ( ref typed) => {
352
358
warn ! ( "attempted to access {} as wrong type" , typed) ;
@@ -355,53 +361,55 @@ fn get_or_parse<H: Header + HeaderFormat>(item: &RWLock<Item>) -> Option<&RWLock
355
361
_ => ( )
356
362
}
357
363
358
- // Take out a write lock to do the parsing and mutation.
359
- let mut write = item . write ( ) ;
360
-
361
- // Since this lock can queue, it's possible another thread just
362
- // did the work for us.
363
- match write . typed {
364
- // Check they inserted the correct type and move on.
365
- Some ( ref typed ) if typed . is :: < H > ( ) => return Some ( item ) ,
364
+ let worked = item . try_mutate ( parse :: < H > ) ;
365
+ debug_assert ! ( worked , "item.try_mutate should return true" ) ;
366
+ if item . borrow ( ) . typed . is_some ( ) {
367
+ Some ( item )
368
+ } else {
369
+ None
370
+ }
371
+ }
366
372
367
- // Wrong type, another thread got here before us and parsed
368
- // as a different representation.
373
+ fn get_or_parse_mut < H : Header + HeaderFormat > ( item : & mut MuCell < Item > ) -> Option < & mut MuCell < Item > > {
374
+ let is_correct_type = match item. borrow ( ) . typed {
375
+ Some ( ref typed) if typed. is :: < H > ( ) => Some ( true ) ,
369
376
Some ( ref typed) => {
370
- debug ! ( "other thread was here first?" )
371
377
warn ! ( "attempted to access {} as wrong type" , typed) ;
372
- return None ;
373
- } ,
378
+ Some ( false )
379
+ }
380
+ _ => None
381
+ } ;
374
382
375
- // We are first in the queue or the only ones, so do the actual
376
- // work of parsing and mutation.
377
- _ => ( )
383
+ match is_correct_type {
384
+ Some ( true ) => return Some ( item) ,
385
+ Some ( false ) => return None ,
386
+ None => ( )
387
+ }
388
+
389
+ parse :: < H > ( item. borrow_mut ( ) ) ;
390
+ if item. borrow ( ) . typed . is_some ( ) {
391
+ Some ( item)
392
+ } else {
393
+ None
378
394
}
395
+ }
379
396
380
- let header = match write. raw {
397
+ fn parse < H : Header + HeaderFormat > ( item : & mut Item ) {
398
+ item. typed = match item. raw {
381
399
Some ( ref raw) => match Header :: parse_header ( raw[ ] ) {
382
- Some :: < H > ( h) => h ,
383
- None => return None
400
+ Some :: < H > ( h) => Some ( box h as Box < HeaderFormat + Send + Sync > ) ,
401
+ None => None
384
402
} ,
385
403
None => unreachable ! ( )
386
404
} ;
387
-
388
- // Mutate!
389
- write. typed = Some ( box header as Box < HeaderFormat + Send + Sync > ) ;
390
- Some ( item)
391
405
}
392
406
393
- fn downcast < H : Header + HeaderFormat > ( read : & Item ) -> & H {
394
- match read. typed {
395
- Some ( ref val) => unsafe { val. downcast_ref_unchecked ( ) } ,
396
- _ => unreachable ! ( )
397
- }
407
+ unsafe fn downcast < H : Header + HeaderFormat > ( item : & Item ) -> & H {
408
+ item. typed . as_ref ( ) . expect ( "item.typed must be set" ) . downcast_ref_unchecked ( )
398
409
}
399
410
400
- fn downcast_mut < H : Header + HeaderFormat > ( write : & mut Item ) -> & mut H {
401
- match write. typed {
402
- Some ( ref mut val) => unsafe { val. downcast_mut_unchecked ( ) } ,
403
- _ => unreachable ! ( )
404
- }
411
+ unsafe fn downcast_mut < H : Header + HeaderFormat > ( item : & mut Item ) -> & mut H {
412
+ item. typed . as_mut ( ) . expect ( "item.typed must be set" ) . downcast_mut_unchecked ( )
405
413
}
406
414
407
415
impl fmt:: Show for Item {
@@ -421,12 +429,6 @@ impl fmt::Show for Item {
421
429
}
422
430
}
423
431
424
- impl Clone for RWLock < Item > {
425
- fn clone ( & self ) -> RWLock < Item > {
426
- RWLock :: new ( self . read ( ) . clone ( ) )
427
- }
428
- }
429
-
430
432
impl fmt:: Show for Box < HeaderFormat + Send + Sync > {
431
433
fn fmt ( & self , fmt : & mut fmt:: Formatter ) -> fmt:: Result {
432
434
( * * self ) . fmt_header ( fmt)
@@ -659,6 +661,32 @@ mod tests {
659
661
}
660
662
}
661
663
664
+ #[ bench]
665
+ fn bench_header_get ( b : & mut Bencher ) {
666
+ let mut headers = Headers :: new ( ) ;
667
+ headers. set ( ContentLength ( 11 ) ) ;
668
+ b. iter ( || assert_eq ! ( headers. get:: <ContentLength >( ) , Some ( & ContentLength ( 11 ) ) ) )
669
+ }
670
+
671
+ #[ bench]
672
+ fn bench_header_get_miss ( b : & mut Bencher ) {
673
+ let headers = Headers :: new ( ) ;
674
+ b. iter ( || assert ! ( headers. get:: <ContentLength >( ) . is_none( ) ) )
675
+ }
676
+
677
+ #[ bench]
678
+ fn bench_header_set ( b : & mut Bencher ) {
679
+ let mut headers = Headers :: new ( ) ;
680
+ b. iter ( || headers. set ( ContentLength ( 12 ) ) )
681
+ }
682
+
683
+ #[ bench]
684
+ fn bench_header_has ( b : & mut Bencher ) {
685
+ let mut headers = Headers :: new ( ) ;
686
+ headers. set ( ContentLength ( 11 ) ) ;
687
+ b. iter ( || assert ! ( headers. has:: <ContentLength >( ) ) )
688
+ }
689
+
662
690
#[ bench]
663
691
fn bench_header_view_is ( b : & mut Bencher ) {
664
692
let mut headers = Headers :: new ( ) ;
0 commit comments