@@ -156,6 +156,8 @@ pub(crate) struct SessionState {
156
156
pub ( crate ) aggregated_subscribers : Vec < OwnedKeyExpr > ,
157
157
pub ( crate ) aggregated_publishers : Vec < OwnedKeyExpr > ,
158
158
pub ( crate ) publisher_qos_tree : KeBoxTree < PublisherQoSConfig > ,
159
+ #[ cfg( feature = "unstable" ) ]
160
+ pub ( crate ) closing_callbacks : ClosingCallbackList ,
159
161
}
160
162
161
163
impl SessionState {
@@ -190,6 +192,8 @@ impl SessionState {
190
192
aggregated_subscribers,
191
193
aggregated_publishers,
192
194
publisher_qos_tree,
195
+ #[ cfg( feature = "unstable" ) ]
196
+ closing_callbacks : Default :: default ( ) ,
193
197
}
194
198
}
195
199
}
@@ -1249,6 +1253,61 @@ impl Session {
1249
1253
source_info : SourceInfo :: empty ( ) ,
1250
1254
}
1251
1255
}
1256
+
1257
+ /// Registers a closing callback to the session.
1258
+ ///
1259
+ /// The callback will be called when the session will be closed. It returns an id to unregister
1260
+ /// the callback with [`unregister_closing_callback`](Self::unregister_closing_callback). If
1261
+ /// the session is already closed, the callback is returned in an error.
1262
+ ///
1263
+ /// # Examples
1264
+ ///
1265
+ /// ```rust
1266
+ /// # #[tokio::main]
1267
+ /// # async fn main() {
1268
+ ///
1269
+ /// let session = zenoh::open(zenoh::Config::default()).await.unwrap();
1270
+ /// if let Err(_) = session.register_closing_callback(|| println!("session closed")) {
1271
+ /// println!("session already closed");
1272
+ /// }
1273
+ /// # }
1274
+ /// ```
1275
+ #[ zenoh_macros:: unstable]
1276
+ pub fn register_closing_callback < F : FnOnce ( ) + Send + Sync + ' static > (
1277
+ & self ,
1278
+ callback : F ,
1279
+ ) -> Result < ClosingCallbackId , F > {
1280
+ let mut state = zwrite ! ( self . 0 . state) ;
1281
+ if state. primitives ( ) . is_err ( ) {
1282
+ return Err ( callback) ;
1283
+ }
1284
+ Ok ( state. closing_callbacks . insert_callback ( Box :: new ( callback) ) )
1285
+ }
1286
+
1287
+ /// Unregisters a closing callback.
1288
+ ///
1289
+ /// The callback must have been registered with
1290
+ /// [`register_closing_callback`](Self::register_closing_callback).
1291
+ /// It will no longer be called on session closing.
1292
+ ///
1293
+ /// # Examples
1294
+ ///
1295
+ /// ```rust
1296
+ /// # #[tokio::main]
1297
+ /// # async fn main() {
1298
+ ///
1299
+ /// let session = zenoh::open(zenoh::Config::default()).await.unwrap();
1300
+ /// let Ok(id) = session.register_closing_callback(|| println!("session closed")) else {
1301
+ /// panic!("session already closed");
1302
+ /// };
1303
+ /// session.unregister_closing_callback(id);
1304
+ /// # }
1305
+ /// ```
1306
+ #[ zenoh_macros:: unstable]
1307
+ pub fn unregister_closing_callback < F : FnOnce ( ) > ( & self , callback_id : ClosingCallbackId ) {
1308
+ let mut state = zwrite ! ( self . 0 . state) ;
1309
+ state. closing_callbacks . remove_callback ( callback_id) ;
1310
+ }
1252
1311
}
1253
1312
1254
1313
impl Session {
@@ -3213,6 +3272,7 @@ impl Closee for Arc<SessionInner> {
3213
3272
// will be stabilized.
3214
3273
let mut state = zwrite ! ( self . state) ;
3215
3274
let _matching_listeners = std:: mem:: take ( & mut state. matching_listeners ) ;
3275
+ state. closing_callbacks . close ( ) ;
3216
3276
drop ( state) ;
3217
3277
}
3218
3278
}
@@ -3225,3 +3285,51 @@ impl Closeable for Session {
3225
3285
self . 0 . clone ( )
3226
3286
}
3227
3287
}
3288
+
3289
+ #[ cfg( feature = "unstable" ) ]
3290
+ #[ derive( Default ) ]
3291
+ pub ( crate ) struct ClosingCallbackList {
3292
+ callbacks : slab:: Slab < ClosingCallback > ,
3293
+ generation : usize ,
3294
+ }
3295
+
3296
+ #[ cfg( feature = "unstable" ) ]
3297
+ impl ClosingCallbackList {
3298
+ fn insert_callback ( & mut self , callback : Box < dyn FnOnce ( ) + Send + Sync > ) -> ClosingCallbackId {
3299
+ let generation = self . generation ;
3300
+ let index = self . callbacks . insert ( ClosingCallback {
3301
+ callback,
3302
+ generation,
3303
+ } ) ;
3304
+ self . generation = self . generation . wrapping_add ( 1 ) ;
3305
+ ClosingCallbackId { index, generation }
3306
+ }
3307
+
3308
+ fn remove_callback ( & mut self , id : ClosingCallbackId ) {
3309
+ if matches ! ( self . callbacks. get( id. index) , Some ( cb) if cb. generation == id. generation) {
3310
+ self . callbacks . remove ( id. index ) ;
3311
+ }
3312
+ }
3313
+
3314
+ fn close ( & mut self ) {
3315
+ for cb in self . callbacks . drain ( ) {
3316
+ ( cb. callback ) ( ) ;
3317
+ }
3318
+ }
3319
+ }
3320
+
3321
+ #[ cfg( feature = "unstable" ) ]
3322
+ struct ClosingCallback {
3323
+ callback : Box < dyn FnOnce ( ) + Send + Sync > ,
3324
+ generation : usize ,
3325
+ }
3326
+
3327
+ /// The id of a registered session closing callback.
3328
+ ///
3329
+ /// See [`Session::register_closing_callback`].
3330
+ #[ zenoh_macros:: unstable]
3331
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
3332
+ pub struct ClosingCallbackId {
3333
+ index : usize ,
3334
+ generation : usize ,
3335
+ }
0 commit comments