Line data Source code
1 : /*
2 : * If not stated otherwise in this file or this component's LICENSE file the
3 : * following copyright and licenses apply:
4 : *
5 : * Copyright 2022 Sky UK
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : #include "Timer.h"
21 : #include "RialtoCommonLogging.h"
22 :
23 : namespace firebolt::rialto::common
24 : {
25 : std::weak_ptr<ITimerFactory> TimerFactory::m_factory;
26 :
27 31 : std::shared_ptr<ITimerFactory> ITimerFactory::getFactory()
28 : {
29 31 : std::shared_ptr<ITimerFactory> factory = TimerFactory::m_factory.lock();
30 :
31 31 : if (!factory)
32 : {
33 : try
34 : {
35 31 : factory = std::make_shared<TimerFactory>();
36 : }
37 0 : catch (const std::exception &e)
38 : {
39 0 : RIALTO_COMMON_LOG_ERROR("Failed to create the timer factory, reason: %s", e.what());
40 : }
41 :
42 31 : TimerFactory::m_factory = factory;
43 : }
44 :
45 31 : return factory;
46 : }
47 :
48 5 : std::unique_ptr<ITimer> TimerFactory::createTimer(const std::chrono::milliseconds &timeout,
49 : const std::function<void()> &callback, TimerType timerType) const
50 : {
51 5 : return std::make_unique<Timer>(timeout, callback, timerType);
52 : }
53 :
54 5 : Timer::Timer(const std::chrono::milliseconds &timeout, const std::function<void()> &callback, TimerType timerType)
55 5 : : m_active{true}, m_timeout{timeout}, m_callback{callback}
56 : {
57 5 : m_thread = std::thread(
58 10 : [this, timerType]()
59 : {
60 : do
61 : {
62 10 : bool shouldExecuteCallback = false;
63 : {
64 10 : std::unique_lock<std::mutex> lock{m_mutex};
65 29 : if (!m_cv.wait_for(lock, m_timeout, [this]() { return !m_active; }))
66 : {
67 8 : if (m_active && m_callback)
68 : {
69 8 : shouldExecuteCallback = true;
70 : }
71 : }
72 10 : }
73 :
74 10 : if (shouldExecuteCallback)
75 : {
76 8 : m_callback();
77 : }
78 10 : } while (timerType == TimerType::PERIODIC && m_active);
79 5 : m_active = false;
80 10 : });
81 5 : }
82 :
83 10 : Timer::~Timer()
84 : {
85 5 : cancel();
86 10 : }
87 :
88 8 : void Timer::cancel()
89 : {
90 8 : m_active = false;
91 8 : m_cv.notify_one();
92 :
93 8 : if (std::this_thread::get_id() == m_thread.get_id())
94 : {
95 2 : if (m_thread.joinable())
96 : {
97 2 : m_thread.detach();
98 : }
99 2 : return;
100 : }
101 :
102 6 : if (m_thread.joinable())
103 : {
104 3 : m_thread.join();
105 : }
106 : }
107 :
108 6 : bool Timer::isActive() const
109 : {
110 6 : return m_active;
111 : }
112 : } // namespace firebolt::rialto::common
|