ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
threadmanager.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2019 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
7#if !defined(HPP_AWORX_ALIB_THREADS_MODEL_THREADMANAGER)
9#endif
10
11#if ALIB_ENUMS
12# if !defined(HPP_ALIB_ENUMS_SERIALIZATION)
14# endif
15#endif
16
17#if !defined(ALIB_DOX) // todo remove
18
19
20namespace alib::threads::model {
21
22ThreadManager::ThreadManager()
23: Thread("ThrdMgr")
24{
25 mStoppedFlag= false;
26}
27
28ThreadManager::~ThreadManager()
29{
30 if( state <= State::Started )
31 {
32 ALIB_WARNING("ATHR", "ThreadManager destroyed without having run" )
33 }
34 else if( state != State::Terminated )
35 {
36 ALIB_ERROR("ATHR", "ThreadManager destroyed without being terminated" )
37 Start();
38 }
39}
40
41void ThreadManager::Add(MThread& thread)
42{
43 std::unique_lock<std::mutex> lock(mutex);
44 threadMap.emplace( thread.GetId() , &thread );
45 thread.Start();
46}
47
48
49void ThreadManager::StopAndTerminateAll()
50{
51 ALIB_MESSAGE("ATHR", "ThreadManager::StopAndTerminateAll" )
52
53 // stop myself
54 if( state < State::Stopped)
55 {
56 mStoppedFlag= true;
57 NotifyAll();
58 }
59
60 ALIB_DBG( Ticks waitCheck= Ticks::Now();
61 int nextWarnSecond= 1; )
62 while( state > State::Unstarted && state < State::Stopped )
63 {
64 Thread::SleepMicros( 50 );
65 ALIB_DBG( if( waitCheck.Age().InAbsoluteSeconds() == nextWarnSecond )
66 ALIB_WARNING( "ATHR", "Waiting for ThreadManager to stop") )
67 }
68
69 // stop all registered MThreads
70 { ALIB_LOCK
71
72 // send stop to those unstopped
73 for( auto it : threadMap )
74 if( !it.second->IsStopped() )
75 it.second->Stop();
76
77 ALIB_DBG( waitCheck= Ticks::Now(); nextWarnSecond= 1; )
78 int cntRunning;
79 while(true)
80 {
81 // check that all threads are stopped
82 cntRunning= 0;
83 for( auto it : threadMap )
84 if( it.second->GetState() < Thread::State::Stopped )
85 cntRunning++;
86 if( cntRunning == 0 )
87 break;
88
89 Thread::SleepMicros( 50 );
90 #if ALIB_DEBUG
91 if( waitCheck.Age().InAbsoluteSeconds() == nextWarnSecond )
92 {
93 NString4K dbgThreadList("ThreadManager Termination: Waiting on " );
94 dbgThreadList << static_cast<integer>(cntRunning) << " Threads to stop. Threadlist: " << NewLine();
95 int tNr= 0;
96 for( auto it : threadMap )
97 {
98 dbgThreadList << ++tNr << ": " << it.second->GetName() << ",\tState::"
99 #if ALIB_ENUMS
100 << it.second->state << NewLine();
101 #else
102 << static_cast<int>( it.second->state) << NewLine();
103 #endif
104 }
105 ALIB_WARNING( "ATHR", dbgThreadList.NewLine().Terminate() )
106 nextWarnSecond++;
107 }
108 #endif
109 }
110
111 // terminate all registered MThreads
112 for( auto it : threadMap )
113 it.second->Terminate();
114 threadMap.clear();
115
116 // terminate myself
117 Terminate();
118 } // lock
119}
120
121
122void ThreadManager::Run()
123{
124 // --------------------- Trigger loop ---------------------
125 Ticks nextWakeup= Ticks::Now();
126 ALIB_DBG( Ticks::Duration dbgSleepTime; )
127 while(!IsStopped())
128 {
129 Ticks now= Ticks::Now();
130
131 #if ALIB_DEBUG
132 auto diff= (nextWakeup - now).InAbsoluteMicroseconds();
133 NString256 msg("ThreadManager woke up. Scheduled wakeup " );
134 if( diff < 0 )
135 {
136 msg << "was " << -diff << "\u00B5s ago ("
137 << static_cast<double>( -100 * diff / dbgSleepTime.InAbsoluteMicroseconds())
138 / 100.0
139 << "% late)";
140 }
141 else
142 {
143 msg << "is in " << diff << "\u00B5s ("
144 << static_cast<double>( 100 * diff / dbgSleepTime.InAbsoluteMicroseconds())
145 / 100.0
146 << "% early)";
147 }
148 ALIB_MESSAGE("ATHR", msg.Terminate())
149 #endif
150
151 //--------- trigger triggered objects --------
152 { ALIB_LOCK
153 for( auto it : triggerList )
154 {
155 if( it.nextWakeup <= now )
156 {
157 it.triggered->trigger();
158 now= Ticks::Now();
159 it.nextWakeup= now + Ticks::Duration::FromAbsoluteMilliseconds(it.triggered->triggerPeriodInMilliseconds());
160 }
161
162 if( nextWakeup < it.nextWakeup)
163 nextWakeup= it.nextWakeup;
164 }
165 }
166
167 // quickly check for stopped signal
168 if( IsStopped() )
169 {
170 ALIB_MESSAGE("ATHR", "ThreadManager Stopping")
171 break;
172 }
173
174 // sleep and update status for threadDB
175 ALIB_DBG( dbgSleepTime= nextWakeup - now; )
176 SleepUntil( nextWakeup );
177 }
178
179 ALIB_MESSAGE("ATHR", "ThreadManager Exiting" )
180}
181
182void ThreadManager::AddTriggered(Triggered& triggered)
183{
184 { ALIB_LOCK
185
186 // find if not already registered
187 auto it= triggerList.begin();
188 while(it != triggerList.end() && it->triggered != &triggered);
189
190 if( it == triggerList.end() )
191 triggerList.push_back( { &triggered,
192 Ticks::Now() + Ticks::Duration::FromAbsoluteMilliseconds(
193 triggered.triggerPeriodInMilliseconds() )
194 } );
195 else
196 it->nextWakeup= Ticks::Now(); // we do a first wakeup as soon as possible away
197 }
198 // let's wake this thread up and perform a first trigger
199 Notify();
200}
201
202void ThreadManager::RemoveTriggered(Triggered &triggered)
203{
204 bool found= false;
205
206 { ALIB_LOCK
207 for(auto it= triggerList.begin() ; it != triggerList.end() ; it++)
208 {
209 if(it->triggered == &triggered)
210 {
211 found= true;
212 triggerList.erase(it);
213 break;
214 }
215 }
216 }
217
218 // check
219 if(!found)
220 {
221 ALIB_MESSAGE("ATHR", NString256( "Managed thread \"" )
222 << triggered.Name
223 << "\" not found for de-registering with trigger list" )
224 }
225}
226
227
228
229
230} // namespace [alib::threads::model]
231
232#endif // !defined(ALIB_DOX)
233
#define ALIB_WARNING(...)
Definition alib.hpp:981
#define ALIB_MESSAGE(...)
Definition alib.hpp:982
#define ALIB_ERROR(...)
Definition alib.hpp:980
#define ALIB_LOCK
#define ALIB_DBG(...)
Definition alib.hpp:457
ALIB_API HashMap< std::thread::id, Thread * > threadMap
constexpr CString NewLine()
Definition cstring.hpp:528
threads::Thread Thread
Type alias in namespace alib.
Definition thread.hpp:390
time::Ticks Ticks
Type alias in namespace alib.
Definition ticks.hpp:114
NLocalString< 256 > NString256
Type alias name for TLocalString<nchar,256> .
NLocalString< 4096 > NString4K
Type alias name for TLocalString<nchar,4096> .