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