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(std::unique_ptr<RunnableInstance>&& InstancePtr, RunnableObject* BaseObject)
9 {
10 InstancePtr->BlockUntilReadyToStart();
11
12 auto const Instrument = static_cast<InstrumentBase*>(BaseObject);
13 auto& Instance = static_cast<InstrumentInstance&>(*InstancePtr);
14 bool IsExiting = false;
15 bool IsFirstRun = true;
17 std::chrono::time_point<std::chrono::system_clock> LastUpdate; // LastUpdate.time_since_epoch() == 0 now.
18
19 try
20 {
21 auto& NewTaskNotifier = Instrument->GetInstrumentData()->InstrumentThreadOnly.GetNewTaskNotifier();
22
23 while (!IsExiting)
24 {
25 if (Instrument->IsExiting())
26 IsExiting = true;
27
28 // Loop through all pending tasks. Potential change in between loop condition and function call is taken care of by HandleTask()
29 while (Instrument->GetInstrumentData()->GetNumEnqueuedTasks())
30 {
31 DoContinue = Instrument->InstrumentThreadOnly.HandleTask(Instance);
33 {
35 IsExiting = true;
36
37 break;
38 }
39 }
40
41 if (!IsExiting)
42 {
43 auto TaskQueueDelay = Instrument->GetTaskQueueDelay();
44 auto Now = std::chrono::system_clock::now();
45
47 (Now - LastUpdate >= TaskQueueDelay || TaskQueueDelay == decltype(TaskQueueDelay)::max()))
48 {
49 Instrument->InstrumentThreadOnly.UpdateData();
50
51 LastUpdate = Now;
52 Instrument->GetInstrumentData()->InstrumentThreadOnly.SetLastUpdateTime(Now);
53 }
54
55 if (!IsFirstRun)
56 {
57 if (TaskQueueDelay == decltype(TaskQueueDelay)::max())
58 NewTaskNotifier.Wait();
59 else if (TaskQueueDelay.count() == 0)
60 std::this_thread::yield();
61 else
62 NewTaskNotifier.Wait(TaskQueueDelay);
63 }
64 }
65
66 if (IsFirstRun)
67 {
68 // The initialization task gets enqueued before the instrument thread starts. Hence, it will have been executed at this point.
69 Instrument->InstrumentThreadOnly.SetInitialized();
70 IsFirstRun = false;
71 }
72 }
73 }
74 catch (const Util::Exception& e)
75 {
76 Util::EventLog().Log("An instrument has been terminated because of the error reported below.", Util::ErrorType::Error);
78
79 Instrument->InstrumentThreadOnly.SetException(std::current_exception());
80 Instrument->InstrumentThreadOnly.OnError();
81
82 return e.ErrorCode;
83 }
84 catch (const std::exception& e)
85 {
86 Util::EventLog().Log("An instrument has been terminated because of the following error: " + std::string(e.what()), Util::ErrorType::Error);
87
88 Instrument->InstrumentThreadOnly.SetException(std::current_exception());
89 Instrument->InstrumentThreadOnly.OnError();
90
92 }
93 catch (...)
94 {
95 Util::EventLog().Log("An instrument has been terminated because of an unknown error.", Util::ErrorType::Error);
96
97 Instrument->InstrumentThreadOnly.SetException(std::current_exception());
98 Instrument->InstrumentThreadOnly.OnError();
99
101 }
102
104 }
105
106 std::unique_ptr<TaskBase> InstrumentDataBase::PopTaskFront()
107 {
108 if (TaskQueue.empty())
109 return nullptr;
110
111 if (TaskQueue.front()->IsLocked())
112 throw Util::InvalidStateException("A task cannot be removed from task queue since it is locked (already started running?)");
113
114 auto Task = std::move(TaskQueue.front());
115 TaskQueue.pop_front();
116
117 return Task;
118 }
119
120 std::unique_ptr<TaskBase> InstrumentDataBase::PopTaskBack()
121 {
122 if (TaskQueue.empty())
123 return nullptr;
124
125 if (TaskQueue.back()->IsLocked())
126 throw Util::InvalidStateException("A task cannot be removed from task queue since it is locked (already started running?)");
127
128 auto Task = std::move(TaskQueue.back());
129 TaskQueue.pop_back();
130
131 return Task;
132 }
133
134 std::unique_ptr<TaskBase> InstrumentDataBase::PopFinishedTask()
135 {
136 if (FinishedTasks.empty())
137 return nullptr;
138
139 auto Task = std::move(FinishedTasks.front());
140 FinishedTasks.pop_front();
141
142 return Task;
143 }
144
145 std::exception_ptr InstrumentDataBase::GetException() const noexcept
146 {
148 return std::make_exception_ptr(Util::Exception());
149
150 return InstrumentException;
151 }
152
153 void InstrumentDataBase::EnqueueTask(std::unique_ptr<TaskBase>&& Task, bool CallFromInstrThread, bool NotifyReceiver)
154 {
155 CheckError();
156 CheckQueueState(CallFromInstrThread);
157
158 TaskQueue.push_back(std::move(Task));
159 if (NotifyReceiver)
161 }
162
163 void InstrumentDataBase::EnqueuePriorityTask(std::unique_ptr<TaskBase>&& Task, bool CallFromInstrThread, bool NotifyReceiver)
164 {
165 CheckError();
166 CheckQueueState(CallFromInstrThread);
167
168 TaskQueue.push_front(std::move(Task));
169 if (NotifyReceiver)
171 }
172
174 {
175 if (Task->get()->InstrumentDataBaseOnly.KeepFinishedTask())
176 FinishedTasks.splice(FinishedTasks.cend(), TaskQueue, Task);
177 else
178 TaskQueue.erase(Task);
179 }
180
182 {
183 TaskQueue.clear();
184 }
185
187 {
188 if (TaskQueue.size() < 2)
189 return;
190
191 TaskQueue.erase(++TaskQueue.begin(), TaskQueue.end());
192 }
193
195 {
196 QueueClosed = false;
197 HasException = false;
198 InstrumentException = nullptr;
199
200 TaskQueue.clear();
201 FinishedTasks.clear();
202
204 }
205
206 void InstrumentDataBase::SetException(std::exception_ptr Exception) noexcept
207 {
208 IndicateException();
209
210 InstrumentException = Exception;
211 }
212
217
218 void InstrumentDataBase::CheckQueueState(bool CallFromInstrThread) const
219 {
220 // Only allow enqueuing a task by other threads if the queue is not closed.
221 // Allow always if the instrument itself is enqueuing something (e.g. upon update or exit).
222 if (IsQueueClosed() && !CallFromInstrThread)
223 throw Util::InvalidStateException("A task cannot be enqueued since the task queue is closed (instrument is shut down?)");
224 }
225
229
233
234 InstrumentBase::InstrumentBase(const std::thread::id OwnerThreadID, ParamsBasePtrType&& Params)
235 : RunnableObject(OwnerThreadID, std::move(Params)),
236 InstrumentThreadOnly(*this), InstrumentData(std::move(dynamic_Params_cast<InstrumentBase>(GetParams())->InstrumentData))
237 {
238 if (!InstrumentData)
239 throw Util::InvalidArgException("InstrumentData cannot be nullptr.");
240 }
241
245
247 {
248 return InstrumentDataTypeSyncPtrType(InstrumentData.get(), Timeout);
249 }
250
252 {
254 }
255
257 {
258 return InstrumentDataTypeSyncPtrType(InstrumentData.get(), Timeout);
259 }
260
262 {
263 auto Task = MakeUpdateTask();
264 if (!Task)
265 return;
266
267 // Prevent notifying the instrument thread's NewTaskNotifier by update tasks.
268 GetNonConstInstrumentData()->InstrumentBaseOnly.EnqueueTask(std::move(Task), IsCallFromRunnableThread(), false);
269 }
270
271 void InstrumentBase::EnqueueArriveAtLatchTask(std::latch& Latch) const
272 {
273 auto Task = MakeTask<ArriveAtLatchTask>(Latch);
274
275 GetNonConstInstrumentData()->EnqueueTask(std::move(Task));
276 }
277
279 {
281
284
286
287 {
288 // Locks InstrumentData
289 auto InstrumentDataPtr = GetInstrumentData();
290
291 if (!InstrumentDataPtr->GetNumEnqueuedTasks())
293
294 Task = InstrumentDataPtr->GetTaskFront();
295 if (Task->get()->IsAborting())
296 {
297 Task->get()->InstrumentBaseOnly.SetAborted();
298 GetInstrumentData()->InstrumentBaseOnly.RemoveTaskFromQueue(Task);
299
301 }
302 if (Task->get()->GetDeferUntil() > std::chrono::system_clock::now())
304
305 Task->get()->InstrumentBaseOnly.Lock();
306 } // InstrumentData unlocked here
307
308 auto DoContinue = Task->get()->InstrumentBaseOnly.Run(Instance);
309 GetInstrumentData()->InstrumentBaseOnly.RemoveTaskFromQueue(Task);
310
311 return DoContinue;
312 }
313
315 {
317
319 return;
320
321 UpdateData();
322 }
323
324 void InstrumentBase::SetException(std::exception_ptr Exception) noexcept
325 {
326 try
327 {
328 // Locking InstrumentData may throw.
329 GetInstrumentData()->InstrumentBaseOnly.SetException(Exception);
330 }
331 catch (...)
332 {
333 // Atomic operation avoids locking InstrumentData.
334 InstrumentData->InstrumentBaseOnly.IndicateException();
335 }
336 }
337
339 {
341
342 try
343 {
344 // Necessary to call tasks' destructors. This is required to avoid deadlocks e.g. by pending ArriveAtLatchTask tasks.
345 GetInstrumentData()->InstrumentBaseOnly.RemoveAllTasks();
346
347 OnErrorChild();
348 }
349 catch (const Util::Exception& e)
350 {
351 Util::EventLog().Log("Calling an instrument's error handler, the error listed below occurred.", Util::ErrorType::Error);
352 Util::EventLog().Log(e);
353 }
354 catch (const std::exception& e)
355 {
356 Util::EventLog().Log("Calling an instrument's error handler, the error listed below occurred.", Util::ErrorType::Error);
357 Util::EventLog().Log(e.what());
358 }
359 catch (...)
360 {
361 Util::EventLog().Log("Calling an instrument's error handler, an unknown error occurred.", Util::ErrorType::Error);
362 }
363 }
364
366 {
367 // Firstly, reset instrument's data...
368 InstrumentData->InstrumentBaseOnly.Reset();
369 Initialized = false;
370
371 // ...so that derived instruments can fill the instrument's data again, secondly.
373 }
374
376 {
377 auto Task = MakeInitTask();
378 if (Task)
379 InstrumentData->EnqueueTask(std::move(Task));
380
381 auto InstancePtr = std::make_unique<InstrumentInstance>(*this, MakeThreadExitedPromise(), InstrumentBase::InstrumentDataGetterType{
383 });
384
385 MakeThread(InstrumentThreadMain, std::move(InstancePtr));
386 }
387
389 {
390 GetInstrumentData()->InstrumentBaseOnly.GetNewTaskNotifier().Notify();
391 }
392
393 // Does not call Object::UseCount.AcquireLock() to make sure, no other object is starting to use this instrument
394 // while resetting. Object::Reset() or RunnableObject::Terminate() ensure that already.
395 void InstrumentBase::TerminateChild(const std::chrono::milliseconds Timeout)
396 {
397 auto Task = MakeExitTask();
398
399 try
400 {
401 // Locks InstrumentData.
402 // If InstrumentData cannot be locked because it is continuously locked by instrument/module thread, deadlock
403 // is avoided since GetInstrumentData throws Util::TimeoutException after timeout in this case.
404 auto InstrumentDataPtr = GetInstrumentData();
405
406 if (InstrumentDataPtr->GetNumEnqueuedTasks())
407 {
408 InstrumentDataPtr->InstrumentBaseOnly.RemoveAllTasksExceptFront();
409 InstrumentDataPtr->GetTaskFront()->get()->Abort();
410 }
411
412 // Allow to insert tasks which should be executed before the final exit task. Instrument data might be
413 // locked recursively here (which is supported).
414 if (!InstrumentDataPtr->GetException())
416
417 if (Task && !InstrumentDataPtr->GetException())
418 InstrumentDataPtr->EnqueueTask(std::move(Task));
419
420 // Do not allow enqueuing further tasks.
421 InstrumentDataPtr->InstrumentBaseOnly.CloseQueue();
422 } // InstrumentData unlocked here since InstrumentDataPtr gets destroyed.
423 catch (const Util::Exception& e)
424 {
425 // Exception occurring while trying to issue an ExitTask is swallowed and logged. It is tried to terminate
426 // the instrument anyway.
427 Util::EventLog().Log("An instrument has been terminated whithout cleaning up since the error reported below has occurred while issuing an exit task.",
429 Util::EventLog().Log(e);
430 }
431 }
432
434 {
436
437 try
438 {
440 }
441 catch (const Util::Exception& e)
442 {
443 Util::EventLog().Log("Calling an instrument's prepare exit handler, the error listed below occurred.", Util::ErrorType::Error);
444 Util::EventLog().Log(e);
445 }
446 catch (const std::exception& e)
447 {
448 Util::EventLog().Log("Calling an instrument's prepare exit handler, the error listed below occurred.", Util::ErrorType::Error);
449 Util::EventLog().Log(e.what());
450 }
451 catch (...)
452 {
453 Util::EventLog().Log("Calling an instrument's prepare exit handler, an unknown error occurred.", Util::ErrorType::Error);
454 }
455 }
456
457 std::exception_ptr InstrumentBase::GetExceptionChild(const std::chrono::milliseconds Timeout) const
458 {
459 using namespace std::chrono_literals;
460
461 // If InstrumentData cannot be locked because it is continuously locked by instrument/module thread, deadlock
462 // is avoided since GetInstrumentData throws Util::TimeoutException after timeout in this case.
463 // Short timeout only since main thread should not block.
465 }
466
468 {
469 using namespace std::chrono_literals;
470 auto LockedInstrData = GetInstrumentData(ShortTimeoutDefault);
471
472 auto Exception = GetExceptionUnsafe(LockedInstrData);
473 Util::ForwardException(Exception);
474
475 return IsRunning() && !IsExiting() && IsInitialized();
476 }
477
478 InstrumentInstance::InstrumentInstance(InstrumentBase& Owner, std::promise<void>&& ThreadExitedPromise,
479 const InstrumentBase::InstrumentDataGetterType InstrumentDataGetter)
480 : RunnableInstance(Owner, std::move(ThreadExitedPromise)),
481 InstrumentDataGetter(InstrumentDataGetter)
482 {
483 }
484
486 : RunnableInstance(std::move(Other)), InstrumentDataGetter(Other.InstrumentDataGetter)
487 {
488 }
489
495
497 : CallbackFunc(Other.CallbackFunc), HasBeenCalled(Other.HasBeenCalled)
498 {
499 Other.HasBeenCalled = true;
500 }
501
503 {
504 try
505 {
506 // Default-constructed ExceptionContainer does indicate a non-error state.
507 ExceptionContainer Exception;
508 this->operator()(nullptr, Exception);
509 }
510 catch (...)
511 {
512 // Swallow exceptions possibly thrown by callback execution to prevent them leaving the destructor.
513 }
514 }
515
517 {
518 // Ensure that CallbackFunc gets called in any case.
520 {
522
523 try
524 {
525 // Default-constructed ExceptionContainer does indicate a non-error state.
526 ExceptionContainer Exception;
527 CallbackFunc(this, Exception);
528 }
529 catch (...)
530 {
531 // Swallow exceptions possibly thrown by CallbackFunc to prevent them leaving the destructor.
532 }
533 }
534 }
535
536 bool TaskBase::IsLocked() const noexcept
537 {
538 // Perform a copy for thread-safety to only load the atomic's state once.
539 auto StateCopy = State.load();
540
541 return StateCopy == TaskState::Locked || StateCopy == TaskState::Running;
542 }
543
545 {
547 throw Util::InvalidStateException("An instrument's task cannot be locked since it is not in a pending state.");
548
550 }
551
553 {
555 throw Util::InvalidStateException("An instrument's task cannot be started since it is not in a pending or locked state.");
556
558
559 try
560 {
561 auto Result = RunChild(Instance);
562
563 State = Result.GetErrorCode() ? TaskState::Failed : (Result.HasAborted() ? TaskState::Aborted : TaskState::Finished);
564 ErrorCode = Result.GetErrorCode();
565
566 // Default-constructed ExceptionContainer does indicate a non-error state.
567 ExceptionContainer Exception;
568 CallbackFunc(this, Exception);
569
570 return Result.ToTaskHandlingContinuationType();
571 }
572 catch (...)
573 {
576
577 ExceptionContainer Exception(std::current_exception());
578 if (CallbackFunc)
579 {
580 CallbackFunc(this, Exception);
581 if (!Exception.IsError())
583 }
584
585 throw;
586 }
587 }
588
590 {
591 InitFuncImpl(dispatch_tag<InitTaskBase>(), Instance);
592
593#ifdef DYNEXP_DEBUG
594 Util::EventLog().Log("Instrument \"" + Instance.ParamsGetter()->ObjectName.Get() + "\" has been initialized.");
595#endif // DYNEXP_DEBUG
596
597 return {};
598 }
599
601 {
602 ExitFuncImpl(dispatch_tag<ExitTaskBase>(), Instance);
603
604#ifdef DYNEXP_DEBUG
605 Util::EventLog().Log("Instrument \"" + Instance.ParamsGetter()->ObjectName.Get() + "\" has been shut down.");
606#endif // DYNEXP_DEBUG
607
609 }
610
612 {
613 UpdateFuncImpl(dispatch_tag<UpdateTaskBase>(), Instance);
614
615 return {};
616 }
617
619 {
620 if (!HasArrived)
621 Latch.count_down();
622 }
623
625 {
626 HasArrived = true;
627 Latch.count_down();
628
629 return {};
630 }
631}
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...
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...
Refer to DynExp::ParamsBase::dispatch_tag.
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:480
static auto GetExceptionUnsafe(const InstrumentDataTypeSyncPtrConstType &InstrumentDataPtr)
Getter for InstrumentDataBase::InstrumentException. If InstrumentDataBase::InstrumentException is nul...
Definition Instrument.h:660
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:543
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:774
TaskHandlingContinuationType HandleTask(InstrumentInstance &Instance)
Executes and removes the next pending task from the instrument's task queue.
InstrumentBase(const std::thread::id OwnerThreadID, ParamsBasePtrType &&Params)
Constructs an instrument instance.
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:805
void OnPrepareExit()
This function enables derived classes to enqueue tasks to be executed directly before the final exit ...
void SetException(std::exception_ptr Exception) noexcept
Sets this instrument instance to an error state and tries to store the exception responsible for the ...
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:761
virtual std::unique_ptr< InitTaskBase > MakeInitTask() const
Factory function for an init task (InitTaskBase). Override to define the desired initialization task ...
Definition Instrument.h:783
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:591
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:760
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:537
virtual bool HandleAdditionalTask()
Determines whether task handling should continue.
Definition Instrument.h:767
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:792
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:801
TaskHandlingContinuationType
Indicates how an instrument should proceed after handling a task.
Definition Instrument.h:509
const std::unique_ptr< InstrumentDataType > InstrumentData
Instrument data belonging to this InstrumentBase instance.
Definition Instrument.h:804
bool IsInitialized() const
Getter for Initialized.
Definition Instrument.h:638
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:368
TaskQueueType TaskQueue
FIFO task queue of the instrument owning this InstrumentDataBase instance.
Definition Instrument.h:398
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:277
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:221
std::atomic< bool > HasException
If set to true, indicates to the main thread that an exception has happened in the instrument thread....
Definition Instrument.h:416
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:214
std::unique_ptr< TaskBase > PopTaskFront()
Removes a task from the front of an instrument's task queue.
std::exception_ptr GetException() const noexcept
Getter for InstrumentDataBase::InstrumentException. If InstrumentDataBase::InstrumentException is nul...
Util::OneToOneNotifier NewTaskNotifier
Used to notify the instrument thread about new tasks when enqueuing tasks into the task queue....
Definition Instrument.h:407
void SetException(std::exception_ptr Exception) noexcept
Setter for InstrumentException.
std::exception_ptr InstrumentException
Used to transfer exceptions from the instrument thread to the main thread. Stores the exception respo...
Definition Instrument.h:423
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:400
TaskQueueType FinishedTasks
List of the instrument's finished tasks. Tasks are moved here from TaskQueue after completion.
Definition Instrument.h:399
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:813
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:3513
const Object::ParamsGetterType ParamsGetter
Invoke to obtain the parameters (derived from ParamsBase) of Owner.
Definition Object.h:3710
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:658
std::promise< void > MakeThreadExitedPromise()
Helper function to be used by overridden RunChild() functions in derived classes to (re)initialize th...
Definition Object.cpp:643
void MakeThread(ThreadFuncType ThreadFunc, std::unique_ptr< RunnableInstance > &&InstancePtr)
Creates and runs the thread of the RunnableObject instance. Call this function in the derived class o...
Definition Object.cpp:651
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 EnsureCallFromRunnableThread() const
Asserts that the call to this function is performed from the RunnableObject instance's thread by call...
Definition Object.cpp:663
bool IsRunning() const noexcept
Returns Running.
Definition Object.h:2550
Type owning a callback function which is invoked when a task has finished, failed,...
Definition Instrument.h:978
~CallbackType()
Calls operator()() passing nullptr to the first argument of FuncType. Swallows all exceptions possibl...
CallbackType()
Constructs a CallbackType instance with an empty CallbackFunc.
Definition Instrument.h:991
CallbackType CallbackFunc
This callback function is called after the task has finished (either successfully or not) with a poin...
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.
virtual ~TaskBase()=0
The destructor aborts a waiting task setting State to TaskState::Aborted. Then, it calls CallbackFunc...
InstrumentBase::TaskHandlingContinuationType Run(InstrumentInstance &Instance)
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
Defines the return type of task functions.
Definition Instrument.h:865
@ Terminate
Task handling should not continue, the instrument should terminate.
@ Continue
Task handling should continue, the instrument does not terminate.
constexpr InstrumentBase::TaskHandlingContinuationType ToTaskHandlingContinuationType() const noexcept
Converts Continue to InstrumentBase::TaskHandlingContinuationType.
const ContinuationType Continue
Determines whether an instrument should terminate after handling a task.
Definition Instrument.h:918
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.
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:317
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:107
An invalid argument like a null pointer has been passed to a function.
Definition Exception.h:138
An operation cannot be performed currently since the related object is in an invalid state like an er...
Definition Exception.h:151
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
auto get() const noexcept
Returns the managed (locked) object.
Definition Util.h:241
DynExp's main namespace contains the implementation of DynExp including classes to manage resources (...
int InstrumentThreadMain(std::unique_ptr< RunnableInstance > &&InstancePtr, RunnableObject *BaseObject)
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:517
Accumulates include statements to provide a precompiled header.