Line data Source code
1 : /* 2 : * This file is part of PTN Engine 3 : * 4 : * Copyright (c) 2023-2024 Eduardo ValgĂ´de 5 : * 6 : * Licensed under the Apache License, Version 2.0 (the "License"); 7 : * you may not use this file except in compliance with the License. 8 : * You may obtain a copy of the License at 9 : * 10 : * http://www.apache.org/licenses/LICENSE-2.0 11 : * 12 : * Unless required by applicable law or agreed to in writing, software 13 : * distributed under the License is distributed on an "AS IS" BASIS, 14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 : * See the License for the specific language governing permissions and 16 : * limitations under the License. 17 : */ 18 : 19 : #include "PTN_Engine/EventLoop.h" 20 : #include "PTN_Engine/IPTN_EngineEL.h" 21 : #include "PTN_Engine/PTN_Exception.h" 22 : #include <thread> 23 : 24 : namespace ptne 25 : { 26 : using namespace std; 27 : 28 78 : EventLoop::EventLoop(IPTN_EngineEL &ptnEngineInternal) 29 78 : : m_ptnEngine(ptnEngineInternal) 30 : { 31 78 : } 32 : 33 78 : EventLoop::~EventLoop() = default; 34 : 35 321 : bool EventLoop::isRunning() const 36 : { 37 321 : return m_eventLoopThreadRunning; 38 : } 39 : 40 171 : void EventLoop::stop() noexcept 41 : { 42 171 : if (!isRunning()) 43 : { 44 136 : return; 45 : } 46 : 47 35 : if (m_eventLoopThread.get_stop_token().stop_possible()) 48 : { 49 35 : m_eventLoopThread.request_stop(); 50 35 : m_barrier->arrive_and_wait(); 51 : } 52 : } 53 : 54 43 : void EventLoop::start(const bool log, ostream &o) 55 : { 56 43 : if (isRunning()) 57 : { 58 1 : throw PTN_Exception("Cannot call execute while the event loop is still running."); 59 : } 60 42 : if (m_ptnEngine.getActionsThreadOption() == PTN_Engine::ACTIONS_THREAD_OPTION::SINGLE_THREAD) 61 : { 62 200012 : while (m_ptnEngine.executeInt(log, o)) 63 : ; 64 : } 65 : else 66 : { 67 35 : m_barrier = make_unique<barrier<>>(2); 68 35 : m_eventLoopThreadRunning = true; 69 35 : m_eventLoopThread = jthread(bind_front(&EventLoop::run, this), log, ref(o)); 70 : } 71 42 : } 72 : 73 2473 : void EventLoop::notifyNewEvent() 74 : { 75 2473 : unique_lock eventNotifierGuard(m_eventNotifierMutex); 76 2473 : m_eventNotifier.notify_all(); 77 2473 : } 78 : 79 2 : void EventLoop::setSleepDuration(const SleepDuration sleepDuration) 80 : { 81 2 : unique_lock lock(m_sleepDurationMutex); 82 : // TODO validate input 83 2 : m_sleepDuration = sleepDuration; 84 2 : } 85 : 86 4 : EventLoop::SleepDuration EventLoop::getSleepDuration() const 87 : { 88 4 : shared_lock lock(m_sleepDurationMutex); 89 4 : return m_sleepDuration; 90 4 : } 91 : 92 35 : void EventLoop::run(stop_token stopToken, const bool log, ostream &o) 93 : { 94 606735 : while (!stopToken.stop_requested()) 95 : { 96 606700 : if (!m_ptnEngine.executeInt(log, o)) 97 : { 98 2250 : shared_lock lock(m_sleepDurationMutex); 99 2250 : unique_lock eventNotifierGuard(m_eventNotifierMutex); 100 2250 : m_eventNotifier.wait_for(eventNotifierGuard, m_sleepDuration, 101 4494 : [this] { return m_ptnEngine.getNewInputReceived(); }); 102 2250 : } 103 : } 104 35 : m_eventLoopThreadRunning = false; 105 35 : m_barrier->arrive_and_wait(); 106 35 : } 107 : } // namespace ptne