@@ -199,9 +199,9 @@ impl<T> Channel<T> {
199
199
#[ repr( C ) ]
200
200
struct ChannelSource < T , F : FnMut ( T ) -> Continue + ' static > {
201
201
source : ffi:: GSource ,
202
- source_funcs : Option < Box < ffi:: GSourceFuncs > > ,
203
- channel : Option < Channel < T > > ,
204
- callback : Option < ThreadGuard < F > > ,
202
+ source_funcs : Box < ffi:: GSourceFuncs > ,
203
+ channel : Channel < T > ,
204
+ callback : ThreadGuard < F > ,
205
205
}
206
206
207
207
unsafe extern "C" fn dispatch < T , F : FnMut ( T ) -> Continue + ' static > (
@@ -218,21 +218,13 @@ unsafe extern "C" fn dispatch<T, F: FnMut(T) -> Continue + 'static>(
218
218
219
219
// Get a reference to the callback. This will panic if we're called from a different
220
220
// thread than where the source was attached to the main context.
221
- let callback = source
222
- . callback
223
- . as_mut ( )
224
- . expect ( "ChannelSource called before Receiver was attached" )
225
- . get_mut ( ) ;
221
+ let callback = source. callback . get_mut ( ) ;
226
222
227
223
// Now iterate over all items that we currently have in the channel until it is
228
224
// empty again. If all senders are disconnected at some point we remove the GSource
229
225
// from the main context it was attached to as it will never ever be called again.
230
- let channel = source
231
- . channel
232
- . as_ref ( )
233
- . expect ( "ChannelSource without Channel" ) ;
234
226
loop {
235
- match channel. try_recv ( ) {
227
+ match source . channel . try_recv ( ) {
236
228
Err ( mpsc:: TryRecvError :: Empty ) => break ,
237
229
Err ( mpsc:: TryRecvError :: Disconnected ) => return ffi:: G_SOURCE_REMOVE ,
238
230
Ok ( item) => {
@@ -250,14 +242,12 @@ unsafe extern "C" fn dispatch<T, F: FnMut(T) -> Continue + 'static>(
250
242
unsafe extern "C" fn dispose < T , F : FnMut ( T ) -> Continue + ' static > ( source : * mut ffi:: GSource ) {
251
243
let source = & mut * ( source as * mut ChannelSource < T , F > ) ;
252
244
253
- if let Some ( ref channel) = source. channel {
254
- // Set the source inside the channel to None so that all senders know that there
255
- // is no receiver left and wake up the condition variable if any
256
- let mut inner = ( channel. 0 ) . 0 . lock ( ) . unwrap ( ) ;
257
- inner. source = ChannelSourceState :: Destroyed ;
258
- if let Some ( ChannelBound { ref cond, .. } ) = ( channel. 0 ) . 1 {
259
- cond. notify_all ( ) ;
260
- }
245
+ // Set the source inside the channel to None so that all senders know that there
246
+ // is no receiver left and wake up the condition variable if any
247
+ let mut inner = ( source. channel . 0 ) . 0 . lock ( ) . unwrap ( ) ;
248
+ inner. source = ChannelSourceState :: Destroyed ;
249
+ if let Some ( ChannelBound { ref cond, .. } ) = ( source. channel . 0 ) . 1 {
250
+ cond. notify_all ( ) ;
261
251
}
262
252
}
263
253
@@ -266,14 +256,8 @@ unsafe extern "C" fn finalize<T, F: FnMut(T) -> Continue + 'static>(source: *mut
266
256
267
257
// Drop all memory we own by taking it out of the Options
268
258
269
- #[ cfg( feature = "v2_64" ) ]
270
- {
271
- let _ = source. channel . take ( ) . expect ( "Receiver without channel" ) ;
272
- }
273
259
#[ cfg( not( feature = "v2_64" ) ) ]
274
260
{
275
- let channel = source. channel . take ( ) . expect ( "Receiver without channel" ) ;
276
-
277
261
// FIXME: This is the same as would otherwise be done in the dispose() function but
278
262
// unfortunately it doesn't exist in older version of GLib. Doing it only here can
279
263
// cause a channel sender to get a reference to the source with reference count 0
@@ -283,14 +267,14 @@ unsafe extern "C" fn finalize<T, F: FnMut(T) -> Continue + 'static>(source: *mut
283
267
//
284
268
// Set the source inside the channel to None so that all senders know that there
285
269
// is no receiver left and wake up the condition variable if any
286
- let mut inner = ( channel. 0 ) . 0 . lock ( ) . unwrap ( ) ;
270
+ let mut inner = ( source . channel . 0 ) . 0 . lock ( ) . unwrap ( ) ;
287
271
inner. source = ChannelSourceState :: Destroyed ;
288
- if let Some ( ChannelBound { ref cond, .. } ) = ( channel. 0 ) . 1 {
272
+ if let Some ( ChannelBound { ref cond, .. } ) = ( source . channel . 0 ) . 1 {
289
273
cond. notify_all ( ) ;
290
274
}
291
275
}
292
-
293
- let _ = source. source_funcs . take ( ) ;
276
+ ptr :: drop_in_place ( & mut source . channel ) ;
277
+ ptr :: drop_in_place ( & mut source. source_funcs ) ;
294
278
295
279
// Take the callback out of the source. This will panic if the value is dropped
296
280
// from a different thread than where the callback was created so try to drop it
@@ -299,11 +283,10 @@ unsafe extern "C" fn finalize<T, F: FnMut(T) -> Continue + 'static>(source: *mut
299
283
// This can only really happen if the caller to `attach()` gets the `Source` from the returned
300
284
// `SourceId` and sends it to another thread or otherwise retrieves it from the main context,
301
285
// but better safe than sorry.
302
- let callback = source
303
- . callback
304
- . take ( )
305
- . expect ( "channel source finalized twice" ) ;
306
- if !callback. is_owner ( ) {
286
+ if source. callback . is_owner ( ) {
287
+ ptr:: drop_in_place ( & mut source. callback ) ;
288
+ } else {
289
+ let callback = ptr:: read ( & source. callback ) ;
307
290
let context =
308
291
ffi:: g_source_get_context ( source as * mut ChannelSource < T , F > as * mut ffi:: GSource ) ;
309
292
if !context. is_null ( ) {
@@ -522,9 +505,9 @@ impl<T> Receiver<T> {
522
505
// Store all our data inside our part of the GSource
523
506
{
524
507
let source = & mut * source;
525
- ptr:: write ( & mut source. channel , Some ( channel) ) ;
526
- ptr:: write ( & mut source. callback , Some ( ThreadGuard :: new ( func) ) ) ;
527
- ptr:: write ( & mut source. source_funcs , Some ( source_funcs) ) ;
508
+ ptr:: write ( ptr :: addr_of_mut! ( source. channel) , channel) ;
509
+ ptr:: write ( ptr :: addr_of_mut! ( source. callback) , ThreadGuard :: new ( func) ) ;
510
+ ptr:: write ( ptr :: addr_of_mut! ( source. source_funcs) , source_funcs) ;
528
511
}
529
512
530
513
let source = Source :: from_glib_full ( mut_override ( & ( * source) . source ) ) ;
0 commit comments