DynExp
Highly flexible laboratory automation for dynamically changing experiments.
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 
6 namespace DynExp
7 {
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);
66  Util::EventLog().Log(e);
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 
190  {
192  }
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 
203  {
204  }
205 
207  {
208  }
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 
219  {
220  }
221 
223  {
225  }
226 
228  {
230  }
231 
233  {
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 
258  if (!HandleAdditionalTask())
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 
284  if (!UpdateAdditionalData())
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())
367  OnPrepareExit();
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.
445  if (State == TaskState::Waiting)
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  {
475  if (State != TaskState::Waiting)
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 
544  {
546 
547  return {};
548  }
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...
Definition: Instrument.cpp:550
bool HasArrived
Indicates whether the task has already arrived at the latch.
Definition: Instrument.h:1224
std::latch & Latch
Latch the task arrives at when it is executed.
Definition: Instrument.h:1223
virtual TaskResultType RunChild(InstrumentInstance &Instance) override
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
Definition: Instrument.cpp:556
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...
Definition: Instrument.cpp:532
virtual void ExitFuncImpl(dispatch_tag< ExitTaskBase >, InstrumentInstance &Instance)=0
Deinitializes the respective instrument within the instrument inheritance hierarchy....
Refer to DynExp::ParamsBase::dispatch_tag.
Definition: Instrument.h:1151
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...
Definition: Instrument.cpp:521
Refer to DynExp::ParamsBase::dispatch_tag.
Definition: Instrument.h:1120
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...
Definition: Instrument.cpp:419
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...
Definition: Instrument.cpp:317
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.
Definition: Instrument.cpp:210
bool HandleTask(InstrumentInstance &Instance)
Executes and removes the next pending task from the instrument's task queue.
Definition: Instrument.cpp:254
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 UpdateData() const
Enqueues an update task (instance of class UpdateTaskBase).
Definition: Instrument.cpp:237
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 ...
Definition: Instrument.cpp:385
void EnqueueArriveAtLatchTask(std::latch &Latch) const
Enqueues a task which arrives at a latch when executed (instance of class ArriveAtLatchTask).
Definition: Instrument.cpp:247
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 void OnPrepareExitChild() const
This function enables derived classes to enqueue tasks to be executed directly before the final exit ...
Definition: Instrument.h:720
void UpdateDataInternal()
Inserts an update task (UpdateTaskBase) into the instrument's task queue. Override UpdateAdditionalDa...
Definition: Instrument.cpp:280
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...
Definition: Instrument.cpp:347
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().
Definition: Instrument.cpp:327
std::exception_ptr GetExceptionChild([[maybe_unused]] const std::chrono::milliseconds Timeout) const override final
Definition: Instrument.cpp:409
InstrumentDataTypeSyncPtrType GetInstrumentData(const std::chrono::milliseconds Timeout=GetInstrumentDataTimeoutDefault)
Locks the mutex of the instrument data class instance InstrumentData assigned to this InstrumentBase ...
Definition: Instrument.cpp:222
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
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...
Definition: Instrument.cpp:232
void OnError()
Derived classes can perform critical shutdown actions after an error has occurred....
Definition: Instrument.cpp:290
virtual ~InstrumentBase()=0
Definition: Instrument.cpp:218
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 ...
Definition: Instrument.cpp:340
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().
Definition: Instrument.cpp:189
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...
Definition: Instrument.cpp:178
std::unique_ptr< TaskBase > PopTaskBack()
Removes a task from the back of an instrument's task queue.
Definition: Instrument.cpp:112
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.
Definition: Instrument.cpp:165
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.
Definition: Instrument.cpp:98
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.
Definition: Instrument.cpp:126
void RemoveAllTasksExceptFront()
Clears the instrument's task queue but keeps the front task (the task with highest priority which is ...
Definition: Instrument.cpp:170
void CheckQueueState(bool CallFromInstrThread) const
Checks whether it is currently allowed to enqueue tasks into the instrument task queue.
Definition: Instrument.cpp:194
void RemoveTaskFromQueue(TaskQueueIteratorType &Task)
Removes a task from the instrument's task queue and inserts it into the instrument's list of finished...
Definition: Instrument.cpp:157
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.
Definition: Instrument.cpp:430
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.
Definition: Instrument.cpp:473
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.
Definition: Instrument.h:1079
std::atomic< TaskState > State
Holds the task's current state. Refer to TaskBase::TaskState.
Definition: Instrument.h:1078
bool IsLocked() const noexcept
Determines whether the task is locked.
Definition: Instrument.cpp:465
bool Run(InstrumentInstance &Instance)
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
Definition: Instrument.cpp:481
const CallbackType CallbackFunc
This callback function is called after the task has finished (either successfully or not) with a refe...
Definition: Instrument.h:1072
virtual ~TaskBase()=0
The destructor aborts a waiting task setting State to TaskState::Aborted. Then, it calls CallbackFunc...
Definition: Instrument.cpp:442
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...
Definition: Instrument.cpp:543
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.
Definition: Instrument.h:1182
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
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.
Definition: Object.h:1835
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
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.