@@ -272,6 +272,30 @@ impl<T> AtomicOption<T> {
272
272
self . swap ( cast:: transmute ( 0 ) , order)
273
273
}
274
274
}
275
+
276
+ /// A compare-and-swap. Succeeds if the option is 'None' and returns 'None'
277
+ /// if so. If the option was already 'Some', returns 'Some' of the rejected
278
+ /// value.
279
+ #[ inline]
280
+ pub fn fill ( & mut self , val : ~T , order : Ordering ) -> Option < ~T > {
281
+ unsafe {
282
+ let val = cast:: transmute ( val) ;
283
+ let expected = cast:: transmute ( 0 ) ;
284
+ let oldval = atomic_compare_and_swap ( & mut self . p , expected, val, order) ;
285
+ if oldval == expected {
286
+ None
287
+ } else {
288
+ Some ( cast:: transmute ( val) )
289
+ }
290
+ }
291
+ }
292
+
293
+ /// Be careful: The caller must have some external method of ensuring the
294
+ /// result does not get invalidated by another task after this returns.
295
+ #[ inline]
296
+ pub fn is_empty ( & mut self , order : Ordering ) -> bool {
297
+ unsafe { atomic_load ( & self . p , order) == cast:: transmute ( 0 ) }
298
+ }
275
299
}
276
300
277
301
#[ unsafe_destructor]
@@ -374,6 +398,11 @@ mod test {
374
398
assert ! ( !flg. test_and_set( SeqCst ) ) ;
375
399
}
376
400
401
+ #[ test]
402
+ fn option_empty ( ) {
403
+ assert ! ( AtomicOption :: empty:: <( ) >( ) . is_empty( SeqCst ) ) ;
404
+ }
405
+
377
406
#[ test]
378
407
fn option_swap ( ) {
379
408
let mut p = AtomicOption :: new ( ~1 ) ;
@@ -398,4 +427,13 @@ mod test {
398
427
assert_eq ! ( p. take( SeqCst ) , Some ( ~2 ) ) ;
399
428
}
400
429
430
+ #[ test]
431
+ fn option_fill ( ) {
432
+ let mut p = AtomicOption :: new ( ~1 ) ;
433
+ assert ! ( p. fill( ~2 , SeqCst ) . is_some( ) ) ; // should fail; shouldn't leak!
434
+ assert_eq ! ( p. take( SeqCst ) , Some ( ~1 ) ) ;
435
+
436
+ assert ! ( p. fill( ~2 , SeqCst ) . is_none( ) ) ; // shouldn't fail
437
+ assert_eq ! ( p. take( SeqCst ) , Some ( ~2 ) ) ;
438
+ }
401
439
}
0 commit comments