8000 Change to make MultiDelegate invoke and erase work off iterators. · dok-net/arduino-esp8266@a699050 · GitHub
[go: up one dir, main page]

Skip to content

Commit a699050

Browse files
committed
Change to make MultiDelegate invoke and erase work off iterators.
1 parent 1375187 commit a699050

File tree

1 file changed

+76
-155
lines changed

1 file changed

+76
-155
lines changed

cores/esp8266/MultiDelegate.h

Lines changed: 76 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -217,65 +217,29 @@ namespace delegate
217217
unused = node;
218218
}
219219

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-
260220
#ifndef ARDUINO
261221
std::mutex mutex_unused;
262222
#endif
263223
public:
264224
class iterator : public std::iterator<std::forward_iterator_tag, Delegate>
265225
{
266-
protected:
267-
MultiDelegatePImpl& multiDel;
268-
Node_t* current = nullptr;
269-
Node_t* const stop = nullptr;
270226
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) {}
273232
iterator() = default;
274233
iterator(const iterator&) = default;
275234
iterator& operator=(const iterator&) = default;
235+
iterator& operator=(iterator&&) = default;
236+
operator bool() const
237+
{
238+
return current && stop;
239+
}
276240
bool operator==(const iterator& rhs) const
277241
{
278-
return &multiDel == &rhs.multiDel && current == rhs.current;
242+
return current == rhs.current;
279243
}
280244
bool operator!=(const iterator& rhs) const {
281245
return !operator==(rhs);
@@ -291,7 +255,10 @@ namespace delegate
291255
iterator& operator++() // prefix
292256
{
293257
if (current && stop != current)
294-
multiDel.traverse(current);
258+
{
259+
prev = current;
260+
current = current->mNext;
261+
}
295262
else
296263
current = nullptr; // end
297264
return *this;
@@ -304,11 +271,11 @@ namespace delegate
304271
}
305272
};
306273

307-
iterator begin() const {
274+
iterator begin() {
308275
return iterator(*this);
309276
}
310277
iterator end() const {
311-
return iterator(*this, nullptr);
278+
return iterator();
312279
}
313280

314281
const Delegate* IRAM_ATTR add(const Delegate& del)
@@ -348,52 +315,47 @@ namespace delegate
348315
return &item->mDelegate;
349316
}
350317

351-
bool remove(const Delegate* del)
318+
iterator erase(iterator it)
352319
{
353-
auto current = first;
354-
if (!current)
355-
return false;
356-
357-
Node_t* prev = nullptr;
358-
do
359-
{
360-
if (del == &current->mDelegate)
361-
{
362-
// remove callback from stack
320+
if (!it)
321+
return end();
363322
#ifdef ARDUINO
364-
InterruptLock lockAllInterruptsInThisScope;
323+
InterruptLock lockAllInterruptsInThisScope;
365324
#else
366-
std::lock_guard<std::mutex> lock(mutex_unused);
325+
std::lock_guard<std::mutex> lock(mutex_unused);
367326
#endif
327+
auto to_recycle = it.current;
368328

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+
}
374346

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)
392353
{
393-
prev = current;
394-
current = current->mNext;
354+
erase(it);
355+
return true;
395356
}
396-
} while (current);
357+
++it;
358+
}
397359
return false;
398360
}
399361

@@ -404,8 +366,8 @@ namespace delegate
404366

405367
R operator()(P... args)
406368
{
407-
auto current = first;
408-
if (!current)
369+
auto it = begin();
370+
if (!it)
409371
return {};
410372

411373
static std::atomic<bool> fence(false);
@@ -417,25 +379,19 @@ namespace delegate
417379
if (fence.exchange(true)) return {};
418380
#endif
419381

420-
Node_t* prev = nullptr;
421-
// prevent execution of new callbacks during this run
422-
auto stop = last;
423-
424382
R result;
425-
bool done;
426383
do
427384
{
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);
432388
else
433-
traverse(current);
389+
++it;
434390
#if defined(ESP8266) || defined(ESP32)
435391
// running callbacks might last too long for watchdog etc.
436392
optimistic_yield(10000);
437393
#endif
438-
} while (current && !done);
394+
} while (it);
439395

440396
fence.store(false);
441397
return result;
@@ -445,24 +401,13 @@ namespace delegate
445401
template< typename Delegate, typename R = void, bool ISQUEUE = false, size_t QUEUE_CAPACITY = 32>
446402
class MultiDelegateImpl : public MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>
447403
{
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-
459404
public:
460405
using MultiDelegatePImpl<Delegate, R, ISQUEUE, QUEUE_CAPACITY>::MultiDelegatePImpl;
461406

462407
R operator()()
463408
{
464-
auto current = first;
465-
if (!current)
409+
auto it = this->begin();
410+
if (!it)
466411
return {};
467412

468413
static std::atomic<bool> fence(false);
@@ -474,25 +419,19 @@ namespace delegate
474419
if (fence.exchange(true)) return {};
475420
#endif
476421

477-
Node_t* prev = nullptr;
478-
// prevent execution of new callbacks during this run
479-
auto stop = last;
480-
481422
R result;
482-
bool done;
483423
do
484424
{
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);
489428
else
490-
this->traverse(current);
429+
++it;
491430
#if defined(ESP8266) || defined(ESP32)
492431
// running callbacks might last too long for watchdog etc.
493432
optimistic_yield(10000);
494433
#endif
495-
} while (current && !done);
434+
} while (it);
496435

497436
fence.store(false);
498437
return result;
@@ -520,14 +459,11 @@ namespace delegate
520459
{
521460
public:
522461
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;
526462

527463
void operator()(P... 10000 args)
528464
{
529-
auto current = first;
530-
if (!current)
465+
auto it = this->begin();
466+
if (!it)
531467
return;
532468

533469
static std::atomic<bool> fence(false);
@@ -539,24 +475,18 @@ namespace delegate
539475
if (fence.exchange(true)) return;
540476
#endif
541477

542-
Node_t* prev = nullptr;
543-
// prevent execution of new callbacks during this run
544-
auto stop = last;
545-
546-
bool done;
547478
do
548479
{
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...);
551481
if (ISQUEUE)
552-
this->traverse(prev, current);
482+
it = this->erase(it);
553483
else
554-
traverse(current);
484+
++it;
555485
#if defined(ESP8266) || defined(ESP32)
556486
// running callbacks might last too long for watchdog etc.
557487
optimistic_yield(10000);
558488
#endif
559-
} while (current && !done);
489+
} while (it);
560490

561491
fence.store(false);
562492
}
@@ -567,14 +497,11 @@ namespace delegate
567497
{
568498
public:
569499
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;
573500

574501
void operator()()
575502
{
576-
auto current = first;
577-
if (!current)
503+
auto it = this->begin();
504+
if (!it)
578505
return;
579506

580507
static std::atomic<bool> fence(false);
@@ -586,24 +513,18 @@ namespace delegate
586513
if (fence.exchange(true)) return;
587514
#endif
588515

589-
Node_t* prev = nullptr;
590-
// prevent execution of new callbacks during this run
591-
auto stop = last;
592-
593-
bool done;
594516
do
595517
{
596-
done = current == stop;
597-
Call<Delegate, void, ISQUEUE>::execute(current->mDelegate);
518+
Call<Delegate, void, ISQUEUE>::execute(it.current->mDelegate);
598519
if (ISQUEUE)
599-
this->traverse(prev, current);
520+
it = this->erase(it);
600521
else
601-
this->traverse(current);
522+
++it;
602523
#if defined(ESP8266) || defined(ESP32)
603524
// running callbacks might last too long for watchdog etc.
604525
optimistic_yield(10000);
605526
#endif
606-
} while (current && !done);
527+
} while (it);
607528

608529
fence.store(false);
609530
}

0 commit comments

Comments
 (0)
0