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