Line data Source code
1 : // Copyright 2024 Accenture.
2 :
3 : /**
4 : * \ingroup async
5 : */
6 : #pragma once
7 :
8 : #include "async/Queue.h"
9 :
10 : #include <platform/config.h>
11 :
12 : namespace async
13 : {
14 : /**
15 : * A template class that enables the enqueuing and execution of Runnables. It leverages an
16 : * EventPolicy, making it suitable for event-driven applications.
17 : *
18 : * \tparam Runnable Type of functions, that will be executed.
19 : * \tparam EventPolicy EventPolicy is derived from EventDispatcher. Method enqueue will set Event,
20 : * specified in EventPolicy.
21 : */
22 : template<typename Runnable, typename EventPolicy, typename Lock>
23 : class RunnableExecutor
24 : {
25 : public:
26 : explicit RunnableExecutor(typename EventPolicy::EventDispatcherType& eventDispatcher);
27 :
28 : void init();
29 : void shutdown();
30 :
31 : /**
32 : * Places a Runnable in the internal queue and sets the event in the EventDispatcher. When
33 : * handleEvents is called on the EventDispatcher, all Runnables in the queue are executed
34 : * sequentially, and the queue is emptied.
35 : * \param runnable Runnable to be executed
36 : */
37 : void enqueue(Runnable& runnable);
38 :
39 : private:
40 : void handleEvent();
41 :
42 : Queue<Runnable> _queue;
43 : EventPolicy _eventPolicy;
44 : };
45 :
46 : /**
47 : * Inline implementations.
48 : */
49 : template<typename Runnable, typename EventPolicy, typename Lock>
50 182 : RunnableExecutor<Runnable, EventPolicy, Lock>::RunnableExecutor(
51 : typename EventPolicy::EventDispatcherType& eventDispatcher)
52 182 : : _queue(), _eventPolicy(eventDispatcher)
53 182 : {}
54 :
55 : template<typename Runnable, typename EventPolicy, typename Lock>
56 182 : void RunnableExecutor<Runnable, EventPolicy, Lock>::init()
57 : {
58 182 : _eventPolicy.setEventHandler(
59 : EventPolicy::HandlerFunctionType::
60 : template create<RunnableExecutor, &RunnableExecutor::handleEvent>(*this));
61 182 : }
62 :
63 : template<typename Runnable, typename EventPolicy, typename Lock>
64 1 : void RunnableExecutor<Runnable, EventPolicy, Lock>::shutdown()
65 : {
66 1 : _eventPolicy.removeEventHandler();
67 1 : }
68 :
69 : template<typename Runnable, typename EventPolicy, typename Lock>
70 9 : inline void RunnableExecutor<Runnable, EventPolicy, Lock>::enqueue(Runnable& runnable)
71 : {
72 : {
73 9 : ESR_UNUSED const Lock lock;
74 9 : if (!runnable.isEnqueued())
75 : {
76 8 : _queue.enqueue(runnable);
77 : }
78 9 : }
79 9 : _eventPolicy.setEvent();
80 9 : }
81 :
82 : template<typename Runnable, typename EventPolicy, typename Lock>
83 11 : void RunnableExecutor<Runnable, EventPolicy, Lock>::handleEvent()
84 : {
85 6 : while (true)
86 : {
87 : Runnable* runnable;
88 : {
89 11 : ESR_UNUSED const Lock lock;
90 11 : runnable = _queue.dequeue();
91 11 : }
92 11 : if (runnable != nullptr)
93 : {
94 6 : runnable->execute();
95 : }
96 : else
97 : {
98 5 : break;
99 : }
100 : }
101 5 : }
102 :
103 : } // namespace async
|