@@ -217,65 +217,29 @@ namespace delegate
217
217
unused = node;
218
218
}
219
219
220
- void traverse (Node_t*& current) const
221
- {
222
- current = current->mNext ;
223
- }
224
- void traverse (Node_t*& prev, Node_t*& current, bool remove = true )
225
- {
226
- if (remove && ISQUEUE)
227
- {
228
- // remove callback from stack
229
- #ifdef ARDUINO
230
- InterruptLock lockAllInterruptsInThisScope;
231
- #else
232
- std::lock_guard<std::mutex> lock (mutex_unused);
233
- #endif
234
-
235
- auto to_recycle = current;
236
-
237
- // removing last
238
- if (last == current)
239
- last = prev;
240
-
241
- current = current->mNext ;
242
- if (prev)
243
- {
244
- prev->mNext = current;
245
- }
246
- else
247
- {
248
- first = current;
249
- }
250
-
251
- recycle_node_unsafe (to_recycle);
252
- }
253
- else
254
- {
255
- prev = current;
256
- traverse (current);
257
- }
258
- }
259
-
260
220
#ifndef ARDUINO
261
221
std::mutex mutex_unused;
262
222
#endif
263
223
public:
264
224
class iterator : public std ::iterator<std::forward_iterator_tag, Delegate>
265
225
{
266
- protected:
267
- MultiDelegatePImpl& multiDel;
268
- Node_t* current = nullptr ;
269
- Node_t* const stop = nullptr ;
270
226
public:
271
- iterator (MultiDelegatePImpl& md) : multiDel(md), current(md.first), stop(md.last) {}
272
- iterator (MultiDelegatePImpl& md, nullptr_t ) : multiDel(md) {}
227
+ Node_t* current = nullptr ;
228
+ Node_t* prev = nullptr ;
229
+ const Node_t* stop = nullptr ;
230
+
231
+ iterator (MultiDelegatePImpl& md) : current(md.first), stop(md.last) {}
273
232
iterator () = default ;
274
233
iterator (const iterator&) = default ;
275
234
iterator& operator =(const iterator&) = default ;
235
+ iterator& operator =(iterator&&) = default ;
236
+ operator bool () const
237
+ {
238
+ return current && stop;
239
+ }
276
240
bool operator ==(const iterator& rhs) const
277
241
{
278
- return &multiDel == &rhs. multiDel && current == rhs.current ;
242
+ return current == rhs.current ;
279
243
}
280
244
bool operator !=(const iterator& rhs) const {
281
245
return !operator ==(rhs);
@@ -291,7 +255,10 @@ namespace delegate
291
255
iterator& operator ++() // prefix
292
256
{
293
257
if (current && stop != current)
294
- multiDel.traverse (current);
258
+ {
259
+ prev = current;
260
+ current = current->mNext ;
261
+ }
295
262
else
296
263
current = nullptr ; // end
297
264
return *this ;
@@ -304,11 +271,11 @@ namespace delegate
304
271
}
305
272
};
306
273
307
- iterator begin () const {
274
+ iterator begin () {
308
275
return iterator (*this );
309
276
}
310
277
iterator end () const {
311
- return iterator (* this , nullptr );
278
+ return iterator ();
312
279
}
313
280
314
281
const Delegate* IRAM_ATTR add (const Delegate& del)
@@ -348,52 +315,47 @@ namespace delegate
348
315
return &item->mDelegate ;
349
316
}
350
317
351
- bool remove ( const Delegate* del )
318
+ iterator erase (iterator it )
352
319
{
353
- auto current = first;
354
- if (!current)
355
- return false ;
356
-
357
- Node_t* prev = nullptr ;
358
- do
359
- {
360
- if (del == ¤t->mDelegate )
361
- {
362
- // remove callback from stack
320
+ if (!it)
321
+ return end ();
363
322
#ifdef ARDUINO
364
- InterruptLock lockAllInterruptsInThisScope;
323
+ InterruptLock lockAllInterruptsInThisScope;
365
324
#else
366
- std::lock_guard<std::mutex> lock (mutex_unused);
325
+ std::lock_guard<std::mutex> lock (mutex_unused);
367
326
#endif
327
+ auto to_recycle = it.current ;
368
328
369
- auto to_recycle = current;
370
-
371
- // removing last
372
- if (last == current)
373
- last = prev;
329
+ if (last == it.current )
330
+ last = it.prev ;
331
+ it.current = it.current ->mNext ;
332
+ if (it.prev )
333
+ {
334
+ it.prev ->mNext = it.current ;
335
+ }
336
+ else
337
+ {
338
+ first = it.current ;
339
+ }
340
+ if (ISQUEUE)
341
+ recycle_node_unsafe (to_recycle);
342
+ else
343
+ delete to_recycle;
344
+ return it;
345
+ }
374
346
375
- current = current->mNext ;
376
- if (prev)
377
- {
378
- prev->mNext = current;
379
- }
380
- else
381
- {
382
- first = current;
383
- }
384
-
385
- if (ISQUEUE)
386
- recycle_node_unsafe (to_recycle);
387
- else
388
- delete to_recycle;
389
- return true ;
390
- }
391
- else
347
+ bool erase (const Delegate* const del)
348
+ {
349
+ auto it = begin ();
350
+ while (it)
351
+ {
352
+ if (del == &it.current ->mDelegate )
392
353
{
393
- prev = current ;
394
- current = current-> mNext ;
354
+ erase (it) ;
355
+ return true ;
395
356
}
396
- } while (current);
357
+ ++it;
358
+ }
397
359
return false ;
398
360
}
399
361
@@ -404,8 +366,8 @@ namespace delegate
404
366
405
367
R operator ()(P... args)
406
368
{
407
- auto current = first ;
408
- if (!current )
369
+ auto it = begin () ;
370
+ if (!it )
409
371
return {};
410
372
411
373
static std::atomic<bool > fence (false );
@@ -417,25 +379,19 @@ namespace delegate
417
379
if (fence.exchange (true )) return {};
418
380
#endif
419
381
420
- Node_t* prev = nullptr ;
421
- // prevent execution of new callbacks during this run
422
- auto stop = last;
423
-
424
382
R result;
425
- bool done;
426
383
do
427
384
{
428
- done = current == stop;
429
- result = CallP<Delegate, R, ISQUEUE, P...>::execute (current->mDelegate , args...);
430
- if (ISQUEUE)
431
- traverse (prev, current, result);
385
+ result = CallP<Delegate, R, ISQUEUE, P...>::execute (it.current ->mDelegate , args...);
386
+ if (result && ISQUEUE)
387
+ it = erase (it);
432
388
else
433
- traverse (current) ;
389
+ ++it ;
434
390
#if defined(ESP8266) || defined(ESP32)
435
391
// running callbacks might last too long for watchdog etc.
436
392
optimistic_yield (10000 );
437
393
#endif
438
- } while (current && !done );
394
+ } while (it );
439
395
440
396
fence.store (false );
441
397
return result;
@@ -445,24 +401,13 @@ namespace delegate
445
401
template < typename Delegate, typename R = void , bool ISQUEUE = false , size_t QUEUE_CAPACITY = 32 >
446
402
class MultiDelegateImpl : public MultiDelegatePImpl <Delegate, R, ISQUEUE, QUEUE_CAPACITY>
447
403
{
448
- protected:
449
- using typename MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::Node_t;
450
- using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::first;
451
- using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::last;
452
- using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::unused;
453
- using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::nodeCount;
454
- using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::recycle_node_unsafe;
455
- #ifndef ARDUINO
456
- using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::mutex_unused;
457
- #endif
458
-
459
404
public:
460
405
using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::MultiDelegatePImpl;
461
406
462
407
R operator ()()
463
408
{
464
- auto current = first ;
465
- if (!current )
409
+ auto it = this -> begin () ;
410
+ if (!it )
466
411
return {};
467
412
468
413
static std::atomic<bool > fence (false );
@@ -474,25 +419,19 @@ namespace delegate
474
419
if (fence.exchange (true )) return {};
475
420
#endif
476
421
477
- Node_t* prev = nullptr ;
478
- // prevent execution of new callbacks during this run
479
- auto stop = last;
480
-
481
422
R result;
482
- bool done;
483
423
do
484
424
{
485
- done = current == stop;
486
- result = Call<Delegate, R, ISQUEUE>::execute (current->mDelegate );
487
- if (ISQUEUE)
488
- this ->traverse (prev, current, result);
425
+ result = Call<Delegate, R, ISQUEUE>::execute (it.current ->mDelegate );
426
+ if (result && ISQUEUE)
427
+ it = this ->erase (it);
489
428
else
490
- this -> traverse (current) ;
429
+ ++it ;
491
430
#if defined(ESP8266) || defined(ESP32)
492
431
// running callbacks might last too long for watchdog etc.
493
432
optimistic_yield (10000 );
494
433
#endif
495
- } while (current && !done );
434
+ } while (it );
496
435
497
436
fence.store (false );
498
437
return result;
@@ -520,14 +459,11 @@ namespace delegate
520
459
{
521
460
public:
522
461
using MultiDelegatePImpl<Delegate, void , ISQUEUE, QUEUE_CAPACITY, P...>::MultiDelegatePImpl;
523
- using typename MultiDelegatePImpl<Delegate, void , ISQUEUE, QUEUE_CAPACITY, P...>::Node_t;
524
- using MultiDelegatePImpl<Delegate, void , ISQUEUE, QUEUE_CAPACITY, P...>::first;
525
- using MultiDelegatePImpl<Delegate, void , ISQUEUE, QUEUE_CAPACITY, P...>::last;
526
462
527
463
void operator ()(P...
10000
args)
528
464
{
529
- auto current = first ;
530
- if (!current )
465
+ auto it = this -> begin () ;
466
+ if (!it )
531
467
return ;
532
468
533
469
static std::atomic<bool > fence (false );
@@ -539,24 +475,18 @@ namespace delegate
539
475
if (fence.exchange (true )) return ;
540
476
#endif
541
477
542
- Node_t* prev = nullptr ;
543
- // prevent execution of new callbacks during this run
544
- auto stop = last;
545
-
546
- bool done;
547
478
do
548
479
{
549
- done = current == stop;
550
- CallP<Delegate, void , ISQUEUE, P...>::execute (current->mDelegate , args...);
480
+ CallP<Delegate, void , ISQUEUE, P...>::execute (it.current ->mDelegate , args...);
551
481
if (ISQUEUE)
552
- this ->traverse (prev, current );
482
+ it = this ->erase (it );
553
483
else
554
- traverse (current) ;
484
+ ++it ;
555
485
#if defined(ESP8266) || defined(ESP32)
556
486
// running callbacks might last too long for watchdog etc.
557
487
optimistic_yield (10000 );
558
488
#endif
559
- } while (current && !done );
489
+ } while (it );
560
490
561
491
fence.store (false );
562
492
}
@@ -567,14 +497,11 @@ namespace delegate
567
497
{
568
498
public:
569
499
using MultiDelegateImpl<Delegate, void , ISQUEUE, QUEUE_CAPACITY>::MultiDelegateImpl;
570
- using typename MultiDelegateImpl<Delegate, void , ISQUEUE, QUEUE_CAPACITY>::Node_t;
571
- using MultiDelegateImpl<Delegate, void , ISQUEUE, QUEUE_CAPACITY>::first;
572
- using MultiDelegateImpl<Delegate, void , ISQUEUE, QUEUE_CAPACITY>::last;
573
500
574
501
void operator ()()
575
502
{
576
- auto current = first ;
577
- if (!current )
503
+ auto it = this -> begin () ;
504
+ if (!it )
578
505
return ;
579
506
580
507
static std::atomic<bool > fence (false );
@@ -586,24 +513,18 @@ namespace delegate
586
513
if (fence.exchange (true )) return ;
587
514
#endif
588
515
589
- Node_t* prev = nullptr ;
590
- // prevent execution of new callbacks during this run
591
- auto stop = last;
592
-
593
- bool done;
594
516
do
595
517
{
596
- done = current == stop;
597
- Call<Delegate, void , ISQUEUE>::execute (current->mDelegate );
518
+ Call<Delegate, void , ISQUEUE>::execute (it.current ->mDelegate );
598
519
if (ISQUEUE)
599
- this ->traverse (prev, current );
520
+ it = this ->erase (it );
600
521
else
601
- this -> traverse (current) ;
522
+ ++it ;
602
523
#if defined(ESP8266) || defined(ESP32)
603
524
// running callbacks might last too long for watchdog etc.
604
525
optimistic_yield (10000 );
605
526
#endif
606
- } while (current && !done );
527
+ } while (it );
607
528
608
529
fence.store (false );
609
530
}
0 commit comments