@@ -570,20 +570,31 @@ impl Display for BorrowMutError {
570
570
}
571
571
}
572
572
573
- // Values [1, MIN_WRITING-1] represent the number of `Ref` active. Values in
574
- // [MIN_WRITING, MAX-1] represent the number of `RefMut` active. Multiple
575
- // `RefMut`s can only be active at a time if they refer to distinct,
576
- // nonoverlapping components of a `RefCell` (e.g., different ranges of a slice).
573
+ // Positive values represent the number of `Ref` active. Negative values
574
+ // represent the number of `RefMut` active. Multiple `RefMut`s can only be
575
+ // active at a time if they refer to distinct, nonoverlapping components of a
576
+ // `RefCell` (e.g., different ranges of a slice).
577
577
//
578
578
// `Ref` and `RefMut` are both two words in size, and so there will likely never
579
579
// be enough `Ref`s or `RefMut`s in existence to overflow half of the `usize`
580
- // range. Thus, a `BorrowFlag` will probably never overflow. However, this is
581
- // not a guarantee, as a pathological program could repeatedly create and then
582
- // mem::forget `Ref`s or `RefMut`s. Thus, all code must explicitly check for
583
- // overflow in order to avoid unsafety.
584
- type BorrowFlag = usize ;
580
+ // range. Thus, a `BorrowFlag` will probably never overflow or underflow.
581
+ // However, this is not a guarantee, as a pathological program could repeatedly
582
+ // create and then mem::forget `Ref`s or `RefMut`s. Thus, all code must
583
+ // explicitly check for overflow and underflow in order to avoid unsafety, or at
584
+ // least behave correctly in the event that overflow or underflow happens (e.g.,
585
+ // see BorrowRef::new).
586
+ type BorrowFlag = isize ;
585
587
const UNUSED : BorrowFlag = 0 ;
586
- const MIN_WRITING : BorrowFlag = ( !0 ) /2 + 1 ; // 0b1000...
588
+
589
+ #[ inline( always) ]
590
+ fn is_writing ( x : BorrowFlag ) -> bool {
591
+ x < UNUSED
592
+ }
593
+
594
+ #[ inline( always) ]
595
+ fn is_reading ( x : BorrowFlag ) -> bool {
596
+ x > UNUSED
597
+ }
587
598
588
599
impl < T > RefCell < T > {
589
600
/// Creates a new `RefCell` containing `value`.
@@ -1022,12 +1033,11 @@ impl<'b> BorrowRef<'b> {
1022
1033
#[ inline]
1023
1034
fn new ( borrow : & ' b Cell < BorrowFlag > ) -> Option < BorrowRef < ' b > > {
1024
1035
let b = borrow. get ( ) ;
1025
- if b >= MIN_WRITING {
1036
+ if is_writing ( b) || b == isize:: max_value ( ) {
1037
+ // If there's currently a writing borrow, or if incrementing the
1038
+ // refcount would overflow into a writing borrow.
1026
1039
None
1027
1040
} else {
1028
- // Prevent the borrow counter from overflowing into
1029
- // a writing borrow.
1030
- assert ! ( b < MIN_WRITING - 1 ) ;
1031
1041
borrow. set ( b + 1 ) ;
1032
1042
Some ( BorrowRef { borrow } )
1033
1043
}
@@ -1038,7 +1048,7 @@ impl<'b> Drop for BorrowRef<'b> {
1038
1048
#[ inline]
1039
1049
fn drop ( & mut self ) {
1040
1050
let borrow = self . borrow . get ( ) ;
1041
- debug_assert ! ( borrow < MIN_WRITING && borrow != UNUSED ) ;
1051
+ debug_assert ! ( is_reading ( borrow) ) ;
1042
1052
self . borrow . set ( borrow - 1 ) ;
1043
1053
}
1044
1054
}
@@ -1047,12 +1057,12 @@ impl<'b> Clone for BorrowRef<'b> {
1047
1057
#[ inline]
1048
1058
fn clone ( & self ) -> BorrowRef < ' b > {
1049
1059
// Since this Ref exists, we know the borrow flag
1050
- // is not set to WRITING .
1060
+ // is a reading borrow .
1051
1061
let borrow = self . borrow . get ( ) ;
1052
- debug_assert ! ( borrow != UNUSED ) ;
1062
+ debug_assert ! ( is_reading ( borrow) ) ;
1053
1063
// Prevent the borrow counter from overflowing into
1054
1064
// a writing borrow.
1055
- assert ! ( borrow < MIN_WRITING - 1 ) ;
1065
+ assert ! ( borrow != isize :: max_value ( ) ) ;
1056
1066
self . borrow . set ( borrow + 1 ) ;
1057
1067
BorrowRef { borrow : self . borrow }
1058
1068
}
@@ -1251,12 +1261,8 @@ impl<'b> Drop for BorrowRefMut<'b> {
1251
1261
#[ inline]
1252
1262
fn drop ( & mut self ) {
1253
1263
let borrow = self . borrow . get ( ) ;
1254
- debug_assert ! ( borrow >= MIN_WRITING ) ;
1255
- self . borrow . set ( if borrow == MIN_WRITING {
1256
- UNUSED
1257
- } else {
1258
- borrow - 1
1259
- } ) ;
1264
+ debug_assert ! ( is_writing( borrow) ) ;
1265
+ self . borrow . set ( borrow + 1 ) ;
1260
1266
}
1261
1267
}
1262
1268
@@ -1266,10 +1272,10 @@ impl<'b> BorrowRefMut<'b> {
1266
1272
// NOTE: Unlike BorrowRefMut::clone, new is called to create the initial
1267
1273
// mutable reference, and so there must currently be no existing
1268
1274
// references. Thus, while clone increments the mutable refcount, here
1269
- // we simply go directly from UNUSED to MIN_WRITING .
1275
+ // we explicitly only allow going from UNUSED to UNUSED - 1 .
1270
1276
match borrow. get ( ) {
1271
1277
UNUSED => {
1272
- borrow. set ( MIN_WRITING ) ;
1278
+ borrow. set ( UNUSED - 1 ) ;
1273
1279
Some ( BorrowRefMut { borrow : borrow } )
1274
1280
} ,
1275
1281
_ => None ,
@@ -1284,10 +1290,10 @@ impl<'b> BorrowRefMut<'b> {
1284
1290
#[ inline]
1285
1291
fn clone ( & self ) -> BorrowRefMut < ' b > {
1286
1292
let borrow = self . borrow . get ( ) ;
1287
- debug_assert ! ( borrow >= MIN_WRITING ) ;
1288
- // Prevent the borrow counter from overflowing .
1289
- assert ! ( borrow != ! 0 ) ;
1290
- self . borrow . set ( borrow + 1 ) ;
1293
+ debug_assert ! ( is_writing ( borrow) ) ;
1294
+ // Prevent the borrow counter from underflowing .
1295
+ assert ! ( borrow != isize :: min_value ( ) ) ;
1296
+ self . borrow . set ( borrow - 1 ) ;
1291
1297
BorrowRefMut { borrow : self . borrow }
1292
1298
}
1293
1299
}
0 commit comments