ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
threadpool.inl
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_threadmodel of the \aliblong.
4///
5/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8ALIB_EXPORT namespace alib {
9
10/// This is the namespace of \alibmod <b>"ThreadModel"</b>. Please refer to the
11/// \ref alib_mod_threadmodel "Programmer's Manual" of this module for information
12/// about how the types found in this namespace are used.
13/// \attention This module is not in a stable and consistent state, yet.
14/// Instead, it is considered experimental.
15namespace threadmodel {
16
17//==================================================================================================
18/// \attention This class belongs to module \alib_threadmodel, which is not in a stable and
19/// consistent state, yet.
20/// Also, this type is considered experimental.
21///
22/// Instances of this thread-class are created by \alib{threadmodel;ThreadPool}s.
23/// Applications may extend this class and override method #PrepareJob.
24//==================================================================================================
25struct PoolWorker : protected Thread {
26 friend class ThreadPool;
27 ThreadPool& threadPool; ///< The pool that this instance belongs to.
28
29#if ALIB_STRINGS
30 String16 nameBuffer; ///< Buffer to store the thread name given with construction.
31
32 /// Constructor.
33 /// @param pThreadPool The pool that constructed us.
34 /// @param threadName The name of this thread (for logging and diagnosis)
35 PoolWorker(ThreadPool& pThreadPool, const character* threadName )
36 : Thread(threadName)
37 , threadPool(pThreadPool)
38 , nameBuffer(threadName)
39 { SetName(nameBuffer); } // fix the name to local pointer
40#else
42 : Thread("Poolworker")
43 , threadPool(ptp)
44 {}
45#endif
46
47 /// This default implementation does nothing. Derived types may dynamically cast the
48 /// parameter \p{job} to a known custom type and, for example, attach custom data found in
49 /// a derived version of this class.
50 ///@param job The job to prepare.
51 virtual void PrepareJob(Job* job) { (void) job; }
52
53 /// Implementation of \alib{threads;Thread::Run}. Retrieves jobs from the pool, invokes
54 /// #PrepareJob, and then calls \alib{threadmodel;Job::Do}.
55 void Run() override;
56
57}; // class PoolWorker
58
59//==================================================================================================
60/// \attention This class belongs to module \alib_threadmodel, which is not in a stable and
61/// consistent state, yet.
62/// Also, this type is considered experimental.
63///
64/// This class provides a configurable and scalable thread pooling mechanism for managing
65/// concurrent job execution.
66/// It supports fixed or dynamically resizing thread pools to balance workload and optimize
67/// resource usage, along with several key methods to schedule, manage, and monitor job execution.
68///
69/// ### Key Features
70/// 1. <b>%Thread Pool Management</b>:<br>
71/// - Supports fixed-size and dynamically resizable thread pools.
72/// - Dynamic resizing is handled through customizable parameters found in the struct
73/// \alib{threadmodel::ThreadPool;ResizeStrategy}.
74/// - Automatically adjusts the number of threads based on workload.
75///
76/// 2. <b>%Jobs</b>:<br>
77/// The worker-threads managed by the pool are processing \alib{threadmodel;Job} objects,
78/// which<br>
79/// a) Carry the data needed for processing, and<br>
80/// b) Optionally provide synchronization mechanics that allow a caller to wait until
81/// a job was processed or periodically test for completion.
82///
83/// Allocation and life-cycle management of jobs is efficiently implemented leveraging
84/// the mechanics provided by the module \alib_monomem.
85///
86/// 3. <b>Synchronization and %Job-Cleanup</b>:<br>
87/// Provides \alib{threadmodel;ThreadPool::Sync;a method to synchronize} all worker threads
88/// to ensure that processing continues only after a certain set of jobs has been executed.
89/// <br><br>
90///
91/// 4. <b>Worker Management and Monitoring</b>:<br>
92/// - Supports querying idle worker status and actively running threads.
93/// - Debugging options to analyze job types and execution states.
94///
95/// @see Chapter \ref alib_thrmod_threadpool of this module's Programmer's Manual
96/// provides a quick source code sample that demonstrates the use this class.
97//==================================================================================================
98class ThreadPool : protected TCondition<ThreadPool>
99#if ALIB_DEBUG_CRITICAL_SECTIONS
101#endif
102
103{
104 friend struct PoolWorker;
105 friend struct threads::TCondition<ThreadPool>;
106
107 public:
108 /// The set of management parameters that determine how a thread pool balances the number
109 /// of worker threads.
111 {
112 friend class ThreadPool;
113
114 /// The modes, fixed or automatic.
115 enum class Modes
116 {
117 /// The number of threads is fixed.
119
120 /// The number of threads is increased when the load increases and
121 /// decreased when the load decreases.
123 };
124
125 /// The mode of operation.
127
128 /// If #Mode equals \b Fixed, this is used and all other parameters are ignored.
129 /// If #Mode equals \b Auto, this field gives the maximum number of workers that are
130 /// run in parallel.
132
133 /// The minimum number of threads to keep alive.
134 int WorkersMin = 0;
135
136 /// A threshold in percent that determines at which overload factor the number of threads
137 /// is increased.
138 /// Defaults to \c 300%. For example, this means if the pool currently holds 10 threads,
139 /// then new threads are created when the load increases to \c 30 unprocess jobs.
141
142 /// A threshold in percent that determines at which underload factor the number of threads
143 /// are decreased.
144 /// Defaults to \c 50%.
145 /// For example, \c 30% this means that if 70% of the threads are idle the number of
146 /// threads is decreased.
148
149 /// The duration of that the pool has to be overloaded before an increase of threads
150 /// starts.
151 /// Defaults to zero time interval.
152 Ticks::Duration IncreaseSchedule = Ticks::Duration::FromAbsoluteMilliseconds(0);
153
154 /// The duration of that the pool has to be underloaded before a decrease of threads starts.
155 /// Defaults to 500ms.
156 Ticks::Duration DecreaseSchedule = Ticks::Duration::FromAbsoluteMilliseconds(500);
157
158 protected:
159
160 /// Calculates the target size, depending on the parameters set in this struct and
161 /// the actual values passed.
162 /// @param currentWorkers The number of threads currently in the pool.
163 /// @param idleWorkers The size of the subset of threads currently idle.
164 /// @param load The number of jobs currently queued.
165 /// @param lastChangeTime Time point of last increase or decrease.
166 /// @return The new target size.
167 inline
168 int GetSize( int currentWorkers , int idleWorkers, int load,
169 Ticks& lastChangeTime ) {
170 int target= currentWorkers;
171
172 // fixed mode? -> nothing to do
173 if (Mode == Modes::Fixed)
174 { target= WorkersMax; }
175
176 // check bounds
177 else if( target < WorkersMin ) { target= WorkersMin; }
178 else if( target > WorkersMax ) { target= WorkersMax; }
179
180 // increase?
181 else if( lastChangeTime.Age() >= IncreaseSchedule
182 && (load >= (currentWorkers * IncreaseThreshold / 100) ) )
183 { target = (std::min)(WorkersMax, currentWorkers + 1); }
184
185 // decrease?
186 else if( lastChangeTime.Age() >= DecreaseSchedule
187 && (currentWorkers - idleWorkers) <= (currentWorkers * DecreaseThreshold / 100) ) {
188 target = (std::max)(WorkersMin, currentWorkers - 1);
189 if ( target == 0 && load > 0)
190 target= 1;
191 }
192
193 // that's it
194 if (target != currentWorkers)
195 lastChangeTime.Reset();
196 return target;
197 }
198 };
199
200
201 protected:
202 /// Mono allocator. Used for jobs and by PoolWorkers.
204
205 /// Pool allocator. Used for job objects.
207
208 /// The list of worker threads.
210
211 /// The counted number of currently of workers.
213
214 /// The counted number of currently idle workers.
215 int ctdIdle =0;
216
217 /// The point in time of the last change of thread size.
219
220 /// A number that is increased with the creation of new workers and added to their
221 // \alib{threads;Thread::GetName;thread name}.
223
224 #if ALIB_DEBUG
225 /// Entry in the field #DbgKnownJobs.
227 {
228 const std::type_info* TID; ///< The job type.
229 size_t JobSize; ///< The size of the job object.
230 size_t Usage; ///< Counter of scheduled jobs of this type.
231 };
232
233 /// Serves as template parameter \p{TValueDescriptor} of field #DbgKnownJobs.
235 const std::type_info* >
236 {
237 /// Mandatory function to implement.
238 /// @param entry The table entry to extract the key from.
239 /// @return The key portion of the given \p{entry}.
240 const std::type_info* Key(DbgKnownJobsEntry& entry) const { return entry.TID; }
241 };
242
243 /// Table of known job types and their sizes.
246 #endif
247
248 /// Special synchronization job. Pushed with #Sync and #DeleteJobDeferred.
249 /// With the latter, field #JobToDelete will be given, otherwise this is nulled.
250 struct JobSyncer : Job
251 {
252 /// Optionally a job to be deleted.
254
255 /// Constructor.
256 /// @param job The job that is scheduled to be deleted.
258 : Job(typeid(JobSyncer))
259 , JobToDelete(job) {}
260
261 /// Overrides the parent function as necessary.
262 /// @return The sizeof this derived type.
263 virtual size_t SizeOf() override { return sizeof(JobSyncer); }
264 };
265
266 //================================================================================================
267 // The queue
268 //================================================================================================
269 /// Container element of the queue.
271 {
272 Job* job; ///< The job.
273 bool keep; ///< If true, the job is not deleted by the processing worker,
274 ///< but has to be deleted by the caller.
275 };
276
277 /// The queue of jobs.
279
280
281 /// The number of Jobs that have been scheduled during the lifetime of this instance.
283
284 /// The number of jobs currently in the queue.
285 int ctdOpenJobs {0};
286
287 /// Mandatory method needed and invoked by templated base type \alib{threads;TCondition}.
288 /// @return \c true if the field #queue is not empty and either no sync-job is next or
289 /// all are idle.
291 return queue.IsNotEmpty()
292 && ( queue.back().job->ID != typeid(JobSyncer)
293 || ctdIdle == ctdWorkers );
294 }
295
296 /// Pushes the given \p{cmd} into the priority queue that this class implements.
297 /// @param entry The Job and the deletion flag.
299 // insert before found
300 queue.emplace_front( entry );
301 ++ctdOpenJobs;
303
304 ALIB_MESSAGE( "TMOD/QUEUE", "{} Job({}) pushed",
305 this, &entry.job->ID )
306
308 }
309
310 /// Set if the last thread is terminated and #ctdWorkers goes to \c 0.
311 /// This thread is joined by #Shutdown or when a new thread is added.
313
314 /// Moves the job of highest priority out of the queue.
315 /// Blocks the thread until a job is available.
316 /// @param worker The instance that called this method.
317 /// @return The job with the highest priority.
319
320 /// Internal method that adds a thread. Must only be called when acquired.
322 void addThread();
323
324 /// Implementation of #Schedule and #ScheduleVoid.
325 /// @tparam TJob The job type to create and schedule.
326 /// @tparam TArgs Types of the variadic arguments \p{args} that construct \p{TJob}.
327 /// @param keepJob Denotes whether the job should be deleted after execution or not.
328 /// @param args Variadic arguments forwarded to the constructor of \p{TJob}.
329 /// @return The scheduled job.
330 template<typename TJob, typename... TArgs>
331 [[nodiscard]]
332 TJob* schedule( bool keepJob, TArgs&&... args ) {
334 // first check if this pool is active (has threads)
335 if (ctdWorkers == 0) {
336 ALIB_ASSERT_ERROR( Strategy.WorkersMax > 0
338 || Strategy.WorkersMax > 0 ), "TMOD/STRGY",
339 "No threads to schedule job. Strategy values:\n"
340 " WorkersMax: {}\n"
341 " Strategy.Mode: ",
342 Strategy.WorkersMax ,
343 Strategy.Mode == ResizeStrategy::Modes::Auto ? "Auto" : "Fixed" )
344
345 addThread();
346 }
347 TJob* job= pool().New<TJob>( std::forward<TArgs>(args)... );
348 ALIB_ASSERT_ERROR( job->SizeOf()==sizeof(TJob), "TMOD",
349 "{} error in schedule: Job size mismatch. Expected {} "
350 "while virtual method SizeOf returns {}.\n"
351 "Override this method for job-type <{}>", this, sizeof(TJob), job->SizeOf(), &typeid(*job) )
352
353 ALIB_ASSERT_ERROR( Strategy.WorkersMax > 0, "TMOD",
354 "{} error: Job pushed while this pool is shut down already. "
355 "(Strategy.WorkersMax == 0) ", this )
356
357 #if ALIB_DEBUG
358 auto pair= DbgKnownJobs.EmplaceIfNotExistent( DbgKnownJobsEntry{ &typeid(TJob),
359 sizeof(TJob), 0 } );
360 ++pair.first.Value().Usage;
361 #endif
362
363 pushAndRelease( {job, keepJob} );
364 return job;
365 }
366
367 public:
368 /// The parameters used for scaling the amount of worker threads.
369 /// The values herein can be changed from outside with direct access.
371
372 /// The wait-time slice used by method #WaitForAllIdle.
373 Ticks::Duration IdleWaitTime = Ticks::Duration::FromAbsoluteMicroseconds(50);
374
375 /// Constructor.
376 /// Initializes the thread pool with default settings for field #Strategy.
378
379 #if ALIB_DEBUG_CRITICAL_SECTIONS
380 /// Destructor. Cleans up and shuts down the thread pool.
382
383 /// @return \c true if the lock is acquired (in non-shared mode), \c false otherwise.
384 ALIB_DLL bool DCSIsAcquired() const override;
385
386 /// @return \c true if the lock is shared-acquired (by at least any thread).
387 /// Otherwise, returns \c false.
388 ALIB_DLL bool DCSIsSharedAcquired() const override;
389 #else
390 virtual
392 #endif
393
396
397 /// Returns the mono allocator used by the thread pool.
398 /// The pool has to be acquired before using it.
399 /// @return The mono allocator.
401
402 /// Returns the pool allocator used by the thread pool.
403 /// The pool has to be acquired before using it.
404 /// @return The pool allocator.
406
407 /// Creates a worker using the #pool allocator. Derived types may override this method
408 /// and create a derived \alib{threadmodel;PoolWorker}-type.
409 /// @return A pool worker.
411
412 /// Destructs the given pool worker.
413 /// Derived types may add further logic here.
414 /// @param poolWorker The pool worker to destruct and delete.
415 virtual void DisposeWorker( PoolWorker* poolWorker );
416
417 /// Just an alias to
418 /// \https{Empty Base Optimization,en.cppreference.com/w/cpp/thread/thread/hardware_concurrency}.
419 ///
420 /// While the specification says
421 /// <em>"If the value is not well-defined or not computable, returns \c 0"</em>,
422 /// this method returns \c 1 in this case.
423 ///
424 /// Used as the default value for constructor parameter \p{pWorkersMax}.
425 /// @return Returns the maximum number of threads that can be expected to run concurrently.
426 static int HardwareConcurrency() noexcept
427 { return int(std::thread::hardware_concurrency()); }
428
429 /// Returns the current number of worker threads.
430 /// @return The number of jobs to process, including any currently processed one.
431 int CountedWorkers() const { return ctdWorkers; }
432
433 /// Returns the current number of idle workers.
434 /// @return The number of workers waiting on jobs to process.
435 int CountedIdleWorkers() const { return ctdIdle; }
436
437 /// Checks if all workers are idle.
438 /// @return \c true if the number of idle workers equals the number of workers,
439 /// \c false otherwise.
440 bool IsIdle() const { return ctdIdle == ctdWorkers; }
441
442 /// Pushes a job of the custom type \p{TJob} into the priority queue.<br>
443 /// The job is returned to the caller to be able to await results.
444 /// It is the responsibility of the caller to pass the job to either method
445 /// #DeleteJob or #DeleteJobDeferred for disposal.
446 /// Note that the latter causes a #Sync on this pool, while with use of the former,
447 /// the fulfilment of the returned job object has to be awaited first.
448 /// @tparam TJob The job type to create and schedule.
449 /// @tparam TArgs Types of the variadic arguments \p{args} that construct \p{TJob}.
450 /// @param args Variadic arguments forwarded to the constructor of \p{TJob}.
451 /// @return A reference to the job object for the caller to await results.
452 template<typename TJob, typename... TArgs>
453 [[nodiscard]]
454 TJob& Schedule( TArgs&&... args )
455 { return *schedule<TJob, TArgs...>( true, std::forward<TArgs>(args)... ); }
456
457 /// Pushes a job of the custom type \p{TJob} into the priority queue.
458 /// In contrast to the sibling method #Schedule, the job is not returned by this method.
459 /// Instead, it is scheduled for automatic disposal after execution.
460 /// @tparam TJob The job type to create and schedule.
461 /// @tparam TArgs Types of the variadic arguments \p{args} that construct \p{TJob}.
462 /// @param args Variadic arguments forwarded to the constructor of \p{TJob}.
463 template<typename TJob, typename... TArgs>
464 void ScheduleVoid( TArgs&&... args )
465 { (void) schedule<TJob, TArgs...>( false, std::forward<TArgs>(args)... ); }
466
467 /// Deletes a job object previously scheduled with #Schedule.
468 ///
469 /// \attention
470 /// The caller must not delete received job instances before they are processed.
471 ///
472 /// \attention
473 /// In case a caller does not want to wait longer, the method #DeleteJobDeferred is to be used,
474 /// which causes a #Sync on this pool.
475 /// Therefore, it is preferable to either wait on the job and use this method for deletion,
476 /// or to use the method #ScheduleVoid instead of #Schedule to not even get involved
477 /// with job-deletion.
478 ///
479 /// @param job The job returned from method #Schedule.
480 void DeleteJob(Job& job) {
482 auto size= job.SizeOf();
483 job.~Job();
484 pool.free(&job, size);
485 }
486
487 /// Same as #DeleteJob but schedules the deletion to be performed.
488 /// This method is useful when a job instance was received with the method #Schedule, but the
489 /// caller does not want to continue waiting for the execution of the job.<br>
490 /// If jobs indicate that they have been processed, then the method #DeleteJob is to be used.
491 ///
492 /// \attention Calling this method schedules a #Sync.
493 /// Therefore, the use of this method should be avoided.
494 ///
495 /// @see Methods #ScheduleVoid, #DeleteJob and #Sync.
496 /// @param job The job object to delete.
497 void DeleteJobDeferred(Job& job) { (void) schedule<JobSyncer>(false, &job); }
498
499 /// This method ensures all worker threads in the thread pool complete their currently running
500 /// jobs and also process all jobs that have been scheduled before a call to this method.
501 /// This forces synchronization such that no new jobs are processed until the
502 /// synchronization request is fulfilled.<br>
503 /// It is particularly useful for scenarios requiring a consistent state or ensuring all pending
504 /// asynchronous jobs are complete before proceeding.
505 ///
506 /// Consequently, a call to this method may inherently involve blocking the execution in the
507 /// pool until all prior tasks are finalized. While it is designed to work efficiently with the
508 /// thread pool mechanism, unnecessary or frequent calls to this method impose a performance
509 /// disadvantage.
510 ///
511 /// Invoking \b %Sync() schedules
512 /// \alib{threadmodel::ThreadPool;JobSyncer;a special synchronization job} in the queue of
513 /// this \b %ThreadPool.
514 /// Thus, the method is non-blocking and instantly returns.
515 ///
516 /// \par Necessity for Synchronization Explained with a Sample:
517 /// The requirement for synchronization is best illustrated with a practical scenario.
518 /// Consider a case where the main thread is responsible for scanning the filesystem.
519 /// For each file that meets certain criteria, a job is scheduled in the \b ThreadPool
520 /// to read the content of that file.
521 /// At this stage, the main thread is focused solely on scheduling file-reading jobs and
522 /// isn't directly processing the files.
523 ///
524 /// \par
525 /// Now, before the application proceeds to schedule further jobs, such as processing,
526 /// analyzing, or aggregating the file data, it is crucial to ensure that all file-reading
527 /// jobs have completed.
528 /// Without a synchronization mechanism, there is a risk that some worker threads are still
529 /// reading files while other threads - already assigned to the dependent processing tasks —
530 /// begin before the file data is available.
531 ///
532 /// \par
533 /// A call to \b %Sync() resolves this issue by ensuring that all file-reading jobs are
534 /// completed before any subsequent jobs that rely on their output are scheduled or processed.
535 /// This guarantees consistency, prevents race conditions, and ensures that no dependent
536 /// thread gets an incomplete or inconsistent dataset to work with.
537 /// In summary, synchronization acts as a safeguard in parallelized workflows where the
538 /// logical order of operations must be maintained across multiple threads, particularly
539 /// when tasks are interdependent.
540 ///
541 /// @see Method #DeleteJobDeferred, which likewise causes a synchronization.
542 void Sync() { (void) schedule<JobSyncer>(false, nullptr); }
543
544 #if DOXYGEN
545 /// Waits until all threads are idle.
546 /// @param timeout The maximum time to wait.
547 /// @param dbgWarnAfter The time after which a warning message will be printed to the
548 /// debug log if the timeout was reached.<br>
549 /// This parameter is only available in debug-compilations and thus
550 /// should be passed using macro \ref ALIB_DBG.
551 /// @return \c true if all threads are idle, \c false otherwise.
553 bool WaitForAllIdle( Ticks::Duration timeout,
554 Ticks::Duration dbgWarnAfter );
555 #else
556 ALIB_DLL bool WaitForAllIdle( Ticks::Duration timeout
557 ALIB_DBG(, Ticks::Duration dbgWarnAfter) );
558 bool WaitForAllIdle( Ticks::Duration::TDuration timeout
559 ALIB_DBG(, Ticks::Duration::TDuration dbgWarnAfter) )
560 { return WaitForAllIdle( Ticks::Duration(timeout) ALIB_DBG(,Ticks::Duration(dbgWarnAfter))); }
561
562 #endif
563
564 /// Removes all threads.
565 /// While this method waits that all jobs are finalized just as the method #WaitForAllIdle does,
566 /// it is recommended to #WaitForAllIdle explicitly, before this method is called.
567 /// This allows a more graceful shutdown with the possibility to take action on timeouts.
568 ///
569 /// If after the call to \b WaitForAllIdle no jobs were scheduled, this method is \b not #
570 /// supposed to block.
572 void Shutdown();
573
574 /// Returns the current number of jobs in the queue.
575 /// \note To get the overall number of unprocessed jobs, the difference between
576 /// #CountedWorkers and #CountedIdleWorkers has to be added.
577 /// However, under racing conditions, this difference might evaluated wrongly.
578 /// Therefore, if crucial, this pool has to be acquired before determining this.
579 /// @return The number of jobs to process, not including any currently processed one.
580 int CountedOpenJobs() const { return ctdOpenJobs; }
581
582 /// Returns the number of Jobs that have been scheduled during the lifetime of this instance.
583 /// This is a statistics method.
584 /// @return The number of jobs to process, including any currently processed one.
586
587 #if ALIB_DEBUG && ALIB_STRINGS
588 /// Writes the list of known jobs and their object sizes to the given target.
589 /// \par Availability
590 /// This function is available only with debug-compilations and if the module
591 /// \alib_strings is included in the\alibbuild.
592 /// @see Field DbgDumpKnownJobs.
593 ///
594 /// @param target The string to write to.
595 /// @param linePrefix A prefix string to each line. Defaults to two spaces.
596 /// @return The number of known jobs.
598 int DbgDumpKnownJobs(NAString& target, const NString& linePrefix= " " );
599 #endif
600
601}; // class ThreadPool
602
603} // namespace alib[::threadmodel]
604
605/// Type alias in namespace \b alib.
607
608/// Type alias in namespace \b alib.
610
611} // namespace [alib]
612
613//##################################################################################################
614// struct AppendableTraits<ThreadPool>
615//##################################################################################################
616
617#if ALIB_STRINGS
618// Faking all template specializations of namespace strings for doxygen into namespace
619// strings::APPENDABLES to keep the documentation of namespace string clean!
620namespace alib::strings {
621#if DOXYGEN
622namespace APPENDABLES {
623#endif
624
625/// Specialization of functor \alib{strings;AppendableTraits} for type \alib{files;File}.
627{
628 /// Writes some information about the given \b ThreadPool.
629 /// @param target The \b NAString that \b Append was invoked on.
630 /// @param tpool The thread pool instance.
631 void operator()( AString& target, const alib::threadmodel::ThreadPool& tpool );
632};
633
634#if DOXYGEN
635} // namespace alib::strings[APPENDABLES]
636#endif
637} // namespace [alib::strings]
638#endif
int ctdWorkers
The counted number of currently of workers.
Ticks::Duration IdleWaitTime
The wait-time slice used by method WaitForAllIdle.
ALIB_DLL bool DCSIsAcquired() const override
int ctdIdle
The counted number of currently idle workers.
PoolAllocator pool
Pool allocator. Used for job objects.
static int HardwareConcurrency() noexcept
void pushAndRelease(QueueEntry &&entry)
uinteger StatsCountedScheduledJobs() const
void Acquire(ALIB_DBG_TAKE_CI)
int nextWorkerID
A number that is increased with the creation of new workers and added to their.
MonoAllocator & GetAllocator()
virtual void DisposeWorker(PoolWorker *poolWorker)
TJob & Schedule(TArgs &&... args)
HashTable< MonoAllocator, DbgKnownJobsVD > DbgKnownJobs
Table of known job types and their sizes.
ALIB_DLL bool DCSIsSharedAcquired() const override
int ctdOpenJobs
The number of jobs currently in the queue.
ListPA< QueueEntry, Recycling::None > queue
The queue of jobs.
QueueEntry pop(PoolWorker *worker)
ALIB_DLL void addThread()
Internal method that adds a thread. Must only be called when acquired.
TJob * schedule(bool keepJob, TArgs &&... args)
PoolAllocator & GetPoolAllocator()
ALIB_DLL int DbgDumpKnownJobs(NAString &target, const NString &linePrefix=" ")
ALIB_DLL bool WaitForAllIdle(Ticks::Duration timeout, Ticks::Duration dbgWarnAfter)
friend struct PoolWorker
Type alias in namespace alib.
HashSet< MonoAllocator, PoolWorker * > workers
The list of worker threads.
ALIB_DLL ~ThreadPool() override
Destructor. Cleans up and shuts down the thread pool.
virtual PoolWorker * CreateWorker()
uinteger ctdStatJobsScheduled
The number of Jobs that have been scheduled during the lifetime of this instance.
MonoAllocator ma
Mono allocator. Used for jobs and by PoolWorkers.
Ticks timeOfLastSizeChange
The point in time of the last change of thread size.
void ScheduleVoid(TArgs &&... args)
Thread(const character *pName=A_CHAR(""))
Definition thread.inl:181
virtual void SetName(const character *newName)
Definition thread.inl:247
#define ALIB_MESSAGE(domain,...)
Definition alib.inl:1064
#define ALIB_DLL
Definition alib.inl:503
#define ALIB_EXPORT
Definition alib.inl:497
#define ALIB_LOCK
Definition alib.inl:1336
#define ALIB_DBG(...)
Definition alib.inl:853
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1066
#define ALIB_CALLER_PRUNED
Definition alib.inl:1024
containers::HashSet< TAllocator, T, THash, TEqual, THashCaching, TRecycling > HashSet
Type alias in namespace alib. See type definition alib::containers::HashSet.
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
LocalString< 16 > String16
Type alias name for TLocalString<character,16>.
containers::HashTable< TAllocator, TValueDescriptor, THash, TEqual, THashCaching, TRecycling > HashTable
Type alias in namespace alib. See type definition alib::containers::HashSet.
monomem::TPoolAllocator< MonoAllocator > PoolAllocator
strings::TString< nchar > NString
Type alias in namespace alib.
Definition string.inl:2198
strings::TAString< nchar, lang::HeapAllocator > NAString
Type alias in namespace alib.
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
threads::Thread Thread
Type alias in namespace alib.
Definition thread.inl:387
containers::List< T, PoolAllocator, TRecycling > ListPA
Type alias in namespace alib.
Definition list.inl:697
time::Ticks Ticks
Type alias in namespace alib.
Definition ticks.inl:79
threadmodel::ThreadPool ThreadPool
Type alias in namespace alib.
characters::character character
Type alias in namespace alib.
lang::uinteger uinteger
Type alias in namespace alib.
Definition integers.inl:152
threadmodel::PoolWorker PoolWorker
Type alias in namespace alib.
virtual size_t SizeOf()
Definition jobs.inl:95
Job(const std::type_info &id)
Definition jobs.inl:63
virtual ~Job()=default
Protected destructor.
virtual void PrepareJob(Job *job)
ThreadPool & threadPool
The pool that this instance belongs to.
friend class ThreadPool
Type alias in namespace alib.
PoolWorker(ThreadPool &pThreadPool, const character *threadName)
String16 nameBuffer
Buffer to store the thread name given with construction.
size_t Usage
Counter of scheduled jobs of this type.
size_t JobSize
The size of the job object.
const std::type_info * TID
The job type.
Serves as template parameter TValueDescriptor of field DbgKnownJobs.
const std::type_info * Key(DbgKnownJobsEntry &entry) const
Job * JobToDelete
Optionally a job to be deleted.
Container element of the queue.
friend class ThreadPool
Type alias in namespace alib.
int WorkersMin
The minimum number of threads to keep alive.
int GetSize(int currentWorkers, int idleWorkers, int load, Ticks &lastChangeTime)
TCondition(const character *dbgName)
void Release(ALIB_DBG_TAKE_CI)
void Acquire(ALIB_DBG_TAKE_CI)
void ReleaseAndNotify(ALIB_DBG_TAKE_CI)