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 : {} 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 : } 68 : 69 : template<typename Runnable, typename EventPolicy, typename Lock> 70 9 : inline void RunnableExecutor<Runnable, EventPolicy, Lock>::enqueue(Runnable& runnable) 71 : { 72 : { 73 5 : ESR_UNUSED const Lock lock; 74 9 : if (!runnable.isEnqueued()) 75 : { 76 17 : _queue.enqueue(runnable); 77 : } 78 5 : } 79 9 : _eventPolicy.setEvent(); 80 9 : } 81 : 82 : template<typename Runnable, typename EventPolicy, typename Lock> 83 5 : void RunnableExecutor<Runnable, EventPolicy, Lock>::handleEvent() 84 : { 85 6 : while (true) 86 : { 87 : Runnable* runnable; 88 : { 89 6 : ESR_UNUSED const Lock lock; 90 17 : runnable = _queue.dequeue(); 91 6 : } 92 6 : if (runnable != nullptr) 93 : { 94 6 : runnable->execute(); 95 : } 96 : else 97 : { 98 : break; 99 : } 100 : } 101 5 : } 102 : 103 : } // namespace async