@@ -52,6 +52,14 @@ public sealed class Context : IContext
5252 /// </remarks>
5353 private Dictionary < string , Node > ROSNodes = new Dictionary < string , Node > ( ) ;
5454
55+ /// <summary>
56+ /// Collection of guard conditions active in this context.
57+ /// </summary>
58+ /// <remarks>
59+ /// Also used for synchronisation when creating / removing guard conditions.
60+ /// </remarks>
61+ private HashSet < GuardCondition > GuardConditions = new HashSet < GuardCondition > ( ) ;
62+
5563 /// <summary>
5664 /// Get the current RMW implementation.
5765 /// </summary>
@@ -128,6 +136,41 @@ internal bool RemoveNode(string name)
128136 }
129137 }
130138
139+ /// <summary>
140+ /// Create a guard condition.
141+ /// </summary>
142+ /// <remarks>
143+ /// This method is thread safe.
144+ /// </remarks>
145+ /// <param name="callback"> Callback executed by the executor when the guard condition is triggered. </param>
146+ /// <returns> A new guard condition instance. </returns>
147+ internal GuardCondition CreateGuardCondition ( Action callback )
148+ {
149+ lock ( this . GuardConditions )
150+ {
151+ GuardCondition guardCondition = new GuardCondition ( this , callback ) ;
152+ this . GuardConditions . Add ( guardCondition ) ;
153+ return guardCondition ;
154+ }
155+ }
156+
157+ /// <summary>
158+ /// Remove a guard condition.
159+ /// </summary>
160+ /// <remarks>
161+ /// This method is intended to be used by <see cref="GuardCondition.Dispose"/> and does not dispose the guard condition.
162+ /// Furthermore, it is thread safe.
163+ /// </remarks>
164+ /// <param name="guardCondition"> Guard condition to remove. </param>
165+ /// <returns> If the guard condition existed in this context and has been removed. </returns>
166+ internal bool RemoveGuardCondition ( GuardCondition guardCondition )
167+ {
168+ lock ( this . GuardConditions )
169+ {
170+ return this . GuardConditions . Remove ( guardCondition ) ;
171+ }
172+ }
173+
131174 /// <remarks>
132175 /// This method is not thread safe.
133176 /// Do not call while the context or any entities
@@ -154,7 +197,7 @@ private void Dispose(bool disposing)
154197 {
155198 Utils . CheckReturnEnum ( ret ) ;
156199 }
157- // only continue if ROSNodes has not been finalized
200+ // only continue if ROSNodes and GuardConditions has not been finalized
158201 if ( disposing )
159202 {
160203 this . OnShutdown ? . Invoke ( ) ;
@@ -163,6 +206,11 @@ private void Dispose(bool disposing)
163206 node . DisposeFromContext ( ) ;
164207 }
165208 this . ROSNodes . Clear ( ) ;
209+ foreach ( var guardCondition in this . GuardConditions )
210+ {
211+ guardCondition . DisposeFromContext ( ) ;
212+ }
213+ this . GuardConditions . Clear ( ) ;
166214 // only safe when all nodes are gone, not calling Dispose() will leak the Handle
167215 Utils . CheckReturnEnum ( NativeRcl . rcl_context_fini ( this . Handle ) ) ;
168216 this . FreeHandles ( ) ;
0 commit comments