10 bool IsExiting =
false;
11 bool IsFirstRun =
true;
12 std::chrono::time_point<std::chrono::system_clock> LastUpdate;
16 auto& NewTaskNotifier =
Instrument->GetInstrumentData()->InstrumentThreadOnly.GetNewTaskNotifier();
24 while (
Instrument->GetInstrumentData()->GetNumEnqueuedTasks())
25 if (!
Instrument->InstrumentThreadOnly.HandleTask(Instance))
33 auto TaskQueueDelay =
Instrument->GetTaskQueueDelay();
34 auto Now = std::chrono::system_clock::now();
36 if (Now - LastUpdate >= TaskQueueDelay || TaskQueueDelay == decltype(TaskQueueDelay)::max())
41 Instrument->GetInstrumentData()->InstrumentThreadOnly.SetLastUpdateTime(Now);
46 if (TaskQueueDelay == decltype(TaskQueueDelay)::max())
47 NewTaskNotifier.Wait();
48 else if (TaskQueueDelay.count() == 0)
49 std::this_thread::yield();
51 NewTaskNotifier.Wait(TaskQueueDelay);
58 Instrument->InstrumentThreadOnly.SetInitialized();
69 Instrument->GetInstrumentData()->InstrumentThreadOnly.SetException(std::current_exception());
74 catch (
const std::exception& e)
79 Instrument->GetInstrumentData()->InstrumentThreadOnly.SetException(std::current_exception());
89 Instrument->GetInstrumentData()->InstrumentThreadOnly.SetException(std::current_exception());
106 auto Task = std::move(
TaskQueue.front());
159 if (Task->get()->InstrumentDataBaseOnly.KeepFinishedTask())
249 auto Task = MakeTask<ArriveAtLatchTask>(Latch);
267 if (!InstrumentDataPtr->GetNumEnqueuedTasks())
270 Task = InstrumentDataPtr->GetTaskFront();
271 Task->get()->InstrumentBaseOnly.Lock();
274 auto Result = Task->get()->InstrumentBaseOnly.Run(Instance);
306 catch (
const std::exception& e)
358 if (InstrumentDataPtr->GetNumEnqueuedTasks())
360 InstrumentDataPtr->InstrumentBaseOnly.RemoveAllTasksExceptFront();
361 InstrumentDataPtr->GetTaskFront()->get()->Abort();
366 if (!InstrumentDataPtr->GetException())
369 if (Task && !InstrumentDataPtr->GetException())
370 InstrumentDataPtr->EnqueueTask(std::move(Task));
373 InstrumentDataPtr->InstrumentBaseOnly.CloseQueue();
379 Util::EventLog().
Log(
"An instrument has been terminated whithout cleaning up since the error reported below has occurred while issuing an exit task.",
398 catch (
const std::exception& e)
411 using namespace std::chrono_literals;
421 using namespace std::chrono_literals;
433 InstrumentDataGetter(InstrumentDataGetter)
438 :
RunnableInstance(std::move(Other)), InstrumentDataGetter(Other.InstrumentDataGetter)
468 auto StateCopy =
State.load();
502 return Result.ShouldContinue();
Implementation of DynExp instrument objects.
~ArriveAtLatchTask()
If the task has been aborted or never executed, the destructor arrives at the latch in order to avoid...
bool HasArrived
Indicates whether the task has already arrived at the latch.
std::latch & Latch
Latch the task arrives at when it is executed.
virtual TaskResultType RunChild(InstrumentInstance &Instance) override
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
Wrapper holding a pointer to an exception and providing functionality for accessing it....
bool IsError() const
Checks whether the wrapper holds an exception.
TaskResultType RunChild(InstrumentInstance &Instance) override final
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
virtual void ExitFuncImpl(dispatch_tag< ExitTaskBase >, InstrumentInstance &Instance)=0
Deinitializes the respective instrument within the instrument inheritance hierarchy....
Refer to DynExp::ParamsBase::dispatch_tag.
virtual void InitFuncImpl(dispatch_tag< InitTaskBase >, InstrumentInstance &Instance)=0
Initializes the respective instrument within the instrument inheritance hierarchy....
TaskResultType RunChild(InstrumentInstance &Instance) override final
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
Refer to DynExp::ParamsBase::dispatch_tag.
Base class for instruments. Instruments comprise virtual devices (meta instruments) and physial devic...
static auto GetExceptionUnsafe(const InstrumentDataTypeSyncPtrConstType &InstrumentDataPtr)
Getter for InstrumentDataBase::InstrumentException.
bool IsReadyChild() const override final
Returns wheter this Object instance is ready (e.g. it is running or connected to a hardware device) a...
Util::SynchronizedPointer< const InstrumentDataType > InstrumentDataTypeSyncPtrConstType
Alias for the return type of InstrumentBase::GetInstrumentData() const. Data class instances wrapped ...
void ResetImpl(dispatch_tag< RunnableObject >) override final
Refer to DynExp::Object::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of every de...
virtual bool UpdateAdditionalData()
Determines whether to enqueue update tasks (UpdateTaskBase).
InstrumentBase(const std::thread::id OwnerThreadID, ParamsBasePtrType &&Params)
Constructs an instrument instance.
bool HandleTask(InstrumentInstance &Instance)
Executes and removes the next pending task from the instrument's task queue.
virtual std::unique_ptr< InitTaskBase > MakeInitTask() const
Factory function for an init task (InitTaskBase). Override to define the desired initialization task ...
void UpdateData() const
Enqueues an update task (instance of class UpdateTaskBase).
std::atomic< bool > Initialized
Determines whether the init task (InitTaskBase) has run.
void OnPrepareExit()
This function enables derived classes to enqueue tasks to be executed directly before the final exit ...
void EnqueueArriveAtLatchTask(std::latch &Latch) const
Enqueues a task which arrives at a latch when executed (instance of class ArriveAtLatchTask).
virtual std::unique_ptr< ExitTaskBase > MakeExitTask() const
Factory function for an exit task (ExitTaskBase). Override to define the desired deinitialization tas...
virtual void OnPrepareExitChild() const
This function enables derived classes to enqueue tasks to be executed directly before the final exit ...
void UpdateDataInternal()
Inserts an update task (UpdateTaskBase) into the instrument's task queue. Override UpdateAdditionalDa...
static constexpr auto GetInstrumentDataTimeoutDefault
Determines the default timeout for GetInstrumentData() to lock the mutex synchronizing the instrument...
void TerminateChild(const std::chrono::milliseconds Timeout) override final
Signals derived classes that terminating the RunnableObject instance's thread is about to be requeste...
virtual void OnErrorChild() const
Derived classes can perform critical shutdown actions after an error has occurred....
void RunChild() override final
Refer to Run().
std::exception_ptr GetExceptionChild([[maybe_unused]] const std::chrono::milliseconds Timeout) const override final
InstrumentDataTypeSyncPtrType GetInstrumentData(const std::chrono::milliseconds Timeout=GetInstrumentDataTimeoutDefault)
Locks the mutex of the instrument data class instance InstrumentData assigned to this InstrumentBase ...
virtual std::unique_ptr< UpdateTaskBase > MakeUpdateTask() const
Factory function for an update task (UpdateTaskBase). Override to define the desired update task in d...
Util::SynchronizedPointer< InstrumentDataType > InstrumentDataTypeSyncPtrType
Alias for the return type of InstrumentBase::GetInstrumentData(). Data class instances wrapped into U...
virtual bool HandleAdditionalTask()
Determines whether task handling should continue.
InstrumentDataTypeSyncPtrType GetNonConstInstrumentData(const std::chrono::milliseconds Timeout=GetInstrumentDataTimeoutDefault) const
Always allows InstrumentBase to obtain a non-const pointer to the instrument's data - even in const t...
void OnError()
Derived classes can perform critical shutdown actions after an error has occurred....
virtual ~InstrumentBase()=0
const std::unique_ptr< InstrumentDataType > InstrumentData
Instrument data belonging to this InstrumentBase instance.
bool IsInitialized() const
Getter for Initialized.
void NotifyChild() override final
Notify derived classes that some state has changed (e.g. the termination of Thread is requested) and ...
virtual ~InstrumentConfiguratorBase()=0
virtual void ResetImpl(dispatch_tag< InstrumentDataBase >)
Refer to DynExp::InstrumentDataBase::Reset(). Using tag dispatch mechanism to ensure that ResetImpl()...
TaskQueueType TaskQueue
FIFO task queue of the instrument owning this InstrumentDataBase instance.
void CheckError() const
Throws InstrumentException if it is not nullptr using Util::ForwardException().
bool IsQueueClosed() const noexcept
Determines whether the instrument task queue is closed.
void Reset()
Resets the InstrumentDataBase's instance and calls ResetImpl(dispatch_tag<InstrumentDataBase>) subseq...
std::unique_ptr< TaskBase > PopTaskBack()
Removes a task from the back of an instrument's task queue.
void EnqueuePriorityTask(std::unique_ptr< TaskBase > &&Task)
Enqueues a task at the front of an instrument's task queue and notifies the instrument about the new ...
void RemoveAllTasks()
Clears the instrument's task queue.
TaskQueueType::const_iterator TaskQueueIteratorType
Const iterator type to elements of TaskQueueType.
void EnqueueTask(std::unique_ptr< TaskBase > &&Task)
Enqueues a task at the back of an instrument's task queue and notifies the instrument about the new t...
std::unique_ptr< TaskBase > PopTaskFront()
Removes a task from the front of an instrument's task queue.
Util::OneToOneNotifier NewTaskNotifier
Used to notify the instrument thread about new tasks when enqueuing tasks into the task queue....
std::exception_ptr InstrumentException
Used to transfer exceptions from the instrument thread to the main thread. Stores the exception respo...
std::unique_ptr< TaskBase > PopFinishedTask()
Removes a task from the front of an instrument's list of finished tasks.
void RemoveAllTasksExceptFront()
Clears the instrument's task queue but keeps the front task (the task with highest priority which is ...
void CheckQueueState(bool CallFromInstrThread) const
Checks whether it is currently allowed to enqueue tasks into the instrument task queue.
void RemoveTaskFromQueue(TaskQueueIteratorType &Task)
Removes a task from the instrument's task queue and inserts it into the instrument's list of finished...
bool QueueClosed
If set to true, no new tasks can be enqueued (useful if an instrument is e.g. stopped).
TaskQueueType FinishedTasks
List of the instrument's finished tasks. Tasks are moved here from TaskQueue after completion.
Refer to ParamsBase::dispatch_tag.
Defines data for a thread belonging to a InstrumentBase instance. Refer to RunnableInstance.
InstrumentInstance(InstrumentBase &Owner, std::promise< void > &&ThreadExitedPromise, const InstrumentBase::InstrumentDataGetterType InstrumentDataGetter)
Constructs a non-empty RunnableInstance instance.
virtual ~InstrumentParamsBase()=0
void EnsureCallFromOwningThread() const
Asserts that the call to this function is performed from the thread which constructed this Object ins...
Refer to ParamsBase::dispatch_tag.
Defines data for a thread belonging to a RunnableObject instance. This data is only accessed by the R...
const Object::ParamsGetterType ParamsGetter
Invoke to obtain the parameters (derived from ParamsBase) of Owner.
Defines an Object which possesses a thread it runs in. The RunnableObject can be started and stopped ...
bool IsCallFromRunnableThread() const
Checks whether Thread's id matches the id of the calling thread. This is thread-safe if the function ...
std::promise< void > MakeThreadExitedPromise()
Helper function to be used by overridden RunChild() functions in derived classes to (re)initialize th...
static constexpr auto ShortTimeoutDefault
Default timeout e.g. used as a default for calls to InstrumentBase::GetInstrumentData or ModuleBase::...
bool IsExiting() const noexcept
Returns ShouldExit.
void StoreThread(std::thread &&Thread) noexcept
Stores a thread constructed by a derived class overriding RunChild() in Thread taking ownership of th...
void EnsureCallFromRunnableThread() const
Asserts that the call to this function is performed from the RunnableObject instance's thread by call...
bool IsRunning() const noexcept
Returns Running.
void Lock()
Locks the task to prepare it for execution.
virtual TaskResultType RunChild(InstrumentInstance &Instance)=0
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
std::atomic< int > ErrorCode
Holds the error code of an error which occurred during execution of the task function.
std::atomic< TaskState > State
Holds the task's current state. Refer to TaskBase::TaskState.
bool IsLocked() const noexcept
Determines whether the task is locked.
bool Run(InstrumentInstance &Instance)
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
const CallbackType CallbackFunc
This callback function is called after the task has finished (either successfully or not) with a refe...
virtual ~TaskBase()=0
The destructor aborts a waiting task setting State to TaskState::Aborted. Then, it calls CallbackFunc...
Defines the return type of task functions.
TaskResultType RunChild(InstrumentInstance &Instance) override final
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
virtual void UpdateFuncImpl(dispatch_tag< UpdateTaskBase >, InstrumentInstance &Instance)=0
Updates the respective instrument within the instrument inheritance hierarchy. Call UpdateFuncImpl() ...
Refer to DynExp::ParamsBase::dispatch_tag.
Wraps a member function of some object and stores its default arguments. Moving from CallableMemberWr...
void Log(const std::string &Message, const ErrorType Type=ErrorType::Info, const size_t Line=0, const std::string &Function="", const std::string &File="", const int ErrorCode=0, const std::stacktrace &Trace={}) noexcept
Logs an event from information specified manually.
DynExp exceptions are derived from this class. It contains basic information about the cause of the e...
const int ErrorCode
DynExp error code from DynExpErrorCodes::DynExpErrorCodes
An invalid argument like a null pointer has been passed to a function.
An operation cannot be performed currently since the related object is in an invalid state like an er...
void Notify()
Set notification to stop waiting (sets EventOccurred to true).
Pointer to lock a class derived from ISynchronizedPointerLockable for synchronizing between threads....
constexpr auto Instrument
DynExp's main namespace contains the implementation of DynExp including classes to manage resources (...
T::ParamsType * dynamic_Params_cast(ParamsBasePtrType::element_type *Params)
Casts the parameter base class to a derived Object's parameter class.
int InstrumentThreadMain(InstrumentInstance Instance, InstrumentBase *const Instrument)
Instruments run in their own thread. This is the instrument thread's main function.
std::unique_ptr< ParamsBase > ParamsBasePtrType
Alias for a pointer to the parameter system base class ParamsBase.
void ForwardException(std::exception_ptr e)
Wraps the exception passed to the function in a ForwardedException and throws the ForwardedException....
EventLogger & EventLog()
This function holds a static EventLogger instance and returns a reference to it. DynExp uses only one...
Accumulates include statements to provide a precompiled header.