@@ -129,6 +129,7 @@ namespace Core
129
129
: entry_function()
130
130
, exit_function()
131
131
, dispatch_table()
132
+ , single_dispatch()
132
133
{ }
133
134
134
135
@@ -266,18 +267,24 @@ namespace Core
266
267
*
267
268
* @param event The event that is to be handled.
268
269
* @param handler The handler function object to set.
270
+ * @param single_dispatch_only If the handler can only be executed once.
269
271
* @return The reference to this State object.
270
272
*/
271
273
virtual State & SetEventHandler (
272
274
const Event & event,
273
- const EventHandler & handler
275
+ const EventHandler & handler,
276
+ bool single_dispatch_only = false
274
277
)
275
278
{
276
279
// Indicates that the event has already been configured in this
277
280
// state. A single event can't have multiple functions.
278
281
//
279
282
assert ( transition_table.find ( event ) == transition_table.end () );
280
283
dispatch_table.insert ( { event, handler } );
284
+ if ( single_dispatch_only )
285
+ {
286
+ single_dispatch.insert ( { event, nullptr } );
287
+ }
281
288
return *this ;
282
289
}
283
290
@@ -296,6 +303,16 @@ namespace Core
296
303
)
297
304
{
298
305
EventHandler old_handler{};
306
+ auto sit = single_dispatch.find ( event );
307
+ if ( sit != single_dispatch.end () )
308
+ {
309
+ if ( sit->second != nullptr )
310
+ {
311
+ std::swap ( sit->second , old_handler );
312
+ single_dispatch[event] = handler;
313
+ return std::move ( old_handler );
314
+ }
315
+ }
299
316
auto dit = dispatch_table.find ( event );
300
317
if ( dit != dispatch_table.end () )
301
318
{
@@ -326,6 +343,15 @@ namespace Core
326
343
{
327
344
handler = dit->second ;
328
345
}
346
+ auto sit = single_dispatch.find ( event );
347
+ if ( sit != single_dispatch.end () )
348
+ {
349
+ if ( sit->second == nullptr )
350
+ {
351
+ sit->second = dit->second ;
352
+ dit->second = [this ]( const Event & ) { /* NOOP */ };
353
+ }
354
+ }
329
355
return std::move ( handler );
330
356
}
331
357
@@ -344,7 +370,7 @@ namespace Core
344
370
* taking place and the state is becoming the previous state.
345
371
* @return The ExitFunction of the state.
346
372
*/
347
- inline ExitFunction Exit () const { return exit_function; }
373
+ inline ExitFunction Exit () const { RestoreDispatchTable (); return exit_function; }
348
374
349
375
350
376
private :
@@ -353,6 +379,13 @@ namespace Core
353
379
// /
354
380
using DispatchTable = std::map< Event, EventHandler >;
355
381
382
+ // / Those events that should be handled only once in this state
383
+ // / are entered here. Just the fact that an entry exists in this
384
+ // / table assures that event is a single dispatch event. On exit
385
+ // / the event dispatch is restored.
386
+ // /
387
+ using SingleDispatch = std::map< Event, EventHandler >;
388
+
356
389
// / Describes what state transition to take when an event arrives for
357
390
// / the state. Note that the DispatchTable and the TransitionTable
358
391
// / are mutually exclusive (the same event can't be in both).
@@ -361,10 +394,29 @@ namespace Core
361
394
362
395
363
396
private :
364
- EntryFunction entry_function;
365
- ExitFunction exit_function;
366
- DispatchTable dispatch_table;
367
- TransitionTable transition_table;
397
+ EntryFunction entry_function;
398
+ ExitFunction exit_function;
399
+ mutable DispatchTable dispatch_table;
400
+ mutable SingleDispatch single_dispatch;
401
+ TransitionTable transition_table;
402
+
403
+
404
+ private :
405
+ /* *
406
+ * For those events that are to be dispatched only once it restores
407
+ * the dispatch table so that it may handle the event again.
408
+ */
409
+ void RestoreDispatchTable () const
410
+ {
411
+ for ( auto sit : single_dispatch )
412
+ {
413
+ if ( sit.second != nullptr )
414
+ {
415
+ dispatch_table[sit.first ] = sit.second ;
416
+ sit.second = nullptr ;
417
+ }
418
+ }
419
+ }
368
420
};
369
421
370
422
@@ -374,6 +426,10 @@ namespace Core
374
426
// /
375
427
static const StateID SentinelStateID{ -1 };
376
428
429
+ // / Convenience value to descriptively set the similarly named function
430
+ // / argument in SetEventHandler().
431
+ // /
432
+ static const bool SingleDispatchOnly{ true };
377
433
378
434
public :
379
435
/* *
0 commit comments