@@ -13,7 +13,7 @@ use core::borrow;
13
13
use core:: fmt;
14
14
use core:: cmp:: { self , Ordering } ;
15
15
use core:: intrinsics:: abort;
16
- use core:: mem:: { self , align_of_val, size_of_val} ;
16
+ use core:: mem:: { self , align_of , align_of_val, size_of_val} ;
17
17
use core:: ops:: { Deref , Receiver , CoerceUnsized , DispatchFromDyn } ;
18
18
use core:: pin:: Pin ;
19
19
use core:: ptr:: { self , NonNull } ;
@@ -397,11 +397,7 @@ impl<T: ?Sized> Arc<T> {
397
397
/// ```
398
398
#[ stable( feature = "rc_raw" , since = "1.17.0" ) ]
399
399
pub unsafe fn from_raw ( ptr : * const T ) -> Self {
400
- // Align the unsized value to the end of the ArcInner.
401
- // Because it is ?Sized, it will always be the last field in memory.
402
- let align = align_of_val ( & * ptr) ;
403
- let layout = Layout :: new :: < ArcInner < ( ) > > ( ) ;
404
- let offset = ( layout. size ( ) + layout. padding_needed_for ( align) ) as isize ;
400
+ let offset = data_offset ( ptr) ;
405
401
406
402
// Reverse the offset to find the original ArcInner.
407
403
let fake_ptr = ptr as * mut ArcInner < T > ;
@@ -1071,6 +1067,144 @@ impl<T> Weak<T> {
1071
1067
ptr : NonNull :: new ( usize:: MAX as * mut ArcInner < T > ) . expect ( "MAX is not 0" ) ,
1072
1068
}
1073
1069
}
1070
+
1071
+ /// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
1072
+ ///
1073
+ /// It is up to the caller to ensure that the object is still alive when accessing it through
1074
+ /// the pointer.
1075
+ ///
1076
+ /// The pointer may be [`null`] or be dangling in case the object has already been destroyed.
1077
+ ///
1078
+ /// # Examples
1079
+ ///
1080
+ /// ```
1081
+ /// #![feature(weak_into_raw)]
1082
+ ///
1083
+ /// use std::sync::{Arc, Weak};
1084
+ /// use std::ptr;
1085
+ ///
1086
+ /// let strong = Arc::new(42);
1087
+ /// let weak = Arc::downgrade(&strong);
1088
+ /// // Both point to the same object
1089
+ /// assert!(ptr::eq(&*strong, Weak::as_raw(&weak)));
1090
+ /// // The strong here keeps it alive, so we can still access the object.
1091
+ /// assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
1092
+ ///
1093
+ /// drop(strong);
1094
+ /// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to
1095
+ /// // undefined behaviour.
1096
+ /// // assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
1097
+ /// ```
1098
+ ///
1099
+ /// [`null`]: ../../std/ptr/fn.null.html
1100
+ #[ unstable( feature = "weak_into_raw" , issue = "60728" ) ]
1101
+ pub fn as_raw ( this : & Self ) -> * const T {
1102
+ match this. inner ( ) {
1103
+ None => ptr:: null ( ) ,
1104
+ Some ( inner) => {
1105
+ let offset = data_offset_sized :: < T > ( ) ;
1106
+ let ptr = inner as * const ArcInner < T > ;
1107
+ // Note: while the pointer we create may already point to dropped value, the
1108
+ // allocation still lives (it must hold the weak point as long as we are alive).
1109
+ // Therefore, the offset is OK to do, it won't get out of the allocation.
1110
+ let ptr = unsafe { ( ptr as * const u8 ) . offset ( offset) } ;
1111
+ ptr as * const T
1112
+ }
1113
+ }
1114
+ }
1115
+
1116
+ /// Consumes the `Weak<T>` and turns it into a raw pointer.
1117
+ ///
1118
+ /// This converts the weak pointer into a raw pointer, preserving the original weak count. It
1119
+ /// can be turned back into the `Weak<T>` with [`from_raw`].
1120
+ ///
1121
+ /// The same restrictions of accessing the target of the pointer as with
1122
+ /// [`as_raw`] apply.
1123
+ ///
1124
+ /// # Examples
1125
+ ///
1126
+ /// ```
1127
+ /// #![feature(weak_into_raw)]
1128
+ ///
1129
+ /// use std::sync::{Arc, Weak};
1130
+ ///
1131
+ /// let strong = Arc::new(42);
1132
+ /// let weak = Arc::downgrade(&strong);
1133
+ /// let raw = Weak::into_raw(weak);
1134
+ ///
1135
+ /// assert_eq!(1, Arc::weak_count(&strong));
1136
+ /// assert_eq!(42, unsafe { *raw });
1137
+ ///
1138
+ /// drop(unsafe { Weak::from_raw(raw) });
1139
+ /// assert_eq!(0, Arc::weak_count(&strong));
1140
+ /// ```
1141
+ ///
1142
+ /// [`from_raw`]: struct.Weak.html#method.from_raw
1143
+ /// [`as_raw`]: struct.Weak.html#method.as_raw
1144
+ #[ unstable( feature = "weak_into_raw" , issue = "60728" ) ]
1145
+ pub fn into_raw ( this : Self ) -> * const T {
1146
+ let result = Self :: as_raw ( & this) ;
1147
+ mem:: forget ( this) ;
1148
+ result
1149
+ }
1150
+
1151
+ /// Converts a raw pointer previously created by [`into_raw`] back into
1152
+ /// `Weak<T>`.
1153
+ ///
1154
+ /// This can be used to safely get a strong reference (by calling [`upgrade`]
1155
+ /// later) or to deallocate the weak count by dropping the `Weak<T>`.
1156
+ ///
1157
+ /// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is
1158
+ /// returned.
1159
+ ///
1160
+ /// # Safety
1161
+ ///
1162
+ /// The pointer must represent one valid weak count. In other words, it must point to `T` which
1163
+ /// is or *was* managed by an [`Arc`] and the weak count of that [`Arc`] must not have reached
1164
+ /// 0. It is allowed for the strong count to be 0.
1165
+ ///
1166
+ /// # Examples
1167
+ ///
1168
+ /// ```
1169
+ /// #![feature(weak_into_raw)]
1170
+ ///
1171
+ /// use std::sync::{Arc, Weak};
1172
+ ///
1173
+ /// let strong = Arc::new(42);
1174
+ ///
1175
+ /// let raw_1 = Weak::into_raw(Arc::downgrade(&strong));
1176
+ /// let raw_2 = Weak::into_raw(Arc::downgrade(&strong));
1177
+ ///
1178
+ /// assert_eq!(2, Arc::weak_count(&strong));
1179
+ ///
1180
+ /// assert_eq!(42, *Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap());
1181
+ /// assert_eq!(1, Arc::weak_count(&strong));
1182
+ ///
1183
+ /// drop(strong);
1184
+ ///
1185
+ /// // Decrement the last weak count.
1186
+ /// assert!(Weak::upgrade(&unsafe { Weak::from_raw(raw_2) }).is_none());
1187
+ /// ```
1188
+ ///
1189
+ /// [`null`]: ../../std/ptr/fn.null.html
1190
+ /// [`into_raw`]: struct.Weak.html#method.into_raw
1191
+ /// [`upgrade`]: struct.Weak.html#method.upgrade
1192
+ /// [`Weak`]: struct.Weak.html
1193
+ /// [`Arc`]: struct.Arc.html
1194
+ #[ unstable( feature = "weak_into_raw" , issue = "60728" ) ]
1195
+ pub unsafe fn from_raw ( ptr : * const T ) -> Self {
1196
+ if ptr. is_null ( ) {
1197
+ Self :: new ( )
1198
+ } else {
1199
+ // See Arc::from_raw for details
1200
+ let offset = data_offset ( ptr) ;
1201
+ let fake_ptr = ptr as * mut ArcInner < T > ;
1202
+ let ptr = set_data_ptr ( fake_ptr, ( ptr as * mut u8 ) . offset ( -offset) ) ;
1203
+ Weak {
1204
+ ptr : NonNull :: new ( ptr) . expect ( "Invalid pointer passed to from_raw" ) ,
1205
+ }
1206
+ }
1207
+ }
1074
1208
}
1075
1209
1076
1210
impl < T : ?Sized > Weak < T > {
@@ -2150,3 +2284,21 @@ impl<T: ?Sized> AsRef<T> for Arc<T> {
2150
2284
2151
2285
#[ stable( feature = "pin" , since = "1.33.0" ) ]
2152
2286
impl < T : ?Sized > Unpin for Arc < T > { }
2287
+
2288
+ /// Computes the offset of the data field within ArcInner.
2289
+ unsafe fn data_offset < T : ?Sized > ( ptr : * const T ) -> isize {
2290
+ // Align the unsized value to the end of the ArcInner.
2291
+ // Because it is ?Sized, it will always be the last field in memory.
2292
+ let align = align_of_val ( & * ptr) ;
2293
+ let layout = Layout :: new :: < ArcInner < ( ) > > ( ) ;
2294
+ ( layout. size ( ) + layout. padding_needed_for ( align) ) as isize
2295
+ }
2296
+
2297
+ /// Computes the offset of the data field within ArcInner.
2298
+ ///
2299
+ /// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
2300
+ fn data_offset_sized < T > ( ) -> isize {
2301
+ let align = align_of :: < T > ( ) ;
2302
+ let layout = Layout :: new :: < ArcInner < ( ) > > ( ) ;
2303
+ ( layout. size ( ) + layout. padding_needed_for ( align) ) as isize
2304
+ }
0 commit comments