DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
Instrument.cpp
Go to the documentation of this file.
1// This file is part of DynExp.
2
3#include "stdafx.h"
4#include "Instrument.h"
5
6namespace DynExp
7{
8 int InstrumentThreadMain(InstrumentInstance Instance, InstrumentBase* const Instrument)
9 {
10 bool IsExiting = false;
11 bool IsFirstRun = true;
12 std::chrono::time_point<std::chrono::system_clock> LastUpdate; // LastUpdate.time_since_epoch() == 0 now.
13
14 try
15 {
16 auto& NewTaskNotifier = Instrument->GetInstrumentData()->InstrumentThreadOnly.GetNewTaskNotifier();
17
18 while (!IsExiting)
19 {
20 if (Instrument->IsExiting())
21 IsExiting = true;
22
23 // Loop through all pending tasks. Potential change in between loop condition and function call is taken care of by HandleTask()
24 while (Instrument->GetInstrumentData()->GetNumEnqueuedTasks())
25 if (!Instrument->InstrumentThreadOnly.HandleTask(Instance))
26 {
27 IsExiting = true;
28 break;
29 }
30
31 if (!IsExiting)
32 {
33 auto TaskQueueDelay = Instrument->GetTaskQueueDelay();
34 auto Now = std::chrono::system_clock::now();
35
36 if (Now - LastUpdate >= TaskQueueDelay || TaskQueueDelay == decltype(TaskQueueDelay)::max())
37 {
38 Instrument->InstrumentThreadOnly.UpdateData();
39
40 LastUpdate = Now;
41 Instrument->GetInstrumentData()->InstrumentThreadOnly.SetLastUpdateTime(Now);
42 }
43
44 if (!IsFirstRun)
45 {
46 if (TaskQueueDelay == decltype(TaskQueueDelay)::max())
47 NewTaskNotifier.Wait();
48 else if (TaskQueueDelay.count() == 0)
49 std::this_thread::yield();
50 else
51 NewTaskNotifier.Wait(TaskQueueDelay);
52 }
53 }
54
55 if (IsFirstRun)
56 {
57 // The initialization task gets enqueued before the instrument thread starts. Hence, it will have been executed at this point.
58 Instrument->InstrumentThreadOnly.SetInitialized();
59 IsFirstRun = false;
60 }
61 }
62 }
63 catch (const Util::Exception& e)
64 {
65 Util::EventLog().Log("An instrument has been terminated because of the error reported below.", Util::ErrorType::Error);
67
68 // std::abort() is called when (e.g. timeout) exception occurrs while setting the caught exception.
69 Instrument->GetInstrumentData()->InstrumentThreadOnly.SetException(std::current_exception());
70 Instrument->InstrumentThreadOnly.OnError();
71
72 return e.ErrorCode;
73 }
74 catch (const std::exception& e)
75 {
76 Util::EventLog().Log("An instrument has been terminated because of the following error: " + std::string(e.what()), Util::ErrorType::Error);
77
78 // std::abort() is called when (e.g. timeout) exception occurrs while setting the caught exception.
79 Instrument->GetInstrumentData()->InstrumentThreadOnly.SetException(std::current_exception());
80 Instrument->InstrumentThreadOnly.OnError();
81
83 }
84 catch (...)
85 {
86 Util::EventLog().Log("An instrument has been terminated because of an unknown error.", Util::ErrorType::Error);
87
88 // std::abort() is called when (e.g. timeout) exception occurrs while setting the caught exception.
89 Instrument->GetInstrumentData()->InstrumentThreadOnly.SetException(std::current_exception());
90 Instrument->InstrumentThreadOnly.OnError();
91
93 }
94
96 }
97
98 std::unique_ptr<TaskBase> InstrumentDataBase::PopTaskFront()
99 {
100 if (TaskQueue.empty())
101 return nullptr;
102
103 if (TaskQueue.front()->IsLocked())
104 throw Util::InvalidStateException("A task cannot be removed from task queue since it is locked (already started running?)");
105
106 auto Task = std::move(TaskQueue.front());
107 TaskQueue.pop_front();
108
109 return Task;
110 }
111
112 std::unique_ptr<TaskBase> InstrumentDataBase::PopTaskBack()
113 {
114 if (TaskQueue.empty())
115 return nullptr;
116
117 if (TaskQueue.back()->IsLocked())
118 throw Util::InvalidStateException("A task cannot be removed from task queue since it is locked (already started running?)");
119
120 auto Task = std::move(TaskQueue.back());
121 TaskQueue.pop_back();
122
123 return Task;
124 }
125
126 std::unique_ptr<TaskBase> InstrumentDataBase::PopFinishedTask()
127 {
128 if (FinishedTasks.empty())
129 return nullptr;
130
131 auto Task = std::move(FinishedTasks.front());
132 FinishedTasks.pop_front();
133
134 return Task;
135 }
136
137 void InstrumentDataBase::EnqueueTask(std::unique_ptr<TaskBase>&& Task, bool CallFromInstrThread, bool NotifyReceiver)
138 {
139 CheckError();
140 CheckQueueState(CallFromInstrThread);
141
142 TaskQueue.push_back(std::move(Task));
143 if (NotifyReceiver)
145 }
146
147 void InstrumentDataBase::EnqueuePriorityTask(std::unique_ptr<TaskBase>&& Task, bool CallFromInstrThread, bool NotifyReceiver)
148 {
149 CheckError();
150 CheckQueueState(CallFromInstrThread);
151
152 TaskQueue.push_front(std::move(Task));
153 if (NotifyReceiver)
155 }
156
158 {
159 if (Task->get()->InstrumentDataBaseOnly.KeepFinishedTask())
160 FinishedTasks.splice(FinishedTasks.cend(), TaskQueue, Task);
161 else
162 TaskQueue.erase(Task);
163 }
164
166 {
167 TaskQueue.clear();
168 }
169
171 {
172 if (TaskQueue.size() < 2)
173 return;
174
175 TaskQueue.erase(++TaskQueue.begin(), TaskQueue.end());
176 }
177
179 {
180 QueueClosed = false;
181 InstrumentException = nullptr;
182
183 TaskQueue.clear();
184 FinishedTasks.clear();
185
187 }
188
193
194 void InstrumentDataBase::CheckQueueState(bool CallFromInstrThread) const
195 {
196 // Only allow enqueuing a task by other threads if the queue is not closed.
197 // Allow always if the instrument itself is enqueuing something (e.g. upon update or exit).
198 if (IsQueueClosed() && !CallFromInstrThread)
199 throw Util::InvalidStateException("A task cannot be enqueued since the task queue is closed (instrument is shut down?)");
200 }
201
205
209
210 InstrumentBase::InstrumentBase(const std::thread::id OwnerThreadID, ParamsBasePtrType&& Params)
211 : RunnableObject(OwnerThreadID, std::move(Params)),
212 InstrumentThreadOnly(*this), InstrumentData(std::move(dynamic_Params_cast<InstrumentBase>(GetParams())->InstrumentData))
213 {
214 if (!InstrumentData)
215 throw Util::InvalidArgException("InstrumentData cannot be nullptr.");
216 }
217
221
223 {
224 return InstrumentDataTypeSyncPtrType(InstrumentData.get(), Timeout);
225 }
226
228 {
230 }
231
233 {
234 return InstrumentDataTypeSyncPtrType(InstrumentData.get(), Timeout);
235 }
236
238 {
239 auto Task = MakeUpdateTask();
240 if (!Task)
241 return;
242
243 // Prevent notifying the instrument thread's NewTaskNotifier by update tasks.
244 GetNonConstInstrumentData()->InstrumentBaseOnly.EnqueueTask(std::move(Task), IsCallFromRunnableThread(), false);
245 }
246
247 void InstrumentBase::EnqueueArriveAtLatchTask(std::latch& Latch) const
248 {
249 auto Task = MakeTask<ArriveAtLatchTask>(Latch);
250
251 GetNonConstInstrumentData()->EnqueueTask(std::move(Task));
252 }
253
255 {
257
259 return false;
260
262
263 {
264 // Locks InstrumentData
265 auto InstrumentDataPtr = GetInstrumentData();
266
267 if (!InstrumentDataPtr->GetNumEnqueuedTasks())
268 return true;
269
270 Task = InstrumentDataPtr->GetTaskFront();
271 Task->get()->InstrumentBaseOnly.Lock();
272 } // InstrumentData unlocked here
273
274 auto Result = Task->get()->InstrumentBaseOnly.Run(Instance);
275 GetInstrumentData()->InstrumentBaseOnly.RemoveTaskFromQueue(Task);
276
277 return Result;
278 }
279
281 {
283
285 return;
286
287 UpdateData();
288 }
289
291 {
293
294 try
295 {
296 // Necessary to call tasks' destructors. This is required to avoid deadlocks e.g. by pending ArriveAtLatchTask tasks.
297 GetInstrumentData()->InstrumentBaseOnly.RemoveAllTasks();
298
299 OnErrorChild();
300 }
301 catch (const Util::Exception& e)
302 {
303 Util::EventLog().Log("Calling an instrument's error handler, the error listed below occurred.", Util::ErrorType::Error);
304 Util::EventLog().Log(e);
305 }
306 catch (const std::exception& e)
307 {
308 Util::EventLog().Log("Calling an instrument's error handler, the error listed below occurred.", Util::ErrorType::Error);
309 Util::EventLog().Log(e.what());
310 }
311 catch (...)
312 {
313 Util::EventLog().Log("Calling an instrument's error handler, an unknown error occurred.", Util::ErrorType::Error);
314 }
315 }
316
318 {
319 // Firstly, reset instrument's data...
320 InstrumentData->InstrumentBaseOnly.Reset();
321 Initialized = false;
322
323 // ...so that derived instruments can fill the instrument's data again, secondly.
325 }
326
328 {
329 auto Task = MakeInitTask();
330 if (Task)
331 InstrumentData->EnqueueTask(std::move(Task));
332
334 *this,
337 ), this));
338 }
339
341 {
342 GetInstrumentData()->InstrumentBaseOnly.GetNewTaskNotifier().Notify();
343 }
344
345 // Does not call Object::UseCount.AcquireLock() to make sure, no other object is starting to use this instrument
346 // while resetting. Object::Reset() or RunnableObject::Terminate() ensure that already.
347 void InstrumentBase::TerminateChild(const std::chrono::milliseconds Timeout)
348 {
349 auto Task = MakeExitTask();
350
351 try
352 {
353 // Locks InstrumentData.
354 // If InstrumentData cannot be locked because it is continuously locked by instrument/module thread, deadlock
355 // is avoided since GetInstrumentData throws Util::TimeoutException after timeout in this case.
356 auto InstrumentDataPtr = GetInstrumentData();
357
358 if (InstrumentDataPtr->GetNumEnqueuedTasks())
359 {
360 InstrumentDataPtr->InstrumentBaseOnly.RemoveAllTasksExceptFront();
361 InstrumentDataPtr->GetTaskFront()->get()->Abort();
362 }
363
364 // Allow to insert tasks which should be executed before the final exit task. Instrument data might be
365 // locked recursively here (which is supported).
366 if (!InstrumentDataPtr->GetException())
368
369 if (Task && !InstrumentDataPtr->GetException())
370 InstrumentDataPtr->EnqueueTask(std::move(Task));
371
372 // Do not allow enqueuing further tasks.
373 InstrumentDataPtr->InstrumentBaseOnly.CloseQueue();
374 } // InstrumentData unlocked here since InstrumentDataPtr gets destroyed.
375 catch (const Util::Exception& e)
376 {
377 // Exception occurring while trying to issue an ExitTask is swallowed and logged. It is tried to terminate
378 // the instrument anyway.
379 Util::EventLog().Log("An instrument has been terminated whithout cleaning up since the error reported below has occurred while issuing an exit task.",
381 Util::EventLog().Log(e);
382 }
383 }
384
386 {
388
389 try
390 {
392 }
393 catch (const Util::Exception& e)
394 {
395 Util::EventLog().Log("Calling an instrument's prepare exit handler, the error listed below occurred.", Util::ErrorType::Error);
396 Util::EventLog().Log(e);
397 }
398 catch (const std::exception& e)
399 {
400 Util::EventLog().Log("Calling an instrument's prepare exit handler, the error listed below occurred.", Util::ErrorType::Error);
401 Util::EventLog().Log(e.what());
402 }
403 catch (...)
404 {
405 Util::EventLog().Log("Calling an instrument's prepare exit handler, an unknown error occurred.", Util::ErrorType::Error);
406 }
407 }
408
409 std::exception_ptr InstrumentBase::GetExceptionChild(const std::chrono::milliseconds Timeout) const
410 {
411 using namespace std::chrono_literals;
412
413 // If InstrumentData cannot be locked because it is continuously locked by instrument/module thread, deadlock
414 // is avoided since GetInstrumentData throws Util::TimeoutException after timeout in this case.
415 // Short timeout only since main thread should not block.
417 }
418
420 {
421 using namespace std::chrono_literals;
422 auto LockedInstrData = GetInstrumentData(ShortTimeoutDefault);
423
424 auto Exception = GetExceptionUnsafe(LockedInstrData);
425 Util::ForwardException(Exception);
426
427 return IsRunning() && !IsExiting() && IsInitialized();
428 }
429
430 InstrumentInstance::InstrumentInstance(InstrumentBase& Owner, std::promise<void>&& ThreadExitedPromise,
431 const InstrumentBase::InstrumentDataGetterType InstrumentDataGetter)
432 : RunnableInstance(Owner, std::move(ThreadExitedPromise)),
433 InstrumentDataGetter(InstrumentDataGetter)
434 {
435 }
436
438 : RunnableInstance(std::move(Other)), InstrumentDataGetter(Other.InstrumentDataGetter)
439 {
440 }
441
443 {
444 // Ensure that CallbackFunc gets called in any case.
446 {
448
449 try
450 {
451 if (CallbackFunc)
452 {
453 // Default-constructed ExceptionContainer does indicate a non-error state.
454 ExceptionContainer Exception;
455 CallbackFunc(*this, Exception);
456 }
457 }
458 catch (...)
459 {
460 // Swallow exceptions possibly thrown by CallbackFunc to prevent them leave the destructor.
461 }
462 }
463 }
464
465 bool TaskBase::IsLocked() const noexcept
466 {
467 // Perform a copy for thread-safety to only load the atomic's state once.
468 auto StateCopy = State.load();
469
470 return StateCopy == TaskState::Locked || StateCopy == TaskState::Running;
471 }
472
474 {
476 throw Util::InvalidStateException("An instrument's task cannot be locked since it is not in a pending state.");
477
479 }
480
482 {
484 throw Util::InvalidStateException("An instrument's task cannot be started since it is not in a pending or locked state.");
485
487
488 try
489 {
490 auto Result = RunChild(Instance);
491
492 State = Result.GetErrorCode() ? TaskState::Failed : (Result.HasAborted() ? TaskState::Aborted : TaskState::Finished);
493 ErrorCode = Result.GetErrorCode();
494
495 if (CallbackFunc)
496 {
497 // Default-constructed ExceptionContainer does indicate a non-error state.
498 ExceptionContainer Exception;
499 CallbackFunc(*this, Exception);
500 }
501
502 return Result.ShouldContinue();
503 }
504 catch (...)
505 {
508
509 ExceptionContainer Exception(std::current_exception());
510 if (CallbackFunc)
511 {
512 CallbackFunc(*this, Exception);
513 if (!Exception.IsError())
514 return true;
515 }
516
517 throw;
518 }
519 }
520
522 {
524
525#ifdef DYNEXP_DEBUG
526 Util::EventLog().Log("Instrument \"" + Instance.ParamsGetter()->ObjectName.Get() + "\" has been initialized.");
527#endif // DYNEXP_DEBUG
528
529 return {};
530 }
531
533 {
535
536#ifdef DYNEXP_DEBUG
537 Util::EventLog().Log("Instrument \"" + Instance.ParamsGetter()->ObjectName.Get() + "\" has been shut down.");
538#endif // DYNEXP_DEBUG
539
541 }
542
549
551 {
552 if (!HasArrived)
553 Latch.count_down();
554 }
555
557 {
558 HasArrived = true;
559 Latch.count_down();
560
561 return {};
562 }
563}
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....
Definition Instrument.h:86
bool IsError() const
Checks whether the wrapper holds an exception.
Definition Instrument.h:104
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...
Definition Instrument.h:451
static auto GetExceptionUnsafe(const InstrumentDataTypeSyncPtrConstType &InstrumentDataPtr)
Getter for InstrumentDataBase::InstrumentException.
Definition Instrument.h:612
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 ...
Definition Instrument.h:495
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).
Definition Instrument.h:733
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.
std::exception_ptr GetExceptionChild(const std::chrono::milliseconds Timeout) const override final
Returns a pointer to the exception which has caused this Object instance to fail.
void UpdateData() const
Enqueues an update task (instance of class UpdateTaskBase).
std::atomic< bool > Initialized
Determines whether the init task (InitTaskBase) has run.
Definition Instrument.h:764
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 void OnPrepareExitChild() const
This function enables derived classes to enqueue tasks to be executed directly before the final exit ...
Definition Instrument.h:720
virtual std::unique_ptr< InitTaskBase > MakeInitTask() const
Factory function for an init task (InitTaskBase). Override to define the desired initialization task ...
Definition Instrument.h:742
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...
Definition Instrument.h:543
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....
Definition Instrument.h:719
void RunChild() override final
Refer to Run().
InstrumentDataTypeSyncPtrType GetInstrumentData(const std::chrono::milliseconds Timeout=GetInstrumentDataTimeoutDefault)
Locks the mutex of the instrument data class instance InstrumentData assigned to this InstrumentBase ...
Util::SynchronizedPointer< InstrumentDataType > InstrumentDataTypeSyncPtrType
Alias for the return type of InstrumentBase::GetInstrumentData(). Data class instances wrapped into U...
Definition Instrument.h:489
virtual bool HandleAdditionalTask()
Determines whether task handling should continue.
Definition Instrument.h:726
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
virtual std::unique_ptr< ExitTaskBase > MakeExitTask() const
Factory function for an exit task (ExitTaskBase). Override to define the desired deinitialization tas...
Definition Instrument.h:751
virtual std::unique_ptr< UpdateTaskBase > MakeUpdateTask() const
Factory function for an update task (UpdateTaskBase). Override to define the desired update task in d...
Definition Instrument.h:760
const std::unique_ptr< InstrumentDataType > InstrumentData
Instrument data belonging to this InstrumentBase instance.
Definition Instrument.h:763
bool IsInitialized() const
Getter for Initialized.
Definition Instrument.h:590
void NotifyChild() override final
Notify derived classes that some state has changed (e.g. the termination of Thread is requested) and ...
virtual void ResetImpl(dispatch_tag< InstrumentDataBase >)
Refer to DynExp::InstrumentDataBase::Reset(). Using tag dispatch mechanism to ensure that ResetImpl()...
Definition Instrument.h:359
TaskQueueType TaskQueue
FIFO task queue of the instrument owning this InstrumentDataBase instance.
Definition Instrument.h:376
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.
Definition Instrument.h:276
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 ...
Definition Instrument.h:220
void RemoveAllTasks()
Clears the instrument's task queue.
TaskQueueType::const_iterator TaskQueueIteratorType
Const iterator type to elements of TaskQueueType.
Definition Instrument.h:138
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...
Definition Instrument.h:213
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....
Definition Instrument.h:385
std::exception_ptr InstrumentException
Used to transfer exceptions from the instrument thread to the main thread. Stores the exception respo...
Definition Instrument.h:394
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).
Definition Instrument.h:378
TaskQueueType FinishedTasks
List of the instrument's finished tasks. Tasks are moved here from TaskQueue after completion.
Definition Instrument.h:377
Refer to ParamsBase::dispatch_tag.
Definition Instrument.h:146
Defines data for a thread belonging to a InstrumentBase instance. Refer to RunnableInstance.
Definition Instrument.h:772
InstrumentInstance(InstrumentBase &Owner, std::promise< void > &&ThreadExitedPromise, const InstrumentBase::InstrumentDataGetterType InstrumentDataGetter)
Constructs a non-empty RunnableInstance instance.
void EnsureCallFromOwningThread() const
Asserts that the call to this function is performed from the thread which constructed this Object ins...
Definition Object.cpp:468
Refer to ParamsBase::dispatch_tag.
Definition Object.h:2018
Defines data for a thread belonging to a RunnableObject instance. This data is only accessed by the R...
Definition Object.h:3505
const Object::ParamsGetterType ParamsGetter
Invoke to obtain the parameters (derived from ParamsBase) of Owner.
Definition Object.h:3671
Defines an Object which possesses a thread it runs in. The RunnableObject can be started and stopped ...
Definition Object.h:2426
bool IsCallFromRunnableThread() const
Checks whether Thread's id matches the id of the calling thread. This is thread-safe if the function ...
Definition Object.cpp:656
std::promise< void > MakeThreadExitedPromise()
Helper function to be used by overridden RunChild() functions in derived classes to (re)initialize th...
Definition Object.cpp:643
static constexpr auto ShortTimeoutDefault
Default timeout e.g. used as a default for calls to InstrumentBase::GetInstrumentData or ModuleBase::...
Definition Object.h:2489
bool IsExiting() const noexcept
Returns ShouldExit.
Definition Object.h:2552
void StoreThread(std::thread &&Thread) noexcept
Stores a thread constructed by a derived class overriding RunChild() in Thread taking ownership of th...
Definition Object.cpp:651
void EnsureCallFromRunnableThread() const
Asserts that the call to this function is performed from the RunnableObject instance's thread by call...
Definition Object.cpp:661
bool IsRunning() const noexcept
Returns Running.
Definition Object.h:2550
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.
Definition Instrument.h:824
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...
Definition Util.h:448
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.
Definition Util.cpp:309
DynExp exceptions are derived from this class. It contains basic information about the cause of the e...
Definition Exception.h:51
const int ErrorCode
DynExp error code from DynExpErrorCodes::DynExpErrorCodes
Definition Exception.h:106
An invalid argument like a null pointer has been passed to a function.
Definition Exception.h:137
An operation cannot be performed currently since the related object is in an invalid state like an er...
Definition Exception.h:150
void Notify()
Set notification to stop waiting (sets EventOccurred to true).
Definition Util.cpp:69
Pointer to lock a class derived from ISynchronizedPointerLockable for synchronizing between threads....
Definition Util.h:170
DynExp's main namespace contains the implementation of DynExp including classes to manage resources (...
int InstrumentThreadMain(InstrumentInstance Instance, InstrumentBase *const Instrument)
Instruments run in their own thread. This is the instrument thread's main function.
Definition Instrument.cpp:8
std::unique_ptr< ParamsBase > ParamsBasePtrType
Alias for a pointer to the parameter system base class ParamsBase.
Definition Object.h:1807
T::ParamsType * dynamic_Params_cast(ParamsBasePtrType::element_type *Params)
Casts the parameter base class to a derived Object's parameter class.
Definition Object.h:1835
void ForwardException(std::exception_ptr e)
Wraps the exception passed to the function in a ForwardedException and throws the ForwardedException....
Definition Exception.cpp:30
EventLogger & EventLog()
This function holds a static EventLogger instance and returns a reference to it. DynExp uses only one...
Definition Util.cpp:509
Accumulates include statements to provide a precompiled header.