ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
DedicatedWorker Class Reference

Description:

Attention
This class is part of experimental module ALib ThreadModel and thus is experimental in respect to interface, functionality, and documentation.

This class implements a worker thread that receives jobs from a private queue. Jobs can have a different Priority, and thus may not be executed in the order of insertion. This concept comprises a very simple scheduling approach and should not be overused. In the end, any multithreading software has to be designed in a way that a job queue never grows to a high level, so that all jobs will be processed in a maximum time.

This class is virtual, and it is designed for inheritance: Using software has to derive custom types that provide the custom functionality.

Jobs are represented with the protected type Job.

Derived custom types need to duly fulfill a certain contract of interaction. In short, the following rules are given:

  1. Derived types define jobs by exposing a type derived from virtual class Job. Preferably, the derived types are designed to be public inner types because they usually explicitly belong to the scope of an DedicatedWorker.
    A Job - besides its inherited type-ID - contains input data to the DedicatedWorker as well as output data to the requesting thread. (Both are optional, as can be seen, for example, with the very simple built-in type JobTrigger that has neither input nor output data.)

  2. The derived type exposes interface methods according to the different jobs available to be scheduled. Here, the Job is constructed and returned to the caller, usually as a reference in its derived form.
    Thus, the worker has knowledge of what is to be expected when extracting a job from its queue, and with that is able to safely cast the virtual type "up" to the according derived type.

  3. The Jobs returned by the interface (usually) contain some sort of thread-safe acknowledge mechanics, for example, a Promise or a Condition that a caller can decide to wait on.

  4. Disposal of Job instances has to be explicitly performed by the thread that schedules a job. There are two methods provided for doing it. The first is DeleteJob, which performs instant deletion. This can be called after the job was processed. The latter has to be awaited, as described in the previous paragraph. The second is DeleteJobDeferred, which covers the case that the caller decides not to wait for an acknowledgment. Here, the instance must not be deleted because the DedicatedWorker will access it when it is extracted from the queue (or already is working on it). Thus, this second version schedules a deletion job and lets the worker do it.
    The deletion job has a low priority of DeferredDeletion. Jobs scheduled with an even lower priority must not be deferred-deleted.
    Note
    A similar concept of deferred-deletion is provided with sibling type ThreadPool. There, deferred-deletion has a huge negative impact on performance of the pool. With type DedicatedWorker, the negative impact of deferred deletion is negligible.

  5. The custom types Job types have to likewise fulfill a few contractual rules. Those are given with the type's reference documentation.

Starting and Stopping:

The class inherits type Thread as a protected base type. With that, the conventional methods to start and stop a thread are hidden.
Starting and stopping a DedicatedWorker is instead performed by adding, respectively removing an instance of this type to singleton class DWManager.

Triggering:

This type implements abstract interface Triggered. If this is considered useful by a derived type, then three things have to be performed:

  • The parameterless job JobTrigger has to be processed in the overridden method process.
  • Field triggerDuration has to be adjusted as required, or as an alternative, the method triggerPeriod has to be overridden. The latter might allow more flexibility to adjust the trigger time dependent on certain custom states.
  • The instance of the custom DedicatedWorker has to be registered by calling method Trigger::Add.

Definition at line 205 of file dedicatedworker.hpp.

#include <dedicatedworker.hpp>

Inheritance diagram for DedicatedWorker:
[legend]
Collaboration diagram for DedicatedWorker:
[legend]

Inner Type Index:

struct  JobDeleter
 The job sent by method DeleteJobDeferred. More...
 
struct  JobStop
 The stop job sent by method ScheduleStop. More...
 
struct  JobTrigger
 
struct  QueueElement
 Container element of the queue. More...
 

Public Field Index:

int DbgMaxQueuelength
 

Public Method Index:

 DedicatedWorker (const alib::String &threadName)
 
 ~DedicatedWorker () override
 Destructor.
 
void DeleteJob (Job &job)
 
void DeleteJobDeferred (Job &job)
 
virtual const CString GetName () const
 
int Load () const
 
void ScheduleStop (Priority priority)
 
bool StopIsExecuted ()
 
bool StopIsScheduled ()
 

Protected Field Index:

int length
 The current number of jobs in the queue.
 
DWManagermanager
 needed as we inherit TCondition
 
List< HeapAllocator, QueueElementqueue
 
alib::Ticks statLastJobExecution
 
bool stopJobExecuted = false
 Flag which is set when the stop-job was executed.
 
bool stopJobPushed = false
 Flag which is set when the stop-job was scheduled.
 
Ticks::Duration triggerDuration = Ticks::Duration::FromSeconds(1)
 
- Protected Field Index: inherited from Thread
std::thread * c11Thread =nullptr
 The internal C++ thread object.
 
ThreadID id =0
 The id of the thread.
 
AString name
 The name of the thread.
 
std::thread::id nativeID
 The internal C++ thread id.
 
Runnablerunnable =nullptr
 The runnable to execute.
 
State state = State::Unstarted
 Internal flag to indicate if the thread is alive.
 
- Protected Field Index: inherited from Triggered
const String Name
 
- Protected Field Index: inherited from TCondition< TDerived >
std::condition_variable conditionVariable
 The condition variable used for blocking and notification.
 
DbgConditionAsserter Dbg
 The debug tool instance.
 
std::mutex mutex
 The mutex used for locking this instance.
 

Protected Method Index:

bool isConditionMet ()
 
std::pair< Job *, bool > pop ()
 
virtual bool process (Job &vjob)
 
ALIB_API void pushAndRelease (QueueElement &&jobInfo)
 
virtual ALIB_API void Run () override
 
template<typename TJob , typename... TArgs>
TJob & Schedule (Priority priority, TArgs &&... args)
 
template<typename TJob , typename... TArgs>
TJob & schedule (Priority priority, bool keepJob, TArgs &&... args)
 
template<typename TJob , typename... TArgs>
void ScheduleVoid (Priority priority, TArgs &&... args)
 
virtual void trigger () override
 
virtual Ticks::Duration triggerPeriod () override
 
- Protected Method Index: inherited from Thread
ALIB_API Thread (const String &pName=EMPTY_STRING)
 
 Thread (const Thread &)=delete
 Deleted copy constructor.
 
ALIB_API Thread (Runnable *target, const String &pName=EMPTY_STRING)
 
virtual ALIB_API ~Thread () override
 
ThreadID GetID () const
 
std::thread::id GetNativeID () const
 
State GetState ()
 
bool IsAlive ()
 
virtual ALIB_API void Join ()
 
virtual void SetName (const String &newName)
 
virtual ALIB_API void Start ()
 
- Protected Method Index: inherited from Runnable
virtual ~Runnable ()
 Virtual destructor.
 
- Protected Method Index: inherited from Triggered
 Triggered (const String &pName)
 
virtual ~Triggered ()
 Virtual empty destructor. Needed with any virtual class.
 
- Protected Method Index: inherited from TCondition< TDerived >
 TCondition (const String &dbgName)
 
void Acquire (ALIB_DBG_TAKE_CI)
 
TDerived & cast ()
 
void Release (ALIB_DBG_TAKE_CI)
 
void ReleaseAndNotify (ALIB_DBG_TAKE_CI)
 
void ReleaseAndNotifyAll (ALIB_DBG_TAKE_CI)
 
void WaitForNotification (ALIB_DBG_TAKE_CI)
 
void WaitForNotification (const Ticks &wakeUpTime, const CallerInfo &ci)
 
void WaitForNotification (const Ticks::Duration &maxWaitTimeSpan, const CallerInfo &ci)
 
void WaitForNotification (const Ticks::Duration::TDuration &maxWaitTimeSpan, const CallerInfo &ci)
 

Additional Inherited Members

- Protected Type Index: inherited from Thread
enum class  State {
  Unstarted = 0 , Started = 1 , Running = 2 , Done = 3 ,
  Terminated = 4
}
 
- Protected Static Method Index: inherited from Thread
static ALIB_API ThreadGet (std::thread::id nativeID)
 
static ThreadGetCurrent ()
 
static ALIB_API ThreadGetMain ()
 
static void Sleep (const Ticks::Duration &duration)
 
static void Sleep (const Ticks::Duration::TDuration &duration)
 
static void SleepMicros (int64_t microseconds)
 
static void SleepMillis (int milliseconds)
 
static void SleepNanos (int64_t nanoseconds)
 
static void SleepUntil (const Ticks &time)
 
static void YieldToSystem ()
 

Friends And Related Entity Details:

◆ DWManager

friend class DWManager
friend

Type alias in namespace alib.

Definition at line 209 of file dedicatedworker.hpp.

◆ lang::Owner< DedicatedWorker & >

friend class lang::Owner< DedicatedWorker & >
friend

Definition at line 209 of file dedicatedworker.hpp.

◆ threads::TCondition< DedicatedWorker >

friend struct threads::TCondition< DedicatedWorker >
friend

Definition at line 209 of file dedicatedworker.hpp.

Field Details:

◆ DbgMaxQueuelength

int DbgMaxQueuelength

The maximum number of jobs in the queue at any time. Available only with debug-compilations.

Definition at line 423 of file dedicatedworker.hpp.

◆ length

int length
protected

The current number of jobs in the queue.

Definition at line 259 of file dedicatedworker.hpp.

◆ manager

DWManager& manager
protected

needed as we inherit TCondition

Reference to DWManager instance.

Definition at line 221 of file dedicatedworker.hpp.

◆ queue

List<HeapAllocator, QueueElement> queue
protected

The queue of jobs. This is a simple list, instead of a 'real' priority queue. This design decision was taken because there should never be too many jobs queued and the naive iteration is more efficient than using a 'real' priority queue type.

Definition at line 256 of file dedicatedworker.hpp.

◆ statLastJobExecution

alib::Ticks statLastJobExecution
protected

Statistical information: Point in time of last job execution. In case no job was executed, yet, this is the creation time of the object.

Definition at line 225 of file dedicatedworker.hpp.

◆ stopJobExecuted

bool stopJobExecuted = false
protected

Flag which is set when the stop-job was executed.

Definition at line 231 of file dedicatedworker.hpp.

◆ stopJobPushed

bool stopJobPushed = false
protected

Flag which is set when the stop-job was scheduled.

Definition at line 228 of file dedicatedworker.hpp.

◆ triggerDuration

Ticks::Duration triggerDuration = Ticks::Duration::FromSeconds(1)
protected

If this DedicatedWorker is (in addition) attached to a DWManager as a triggered object, this duration is returned by overridden method Triggered::triggerPeriod to determine the interval between scheduling two trigger jobs.
Defaults to one second, which usually is changed by a derived type.

Definition at line 238 of file dedicatedworker.hpp.

Constructor(s) / Destructor Details:

◆ DedicatedWorker()

DedicatedWorker ( const alib::String & threadName)
inline

Constructor taking a thread name that is passed to parent class Thread.

Parameters
threadNameThe name of this thread. The string's data has to survive this threads' lifespan.

Definition at line 433 of file dedicatedworker.hpp.

◆ ~DedicatedWorker()

~DedicatedWorker ( )
inlineoverride

Destructor.

Definition at line 444 of file dedicatedworker.hpp.

Here is the call graph for this function:

Method Details:

◆ DeleteJob()

void DeleteJob ( Job & job)
inline

Deletes a data object previously received via method schedule, one of its siblings, or scheduling methods of derived types.

The latter might have names that do not contain the term "schedule" but still internally create and return data objects. Any object returned needs to be deleted.

Attention
Deletion of data objects must not be done by the caller of a schedule-method before the job is processed by this DedicatedWorker. For example, if a derived type's interface returns an job instance of type JPromise, then such a result must only be deleted once the promise is fulfilled.

This can be cumbersome in case the calling thread is just not interested in the result. For this case, the alternative method # DeleteJobDeferred is given.

Parameters
jobThe job returned when scheduling a command.

Definition at line 498 of file dedicatedworker.hpp.

Here is the call graph for this function:

◆ DeleteJobDeferred()

void DeleteJobDeferred ( Job & job)
inline

Same as DeleteJob but schedules the deletion to be performed. Scheduling is done with Priority::DeferredDeletion.
This assures that the job deletion is performed after the job execution.

This method is useful when the thread that schedules a job with this DedicatedWorker is not interested in the result, i.e., does not perform an asynchronous wait. Custom jobs where this is rather usually the case, should be exposed in two versions, one that returns a result and another that does not. With the second, the derived DedicatedWorker would delete the given shared data with processing the job. If this is offered, then this method does not need to be called (and cannot be called because the caller does not receive any data).

Parameters
jobThe job object to delete.

Definition at line 519 of file dedicatedworker.hpp.

Here is the call graph for this function:

◆ GetName()

virtual const CString GetName ( ) const
inlinevirtual

Returns the name of the thread. An ALib thread can have any name that is given to it and such name can be changed any time. In fact, names are for debugging and logging purposes only.

Returns
Returns the name of the thread.

Reimplemented from Thread.

Definition at line 225 of file thread.hpp.

◆ isConditionMet()

bool isConditionMet ( )
inlineprotected

Mandatory method needed and invoked by templated base type TCondition.

Returns
true if field queue is not empty, false otherwise.

Definition at line 263 of file dedicatedworker.hpp.

◆ Load()

int Load ( ) const
inline

Returns the current number of jobs in the queue.

Returns
The number of jobs to process, including any currently processed one.

Definition at line 457 of file dedicatedworker.hpp.

◆ pop()

std::pair< Job *, bool > pop ( )
protected

Moves the job of highest priority out of the queue. Blocks the thread until a job is available.

Returns
The job with the highest priority.

Definition at line 237 of file dedicatedworker.cpp.

Here is the call graph for this function:

◆ process()

virtual bool process ( Job & vjob)
inlineprotectedvirtual

This virtual method is called during thread execution (method Run) for each job extracted from the internal job-queue.
While this default-implementation is empty, internally, before a call to this method, the following jobs are already detected and processed:

A derived type may decide to call this parent method before or after checking for its own jobs. If the call returns true, then the job was processed.

It is also allowed to implement a custom processing, for example, with JobStop and thus not to call this version for the internal jobs covered by the custom version.

It is important that overridden versions do return the true if the job was processed and false if not.

Parameters
vjobThe job to process.
Returns
true if the job was processed, false if not.

Definition at line 417 of file dedicatedworker.hpp.

◆ pushAndRelease()

void pushAndRelease ( QueueElement && jobInfo)
protected

Pushes the given jobInfo into the priority queue that this class implements. When invoked, the thread-manager as well as this instance are both locked.

Parameters
jobInfoThe job, the priority, and a flag if this job is to be deleted automatically.

Definition at line 209 of file dedicatedworker.cpp.

Here is the call graph for this function:

◆ Run()

void Run ( )
overrideprotectedvirtual

This implementation of method Thread::Run constitutes a very simple loop that waits for jobs in the queue and passes them to likewise virtual method process. The (only) condition to continuing the loop is that the flag stopJobExecuted is false. This flag will be set by the internal job type JobStop which is pushed with the method ScheduleStop.

Reimplemented from Thread.

Definition at line 259 of file dedicatedworker.cpp.

Here is the call graph for this function:

◆ Schedule()

template<typename TJob , typename... TArgs>
TJob & Schedule ( Priority priority,
TArgs &&... args )
inlineprotected

Pushes a custom job into the priority queue.
The job is returned to the caller to be able to await results. It is the responsibility of the caller to pass the job to either method DeleteJob or DeleteJobDeferred for disposal.

Template Parameters
TJobThe job type to create and schedule.
TArgsTypes of the variadic arguments args that construct TJob.
Parameters
priorityThe priority of the job.
argsVariadic arguments forwarded to the constructor of TJob.
Returns
The scheduled job.

Definition at line 357 of file dedicatedworker.hpp.

Here is the call graph for this function:

◆ schedule()

template<typename TJob , typename... TArgs>
TJob & schedule ( Priority priority,
bool keepJob,
TArgs &&... args )
inlinenodiscardprotected

Pushes a custom job into the priority queue.
This method is protected because derived types should provide dedicated "speaking" interfaces for scheduling jobs. Those are typically short inline methods, which/ are optimized out by C++ compilers.

Template Parameters
TJobThe job type as well as the job's shared data type.
TArgsTypes of the variadic arguments args that construct TJob.
Parameters
priorityThe priority of the job.
keepJobDenotes whether the job should be deleted after execution or not.
argsVariadic arguments forwarded to the constructor of TJob.
Returns
The shared data. Deletion of the object is the responsibility of the caller and is to be done by either invoking DeleteJob or DeleteJobDeferred.

Definition at line 326 of file dedicatedworker.hpp.

Here is the call graph for this function:

◆ ScheduleStop()

void ScheduleStop ( Priority priority)
inline

Schedules a stop job into this thread's job queue. When this job is processed from the queue, this thread will exit.

Parameters
priorityThe priority of the job. Use Lowest if it is assured that no other jobs will be pushed.

Definition at line 475 of file dedicatedworker.hpp.

Here is the call graph for this function:

◆ ScheduleVoid()

template<typename TJob , typename... TArgs>
void ScheduleVoid ( Priority priority,
TArgs &&... args )
inlineprotected

Pushes a custom job into the priority queue. In contrast to the sibling method Schedule, the job is not returned by this method. Instead, it is scheduled for automatic disposal after execution.

Template Parameters
TJobThe job type to create and schedule.
TArgsTypes of the variadic arguments args that construct TJob.
Parameters
priorityThe priority of the job.
argsVariadic arguments forwarded to the constructor of TJob.

Definition at line 368 of file dedicatedworker.hpp.

Here is the call graph for this function:

◆ StopIsExecuted()

bool StopIsExecuted ( )
inline

Returns the state of the internal flag, which is set with the execution of ScheduleStop.

Returns
true, if the ScheduleStop was processed, false otherwise.

Definition at line 465 of file dedicatedworker.hpp.

◆ StopIsScheduled()

bool StopIsScheduled ( )
inline

Returns the state of the internal flag, which is set with the invocation of ScheduleStop.

Returns
true, if the ScheduleStop was called, false otherwise.

Definition at line 461 of file dedicatedworker.hpp.

◆ trigger()

virtual void trigger ( )
inlineoverrideprotectedvirtual

Schedules JobTrigger need to implement this function and perform their trigger actions here.

Implements Triggered.

Definition at line 383 of file dedicatedworker.hpp.

Here is the call graph for this function:

◆ triggerPeriod()

virtual Ticks::Duration triggerPeriod ( )
inlineoverrideprotectedvirtual

Return the sleep time, between two trigger events. Precisely, this method is called after trigger has been executed and defines the next sleep time.

Returns
The desired sleep time between two trigger events.

Implements Triggered.

Definition at line 379 of file dedicatedworker.hpp.


The documentation for this class was generated from the following files: