12
12
13
13
#[ doc( hidden) ]
14
14
pub mod details {
15
- use std:: { fmt:: Debug , marker:: PhantomData , time:: Duration } ;
15
+ use std:: {
16
+ fmt:: Debug ,
17
+ marker:: PhantomData ,
18
+ sync:: atomic:: { AtomicBool , AtomicUsize , Ordering } ,
19
+ time:: Duration ,
20
+ } ;
16
21
17
22
use iceoryx2_bb_log:: { debug, fail} ;
18
23
use iceoryx2_bb_memory:: bump_allocator:: BumpAllocator ;
@@ -35,9 +40,12 @@ pub mod details {
35
40
const TRIGGER_ID_DEFAULT_MAX : TriggerId = TriggerId :: new ( u16:: MAX as _ ) ;
36
41
37
42
#[ derive( Debug ) ]
43
+ #[ repr( C ) ]
38
44
pub struct Management < Tracker : IdTracker , WaitMechanism : SignalMechanism > {
39
45
id_tracker : Tracker ,
40
46
signal_mechanism : WaitMechanism ,
47
+ reference_counter : AtomicUsize ,
48
+ has_listener : AtomicBool ,
41
49
}
42
50
43
51
#[ derive( Copy , PartialEq , Eq ) ]
@@ -232,6 +240,25 @@ pub mod details {
232
240
_wait_mechanism : PhantomData < WaitMechanism > ,
233
241
}
234
242
243
+ impl <
244
+ Tracker : IdTracker ,
245
+ WaitMechanism : SignalMechanism ,
246
+ Storage : DynamicStorage < Management < Tracker , WaitMechanism > > ,
247
+ > Drop for Notifier < Tracker , WaitMechanism , Storage >
248
+ {
249
+ fn drop ( & mut self ) {
250
+ if self
251
+ . storage
252
+ . get ( )
253
+ . reference_counter
254
+ . fetch_sub ( 1 , Ordering :: Relaxed )
255
+ == 1
256
+ {
257
+ self . storage . acquire_ownership ( ) ;
258
+ }
259
+ }
260
+ }
261
+
235
262
impl <
236
263
Tracker : IdTracker ,
237
264
WaitMechanism : SignalMechanism ,
@@ -254,10 +281,16 @@ pub mod details {
254
281
}
255
282
256
283
fn notify ( & self , id : crate :: event:: TriggerId ) -> Result < ( ) , NotifierNotifyError > {
284
+ let msg = "Failed to notify listener" ;
285
+ if !self . storage . get ( ) . has_listener . load ( Ordering :: Relaxed ) {
286
+ fail ! ( from self , with NotifierNotifyError :: Disconnected ,
287
+ "{} since the listener is no longer connected." , msg) ;
288
+ }
289
+
257
290
if self . storage . get ( ) . id_tracker . trigger_id_max ( ) < id {
258
291
fail ! ( from self , with NotifierNotifyError :: TriggerIdOutOfBounds ,
259
- "Failed to notify since the TriggerId {:?} is greater than the max supported TriggerId {:?}." ,
260
- id, self . storage. get( ) . id_tracker. trigger_id_max( ) ) ;
292
+ "{} since the TriggerId {:?} is greater than the max supported TriggerId {:?}." ,
293
+ msg , id, self . storage. get( ) . id_tracker. trigger_id_max( ) ) ;
261
294
}
262
295
263
296
unsafe { self . storage . get ( ) . id_tracker . add ( id) ? } ;
@@ -326,11 +359,24 @@ pub mod details {
326
359
. timeout ( self . creation_timeout )
327
360
. open ( )
328
361
{
329
- Ok ( storage) => Ok ( Notifier {
330
- storage,
331
- _tracker : PhantomData ,
332
- _wait_mechanism : PhantomData ,
333
- } ) ,
362
+ Ok ( storage) => {
363
+ if !storage. get ( ) . has_listener . load ( Ordering :: Relaxed )
364
+ || storage
365
+ . get ( )
366
+ . reference_counter
367
+ . fetch_add ( 1 , Ordering :: Relaxed )
368
+ == 0
369
+ {
370
+ fail ! ( from self , with NotifierCreateError :: DoesNotExist ,
371
+ "{} since it has no listener and will no longer exist." , msg) ;
372
+ }
373
+
374
+ Ok ( Notifier {
375
+ storage,
376
+ _tracker : PhantomData ,
377
+ _wait_mechanism : PhantomData ,
378
+ } )
379
+ }
334
380
Err ( DynamicStorageOpenError :: DoesNotExist ) => {
335
381
fail ! ( from self , with NotifierCreateError :: DoesNotExist ,
336
382
"{} since it does not exist." , msg) ;
@@ -363,6 +409,30 @@ pub mod details {
363
409
_wait_mechanism : PhantomData < WaitMechanism > ,
364
410
}
365
411
412
+ impl <
413
+ Tracker : IdTracker ,
414
+ WaitMechanism : SignalMechanism ,
415
+ Storage : DynamicStorage < Management < Tracker , WaitMechanism > > ,
416
+ > Drop for Listener < Tracker , WaitMechanism , Storage >
417
+ {
418
+ fn drop ( & mut self ) {
419
+ self . storage
420
+ . get ( )
421
+ . has_listener
422
+ . store ( false , Ordering :: Relaxed ) ;
423
+
424
+ if self
425
+ . storage
426
+ . get ( )
427
+ . reference_counter
428
+ . fetch_sub ( 1 , Ordering :: Relaxed )
429
+ == 1
430
+ {
431
+ self . storage . acquire_ownership ( ) ;
432
+ }
433
+ }
434
+ }
435
+
366
436
impl <
367
437
Tracker : IdTracker ,
368
438
WaitMechanism : SignalMechanism ,
@@ -540,10 +610,12 @@ pub mod details {
540
610
. config ( & self . config . convert ( ) )
541
611
. supplementary_size ( Tracker :: memory_size ( id_tracker_capacity) )
542
612
. initializer ( Self :: init)
543
- . has_ownership ( true )
613
+ . has_ownership ( false )
544
614
. create ( Management {
545
615
id_tracker : unsafe { Tracker :: new_uninit ( id_tracker_capacity) } ,
546
616
signal_mechanism : WaitMechanism :: new ( ) ,
617
+ reference_counter : AtomicUsize :: new ( 1 ) ,
618
+ has_listener : AtomicBool :: new ( true ) ,
547
619
} ) {
548
620
Ok ( storage) => Ok ( Listener {
549
621
storage,
0 commit comments