DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
Module.cpp
Go to the documentation of this file.
1// This file is part of DynExp.
2
3#include "stdafx.h"
4#include "moc_Module.cpp"
5#include "Module.h"
6#include "DynExpManager.h"
7
8namespace DynExp
9{
10 int ModuleThreadMain(std::unique_ptr<RunnableInstance>&& InstancePtr, RunnableObject* BaseObject)
11 {
12 InstancePtr->BlockUntilReadyToStart();
13
14 auto const Module = static_cast<ModuleBase*>(BaseObject);
15 auto& Instance = static_cast<ModuleInstance&>(*InstancePtr);
16 bool IsExiting = false;
17 std::chrono::time_point<std::chrono::system_clock> LastMainLoopExecution; // LastUpdate.time_since_epoch() == 0 now.
18 auto ReturnCode = Util::DynExpErrorCodes::NoError;
19
20 try
21 {
22 // Throw if Module->TreatModuleExceptionsAsWarnings() is true, but MaxAllowedSubsequentExceptions have been occurred
23 // in a row to avoid infinite loops due to an exception occurring in each pass.
24 unsigned int NumSubsequentExceptions = 0;
25 constexpr unsigned int MaxAllowedSubsequentExceptions = 10;
26
27 auto& NewEventNotifier = Module->GetModuleData()->ModuleThreadOnly.GetNewEventNotifier();
28
29 while (!IsExiting)
30 {
31 try
32 {
33 if (Module->IsExiting() || Instance.IsExiting())
34 IsExiting = true;
35
36 if (!IsExiting)
37 {
38 if (!Instance.CareAboutWrappers())
39 {
40 if (!Module->IsPaused())
41 {
42 Module->ModuleThreadOnly.OnPause(Instance);
43 Module->SetPaused(true, Instance.GetNotReadyObjectNamesString());
44 }
45 else
46 Module->ModuleThreadOnly.SetReasonWhyPaused(Instance.GetNotReadyObjectNamesString());
47
48 std::this_thread::sleep_for(std::chrono::milliseconds(100));
49 continue;
50 }
51 else if (Module->IsPaused())
52 {
53 Module->SetPaused(false);
54 Module->ModuleThreadOnly.OnResume(Instance);
55 }
56 }
57
58 while (Module->GetModuleData()->GetNumEnqueuedEvents())
59 Module->ModuleThreadOnly.HandleEvent(Instance);
60
61 if (!IsExiting)
62 {
63 auto MainLoopDelay = Module->GetMainLoopDelay();
64 auto Now = std::chrono::system_clock::now();
65
66 if (Now - LastMainLoopExecution >= MainLoopDelay || MainLoopDelay == decltype(MainLoopDelay)::max())
67 {
68 ReturnCode = Module->ModuleThreadOnly.ModuleMainLoop(Instance);
69
70 if (ReturnCode != Util::DynExpErrorCodes::NoError)
71 IsExiting = true;
72
73 LastMainLoopExecution = Now;
74 }
75
76 if (MainLoopDelay == decltype(MainLoopDelay)::max())
77 NewEventNotifier.Wait();
78 else if (MainLoopDelay.count() == 0)
79 std::this_thread::yield();
80 else
81 NewEventNotifier.Wait(MainLoopDelay);
82 }
83
84 NumSubsequentExceptions = 0;
85 }
86 catch ([[maybe_unused]] const Util::LinkedObjectNotLockedException& e)
87 {
88 // In this case, terminate the module since this error cannot be fixed while the module is running.
89 throw;
90 }
91 catch ([[maybe_unused]] const Util::InvalidObjectLinkException& e)
92 {
93 // In this case, terminate the module since this error cannot be fixed while the module is running.
94 throw;
95 }
96 catch (const Util::Exception& e)
97 {
98 ++NumSubsequentExceptions;
99
100 if (Module->TreatModuleExceptionsAsWarnings() && NumSubsequentExceptions < MaxAllowedSubsequentExceptions)
101 Module->SetWarning(e);
102 else
103 throw;
104 }
105 catch (const std::exception& e)
106 {
107 ++NumSubsequentExceptions;
108
109 if (Module->TreatModuleExceptionsAsWarnings() && NumSubsequentExceptions < MaxAllowedSubsequentExceptions)
110 Module->SetWarning(e.what(), Util::DynExpErrorCodes::GeneralError);
111 else
112 throw;
113 }
114 // No catch (...) to terminate module in that case regardless of TreatExceptionsAsWarnings
115 // since we do not know at all what has happened.
116 }
117 }
118 catch (const Util::Exception& e)
119 {
120 Util::EventLog().Log("A module has been terminated because of the error reported below.", Util::ErrorType::Error);
121 Util::EventLog().Log(e);
122
123 Module->ModuleThreadOnly.SetException(std::current_exception());
124 Module->ModuleThreadOnly.OnError(Instance);
125
126 return e.ErrorCode;
127 }
128 catch (const std::exception& e)
129 {
130 Util::EventLog().Log("A module has been terminated because of the following error: " + std::string(e.what()), Util::ErrorType::Error);
131
132 Module->ModuleThreadOnly.SetException(std::current_exception());
133 Module->ModuleThreadOnly.OnError(Instance);
134
136 }
137 catch (...)
138 {
139 Util::EventLog().Log("A module has been terminated because of an unknown error.", Util::ErrorType::Error);
140
141 Module->ModuleThreadOnly.SetException(std::current_exception());
142 Module->ModuleThreadOnly.OnError(Instance);
143
145 }
146
147 return ReturnCode;
148 }
149
153
155 {
156 if (!Event)
157 throw Util::InvalidArgException("Event cannot be nullptr.");
158
159 EventQueue.push(std::move(Event));
161 }
162
164 {
165 if (EventQueue.empty())
166 return nullptr;
167
168 auto Event = std::move(EventQueue.front());
169 EventQueue.pop();
170
171 return Event;
172 }
173
174 std::exception_ptr ModuleDataBase::GetException() const noexcept
175 {
177 return std::make_exception_ptr(Util::Exception());
178
179 return ModuleException;
180 }
181
183 {
184 HasException = false;
185 ModuleException = nullptr;
186 EventQueueType().swap(EventQueue); // clear EventQueue
187
189 }
190
191 void ModuleDataBase::SetException(std::exception_ptr Exception) noexcept
192 {
193 IndicateException();
194
195 ModuleException = Exception;
196 }
197
201
205
206 ModuleBase::ModuleBase(const std::thread::id OwnerThreadID, ParamsBasePtrType&& Params)
207 : RunnableObject(OwnerThreadID, std::move(Params)),
208 ModuleThreadOnly(*this), EventListenersOnly(*this),
209 ModuleData(std::move(dynamic_Params_cast<ModuleBase>(GetParams())->ModuleData))
210 {
211 if (!ModuleData)
212 throw Util::InvalidArgException("ModuleData cannot be nullptr.");
213 }
214
218
220 {
221 return ModuleDataTypeSyncPtrType(ModuleData.get(), Timeout);
222 }
223
224 ModuleBase::ModuleDataTypeSyncPtrConstType ModuleBase::GetModuleData(const std::chrono::milliseconds Timeout) const
225 {
226 return ModuleDataTypeSyncPtrConstType(ModuleData.get(), Timeout);
227 }
228
230 {
231 GetNonConstModuleData()->EnqueueEvent(std::move(Event));
232 }
233
235 {
236 return ModuleDataTypeSyncPtrType(ModuleData.get(), Timeout);
237 }
238
240 {
242
244
245 {
246 // Locks ModuleData
247 auto ModuleDataPtr = GetModuleData();
248
249 if (!ModuleDataPtr->GetNumEnqueuedEvents())
250 return;
251
252 EventPtr = ModuleDataPtr->PopEvent();
253 } // ModuleData unlocked here
254
255 if (EventPtr)
256 EventPtr->Invoke(Instance);
257 }
258
260 {
262
263 RegisteredEvents.push_back(&EventListeners);
264 }
265
267 {
269
270 auto RegisteredEvent = std::find(RegisteredEvents.cbegin(), RegisteredEvents.cend(), &EventListeners);
271 if (RegisteredEvent == RegisteredEvents.cend())
272 return;
273
274 RegisteredEvents.erase(RegisteredEvent);
275 }
276
283
284 void ModuleBase::SetException(std::exception_ptr Exception) noexcept
285 {
286 try
287 {
288 // Locking ModuleData may throw.
289 GetModuleData()->ModuleBaseOnly.SetException(Exception);
290 }
291 catch (...)
292 {
293 // Atomic operation avoids locking ModuleData.
294 ModuleData->ModuleBaseOnly.IndicateException();
295 }
296 }
297
299 {
301
302 OnPauseChild(Instance);
303 }
304
306 {
308
309 OnResumeChild(Instance);
310 }
311
313 {
315
316 try
317 {
318 OnErrorChild(Instance);
319 }
320 catch (const Util::Exception& e)
321 {
322 Util::EventLog().Log("Calling a module's error handler, the error listed below occurred.", Util::ErrorType::Error);
323 Util::EventLog().Log(e);
324 }
325 catch (const std::exception& e)
326 {
327 Util::EventLog().Log("Calling a module's error handler, the error listed below occurred.", Util::ErrorType::Error);
328 Util::EventLog().Log(e.what());
329 }
330 catch (...)
331 {
332 Util::EventLog().Log("Calling a module's error handler, an unknown error occurred.", Util::ErrorType::Error);
333 }
334 }
335
337 {
338 ModuleData->ModuleBaseOnly.Reset();
339 RegisteredEvents.clear();
340
342 }
343
345 {
347
348 auto InstancePtr = std::make_unique<ModuleInstance>(*this, MakeThreadExitedPromise(), ModuleBase::ModuleDataGetterType{
350 });
351
352 MakeThread(ModuleThreadMain, std::move(InstancePtr));
353 }
354
356 {
357 GetModuleData()->ModuleBaseOnly.GetNewEventNotifier().Notify();
358 }
359
360 void ModuleBase::TerminateChild(const std::chrono::milliseconds Timeout)
361 {
362 try
363 {
366 }
367 catch (const Util::Exception& e)
368 {
369 // Exception occurring while trying to issue an OnExit event is swallowed and logged. It is tried to terminate
370 // the module anyway.
371 Util::EventLog().Log("A module has been terminated whithout cleaning up since the error reported below has occurred while issuing an exit event.",
373 Util::EventLog().Log(e);
374 }
375 }
376
377 std::unique_ptr<BusyDialog> ModuleBase::MakeStartupBusyDialogChild(QWidget* ParentWidget) const
378 {
379 auto StartupDialog = std::make_unique<BusyDialog>(ParentWidget);
380 StartupDialog->SetDescriptionText("Starting module's dependencies...");
381
382 return StartupDialog;
383 }
384
385 std::exception_ptr ModuleBase::GetExceptionChild(const std::chrono::milliseconds Timeout) const
386 {
387 using namespace std::chrono_literals;
388
389 // If ModuleData cannot be locked because it is continuously locked by main/module thread, dead lock
390 // is avoided since GetModuleData throws Util::TimeoutException after timeout in this case.
391 // Short timeout only since main thread should not block.
393 }
394
396 {
397 using namespace std::chrono_literals;
398 auto LockedModuleData = GetModuleData(ShortTimeoutDefault);
399
400 auto Exception = GetExceptionUnsafe(LockedModuleData);
401 Util::ForwardException(Exception);
402
403 return IsRunning() && !IsExiting();
404 }
405
407 {
408 // Copy vector since EventListenersBase::Deregister() removes entry from RegisteredEvents
409 // via call to ModuleBase::RemoveRegisteredEvent().
410 auto Events = RegisteredEvents;
411
412 for (auto Event : Events)
413 Event->Deregister(*this);
414 }
415
416 ModuleInstance::ModuleInstance(ModuleBase& Owner, std::promise<void>&& ThreadExitedPromise,
417 const ModuleBase::ModuleDataGetterType ModuleDataGetter)
418 : RunnableInstance(Owner, std::move(ThreadExitedPromise)),
419 ModuleDataGetter(ModuleDataGetter)
420 {
421 }
422
424 : RunnableInstance(std::move(Other)), ModuleDataGetter(Other.ModuleDataGetter)
425 {
426 }
427
431
433 {
434 static InterModuleEventLibrary Lib;
435
436 return Lib;
437 }
438
440 {
441 return Qt::CustomizeWindowHint | Qt::WindowTitleHint |
442 Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint;
443 }
444
446 {
447 return Qt::CustomizeWindowHint | Qt::WindowTitleHint |
448 Qt::WindowCloseButtonHint;
449 }
450
452 : QWidget(Parent), Owner(Owner), DynExpMgr(nullptr),
453 DockWindowShortcut(new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_D), this)),
454 FocusMainWindowShortcut(new QShortcut(QKeySequence(Qt::CTRL | Qt::Key_0), this))
455 {
456 connect(DockWindowShortcut, &QShortcut::activated, this, &QModuleWidget::OnDockWindow);
457 connect(FocusMainWindowShortcut, &QShortcut::activated, this, &QModuleWidget::OnFocusMainWindow);
458 }
459
460 Qt::WindowFlags QModuleWidget::GetQtWindowFlags() const noexcept
461 {
463 }
464
466 {
468 }
469
470 void QModuleWidget::SetDataSaveDirectory(std::string_view Directory) const
471 {
473 }
474
476 {
477 DockWindowShortcut->setEnabled(Enable);
478 }
479
480 void QModuleWidget::closeEvent(QCloseEvent* Event)
481 {
482 if (DynExpMgr)
483 if (QMessageBox::question(this, "DynExp - Stop module?",
484 QString::fromStdString("Do you want to stop this module?"),
485 QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, QMessageBox::StandardButton::No)
486 == QMessageBox::StandardButton::Yes)
487 if (DynExpMgr->StopItem(&Owner))
488 {
489 Event->accept();
490 return;
491 }
492
493 Event->ignore();
494 }
495
500
502 {
503 Owner.SetFocus();
504 }
505
510
511 QModuleDockWidget::QModuleDockWidget(QModuleBase& Owner, QWidget* Parent, Qt::WindowFlags Flags)
512 : QDockWidget(Parent, Flags), Owner(Owner)
513 {
514 }
515
516 void QModuleDockWidget::closeEvent(QCloseEvent* Event)
517 {
518 Event->ignore();
520 }
521
522 // Delegate Ctrl+1 - Ctrl+9 to main window
523 void QModuleDockWidget::keyPressEvent(QKeyEvent* Event)
524 {
525 if (Event->modifiers().testFlag(Qt::ControlModifier))
526 if (Event->key() >= Qt::Key_1 && Event->key() <= Qt::Key_1 + 8)
527 {
530
531 return;
532 }
533
534 QDockWidget::keyPressEvent(Event);
535 }
536
541
542 void WindowStyleParamsExtension::ApplyTo(QWidget& Widget, bool Show) const
543 {
545 Widget.showMinimized();
546 else
547 {
548 QPoint WindowPos(WindowPosX, WindowPosY);
549 QSize WindowSize(Util::NumToT<int>(WindowWidth.Get()), Util::NumToT<int>(WindowHeight.Get()));
550 if (!WindowSize.isEmpty())
551 {
552 Widget.move(WindowPos);
553 Widget.resize(WindowSize);
554 }
555
556 if (Show)
557 {
559 Widget.showMaximized();
560 else
561 Widget.showNormal();
562 }
563 }
564 }
565
566 void WindowStyleParamsExtension::FromWidget(const QWidget& Widget)
567 {
568 if (Widget.isMinimized())
570 else
571 {
573
574 auto WindowPos = Widget.pos();
575 auto WindowSize = Widget.size();
576 WindowPosX = WindowPos.x();
577 WindowPosY = WindowPos.y();
578 WindowWidth = WindowSize.width();
579 WindowHeight = WindowSize.height();
580 }
581 }
582
586
590
591 QModuleBase::QModuleBase(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType&& Params)
592 : ModuleBase(OwnerThreadID, std::move(Params)), Widget(nullptr), MdiArea(nullptr)
593 {
594 }
595
599
600 QAction& QModuleBase::InitUI(DynExpManager& DynExpMgr, QMdiArea* const MdiArea)
601 {
602 if (!MdiArea)
603 throw Util::InvalidArgException("MdiArea cannot be nullptr.");
604
605 // Make UI
606 auto WidgetPtr = MakeUIWidget();
607 if (!WidgetPtr)
608 throw Util::InvalidDataException("Overridden QModuleBase::MakeUIWidget() must not return nullptr.");
609 Widget = WidgetPtr.get();
610 Widget->DynExpMgr = &DynExpMgr;
611
612 // Initialize container widgets
613 this->MdiArea = MdiArea;
614 MdiSubWindow = std::make_unique<QMdiSubWindow>(); // Gets a parent when inserting into MdiArea
615 DockWidget = std::make_unique<QModuleDockWidget>(*this, nullptr, Widget->GetQtWindowFlags()); // nullptr parent to make it floating.
616 DockWidget->setAllowedAreas(Qt::DockWidgetArea::NoDockWidgetArea);
617 DockWidget->setFeatures(QDockWidget::DockWidgetFeature::DockWidgetClosable | QDockWidget::DockWidgetFeature::DockWidgetFloatable);
618 DockWidget->setLocale(QLocale(QLocale::Language::English, QLocale::Country::UnitedStates)); // For number format.
619
620 // Insert new Widget into main MDI area. MdiSubWindow becomes Widget's parent.
621 MdiSubWindow->setWidget(WidgetPtr.release());
622 MdiArea->addSubWindow(MdiSubWindow.get(), Widget->GetQtWindowFlags());
624
627
628 // Create action to push module's window into focus.
629 // Longer timeout while fetching object name since it could take longer if the entire project is started (empiric value).
630 ModuleWindowFocusAction = std::make_unique<QAction>(QString::fromStdString(GetObjectName(std::chrono::seconds(1))));
631 QObject::connect(ModuleWindowFocusAction.get(), &QAction::triggered, Widget, &QModuleWidget::OnFocusWindow);
632
633 MdiSubWindow->show();
634
636 }
637
639 {
640 // Widget is deleted by its respective parent's destructor.
641 MdiSubWindow.reset();
642 DockWidget.reset();
644 }
645
647 {
648 if (!Widget)
649 return;
650
651 Widget->setEnabled(false);
652 }
653
655 {
656 if (!Widget)
657 return;
658
659 Widget->setEnabled(true);
661 }
662
664 {
666 throw Util::InvalidStateException("UI widget has not been created yet.");
667
668 if (Widget->parent() != MdiSubWindow.get())
670 else
671 ModuleWindowFocusAction->setIcon(QIcon());
672 }
673
675 {
676 if (!Widget || !MdiArea || !MdiSubWindow || !DockWidget)
677 return;
678
679 DockWidget->hide();
680 MdiSubWindow->setWidget(Widget); // Sets Widget parent.
681 MdiArea->addSubWindow(MdiSubWindow.get(), Widget->GetQtWindowFlags());
682 MdiSubWindow->show();
684 }
685
687 {
688 if (!Widget || !MdiArea || !MdiSubWindow || !DockWidget)
689 return;
690
691 MdiArea->removeSubWindow(MdiSubWindow.get());
692 MdiSubWindow->setWidget(nullptr);
693 Widget->setParent(DockWidget.get());
694 DockWidget->setWidget(Widget);
695 DockWidget->showNormal();
697 }
698
700 {
701 if (!Widget || !MdiArea || !MdiSubWindow || !DockWidget)
702 return;
703
704 if (Widget->parent() == MdiSubWindow.get())
705 UndockWindow();
706 else
707 DockWindow();
708
709 SetFocus();
710 }
711
712 void QModuleBase::SetFocus() noexcept
713 {
714 if (!Widget || !MdiArea || !MdiSubWindow || !DockWidget)
715 return;
716
717 if (Widget->parent() != MdiSubWindow.get())
718 {
719 Widget->activateWindow();
720 Widget->raise();
721 }
722 else
723 {
725 MdiArea->setActiveSubWindow(MdiSubWindow.get());
726 }
727 }
728
730 {
731 if (!Widget)
732 return;
733
735 }
736
737 void QModuleBase::SendKeyPressEventToMainWindow(QKeyEvent* Event) noexcept
738 {
739 if (!Widget)
740 return;
741
742 Widget->DynExpMgr->PostKeyPressEvent(Event);
743 }
744
746 {
747 // Just because this is the default and we don't want to throw here.
748 if (!Widget || !MdiSubWindow)
749 return true;
750
751 return Widget->parent() == MdiSubWindow.get();
752 }
753
755 {
756 if (!Widget || !MdiSubWindow)
757 throw Util::InvalidStateException("UI widget has not been created yet.");
758
759 if (Widget->parent() != MdiSubWindow.get())
760 return false;
761
762 return MdiArea->currentSubWindow() == MdiSubWindow.get();
763 }
764
766 {
767 if (!Widget || !MdiArea || !MdiSubWindow || !DockWidget)
768 return;
769
770 auto ModuleParams = DynExp::dynamic_Params_cast<QModuleBase>(GetParams());
771 if (ModuleParams->WindowStyleParams.WindowDockingState == WindowStyleParamsExtension::WindowDockingStateType::Docked)
772 DockWindow();
773 else
774 UndockWindow();
775 ModuleParams->WindowStyleParams.ApplyTo(IsWindowDocked() ? static_cast<QWidget&>(*MdiSubWindow) : static_cast<QWidget&>(*DockWidget));
776 }
777
779 {
780 if (!Widget || !MdiArea || !MdiSubWindow || !DockWidget)
781 return;
782
783 auto ModuleParams = DynExp::dynamic_Params_cast<QModuleBase>(GetParams());
784 ModuleParams->WindowStyleParams.FromWidget(IsWindowDocked() ? static_cast<QWidget&>(*MdiSubWindow) : static_cast<QWidget&>(*DockWidget));
785 ModuleParams->WindowStyleParams.WindowDockingState = IsWindowDocked() ?
787 }
788
789 void QModuleBase::SetWidgetProperties(QWidget* const WindowWidget) const
790 {
791 if (!WindowWidget)
792 throw Util::InvalidArgException("WindowWidget cannot be nullptr.");
793
794 // Longer timeout while fetching object name since it could take longer if the entire project is started (empiric value).
795 WindowWidget->setWindowTitle(QString::fromStdString(GetObjectName(std::chrono::seconds(1))));
796 WindowWidget->setWindowIcon(QIcon(DynExpUI::Icons::Module));
797
798 if (!Widget->AllowResize())
799 WindowWidget->layout()->setSizeConstraint(QLayout::SetFixedSize);
800 }
801
806}
Implements DynExp's main UI window called DynExpManager.
Implementation of DynExp module objects.
Implements DynExp's main window as a Qt-based user interface (UI).
void SetDataSaveDirectory(std::string_view Directory) const
Sets a path where modules might save recorded data to. Used by Util::PromptSaveFilePathModule() to st...
void FocusMainWindow() noexcept
Focuses/activates DynExp's main window and moves it on top of other windows if possible.
std::string GetDataSaveDirectory() const
Recalls a path where modules might save recorded data to. Used by Util::PromptSaveFilePathModule() to...
bool StopItem(DynExp::RunnableObject *Object, bool Force=false) noexcept
Calls DynExp::RunnableObject::Terminate() on a DynExp::RunnableObject instance.
virtual ~EventBase()=0
Definition Module.cpp:150
Common base class for all managers of event listeners of type TypedEventListeners....
Definition Module.h:913
virtual ~InterModuleEventBase()=0
Definition Module.cpp:428
Library type that holds factory functions to all available inter-module events.
Definition Module.h:1324
static InterModuleEventLibrary & Get()
Getter for the singleton instance of InterModuleEventLibrary.
Definition Module.cpp:432
Base class for modules. Modules implement programs on their own (e.g. measurement protocols or server...
Definition Module.h:428
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 Module.cpp:360
ModuleDataTypeSyncPtrType GetModuleData(const std::chrono::milliseconds Timeout=GetModuleDataTimeoutDefault)
Locks the mutex of the module data class instance ModuleData assigned to this ModuleBase instance and...
Definition Module.cpp:219
virtual void OnErrorChild(ModuleInstance &Instance) const
This handler gets called just before the module thread terminates due to an exception....
Definition Module.h:718
void OnPause(ModuleInstance &Instance)
This handler gets called just after the module pauses due to e.g. an error in an instrument the modul...
Definition Module.cpp:298
void NotifyChild() override final
Notify derived classes that some state has changed (e.g. the termination of Thread is requested) and ...
Definition Module.cpp:355
void RunChild() override final
Refer to Run().
Definition Module.cpp:344
void OnDeregisterEvents(ModuleInstance *Instance) const
This event is triggered after the OnExit event. It calls EventListenersBase::Deregister() for all man...
Definition Module.cpp:406
static auto GetExceptionUnsafe(const ModuleDataTypeSyncPtrConstType &ModuleDataPtr)
Getter for ModuleDataBase::ModuleException assuming that the module data has already been locked.
Definition Module.h:647
virtual void OnInit(ModuleInstance *Instance) const
This event is triggered right before the module thread starts. Override it to lock instruments this m...
Definition Module.h:764
const std::unique_ptr< ModuleDataType > ModuleData
Module data belonging to this ModuleBase instance.
Definition Module.h:788
virtual ~ModuleBase()=0
Definition Module.cpp:215
void ResetImpl(dispatch_tag< RunnableObject >) override final
Refer to DynExp::Object::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of every de...
Definition Module.cpp:336
virtual void OnResumeChild(ModuleInstance &Instance) const
This handler gets called just after the module resumed from a paused state. Override OnResumeChild() ...
Definition Module.h:717
void SetException(std::exception_ptr Exception) noexcept
Sets this module instance to an error state and tries to store the exception responsible for the erro...
Definition Module.cpp:284
void MakeAndEnqueueEvent(ReceiverType *Receiver, EventType EventFuncPtr, ArgsTs &&...Args) const
Calls MakeEvent() to construct a new event and subsequently enqueues the event into the module's even...
Definition Module.h:827
virtual void OnExit(ModuleInstance *Instance) const
This event is triggered right before the module thread terminates (not due to an exception,...
Definition Module.h:773
void EnqueueEvent(ModuleDataBase::EventPtrType &&Event) const
Enqueues Event at the module event queue's back. Takes ownership of the event. Notifies the module ow...
Definition Module.cpp:229
void RemoveRegisteredEvent(EventListenersBase &EventListeners)
Removes a manager of event listeners from RegisteredEvents if it was added before....
Definition Module.cpp:266
void HandleEvent(ModuleInstance &Instance)
Executes and removes the next pending event from the module's event queue.
Definition Module.cpp:239
ModuleBase(const std::thread::id OwnerThreadID, ParamsBasePtrType &&Params)
Constructs a ModuleBase instance.
Definition Module.cpp:206
Util::SynchronizedPointer< const ModuleDataType > ModuleDataTypeSyncPtrConstType
Alias for the return type of ModuleBase::GetModuleData() const. Data class instances wrapped into Uti...
Definition Module.h:499
void OnResume(ModuleInstance &Instance)
This handler gets called just after the module resumed from a paused state. Override OnResumeChild() ...
Definition Module.cpp:305
Util::SynchronizedPointer< ModuleDataType > ModuleDataTypeSyncPtrType
Alias for the return type of ModuleBase::GetModuleData(). Data class instances wrapped into Util::Syn...
Definition Module.h:493
std::unique_ptr< BusyDialog > MakeStartupBusyDialogChild(QWidget *ParentWidget) const override final
Override to make this function return a pointer to a BusyDialog instance. Refer to Run().
Definition Module.cpp:377
std::vector< EventListenersBase * > RegisteredEvents
Holds a list of pointers to managers of event listeners of the events this module has registered/subs...
Definition Module.h:797
void OnError(ModuleInstance &Instance)
This handler gets called just before the module thread terminates due to an exception....
Definition Module.cpp:312
virtual Util::DynExpErrorCodes::DynExpErrorCodes ModuleMainLoop(ModuleInstance &Instance)=0
Module main loop. The function is executed periodically by the module thread. Also refer to GetMainLo...
void AddRegisteredEvent(EventListenersBase &EventListeners)
Adds a manager of event listeners to RegisteredEvents. Called indirectly by TypedEventListeners::Regi...
Definition Module.cpp:259
static constexpr auto GetModuleDataTimeoutDefault
Determines the default timeout for GetModuleData() to lock the mutex synchronizing the module's data ...
Definition Module.h:550
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.
Definition Module.cpp:385
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 Module.cpp:395
virtual void OnPauseChild(ModuleInstance &Instance) const
This handler gets called just after the module pauses due to e.g. an error in an instrument the modul...
Definition Module.h:716
ModuleDataTypeSyncPtrType GetNonConstModuleData(const std::chrono::milliseconds Timeout=GetModuleDataTimeoutDefault) const
Always allows ModuleBase to obtain a non-const pointer to the module's data - even in const event fun...
Definition Module.cpp:234
Util::DynExpErrorCodes::DynExpErrorCodes ExecModuleMainLoop(ModuleInstance &Instance)
Runs ModuleMainLoop().
Definition Module.cpp:277
virtual ~ModuleConfiguratorBase()=0
Definition Module.cpp:202
std::exception_ptr ModuleException
Used to transfer exceptions from the module thread to the main (user interface) thread....
Definition Module.h:366
Util::OneToOneNotifier NewEventNotifier
Notifies the thread of the module which owns the respective ModuleDataBase's instance when an event h...
Definition Module.h:352
std::queue< EventPtrType > EventQueueType
A module's event queue is a FIFO queue owning the enqueued events.
Definition Module.h:183
std::unique_ptr< EventBase > EventPtrType
Pointer owning an event.
Definition Module.h:178
void SetException(std::exception_ptr Exception) noexcept
Setter for ModuleException.
Definition Module.cpp:191
std::exception_ptr GetException() const noexcept
Getter for ModuleDataBase::ModuleException. If ModuleDataBase::ModuleException is nullptr and ModuleD...
Definition Module.cpp:174
void Reset()
Resets the ModuleDataBase's instance and calls ResetImpl(dispatch_tag<ModuleDataBase>) subsequently.
Definition Module.cpp:182
void EnqueueEvent(EventPtrType &&Event)
Enqueues Event at the module event queue's back. Takes ownership of the event. Notifies the module ow...
Definition Module.cpp:154
EventQueueType EventQueue
FIFO event queue of the module which owns the respective ModuleDataBase's instance.
Definition Module.h:345
std::atomic< bool > HasException
If set to true, indicates to the main (user interface) thread that an exception has happened in the m...
Definition Module.h:359
virtual void ResetImpl(dispatch_tag< ModuleDataBase >)
Refer to DynExp::ModuleDataBase::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of ...
Definition Module.h:326
EventPtrType PopEvent()
Removes one event from the event queue's front and returns the event. Ownership of the event is trans...
Definition Module.cpp:163
Refer to ParamsBase::dispatch_tag.
Definition Module.h:191
Defines data for a thread belonging to a ModuleBase instance. Refer to RunnableInstance.
Definition Module.h:840
ModuleInstance(ModuleBase &Owner, std::promise< void > &&ThreadExitedPromise, const ModuleBase::ModuleDataGetterType ModuleDataGetter)
Constructs a non-empty RunnableInstance instance.
Definition Module.cpp:416
virtual ~ModuleParamsBase()=0
Definition Module.cpp:198
ParamsConstTypeSyncPtrType GetParams(const std::chrono::milliseconds Timeout=GetParamsTimeoutDefault) const
Locks the mutex of the parameter class instance Params assigned to this Object instance and returns a...
Definition Object.cpp:436
auto GetObjectName(const std::chrono::milliseconds Timeout=GetParamsTimeoutDefault) const
Returns the name of this Object instance.
Definition Object.h:2128
Refer to ParamsBase::dispatch_tag.
Definition Object.h:2018
Base class for modules with a Qt-based user interface. Derive from this class to implement modules wi...
Definition Module.h:1660
void DockUndockWindow() noexcept
Toggles the docking state of Widget. Does nothing if any of Widget, MdiArea, MdiSubWindow,...
Definition Module.cpp:699
virtual ~QModuleBase()=0
Definition Module.cpp:596
virtual void UpdateParamsFromWindowStatesChild() override
UpdateParamsFromWindowStates() only calls UpdateParamsFromWindowStatesChild(). Override UpdateParamsF...
Definition Module.cpp:778
QModuleWidget * Widget
User interface widget belonging to the module.
Definition Module.h:1807
virtual void RestoreWindowStatesFromParamsChild() override
RestoreWindowStatesFromParams() only calls RestoreWindowStatesFromParamsChild(). Override RestoreWind...
Definition Module.cpp:765
bool IsActiveWindow()
Checks whether Widget is docked and active.
Definition Module.cpp:754
void FocusMainWindow() noexcept
Focuses/activates DynExp's main window calling DynExpManager::FocusMainWindow(). Does nothing if Widg...
Definition Module.cpp:729
void DisableUI()
Disables all user interface controls in Widget. Does nothing if Widget is nullptr.
Definition Module.cpp:646
bool IsWindowDocked() noexcept
Checks whether Widget is docked.
Definition Module.cpp:745
virtual void UpdateUIChild(const ModuleBase::ModuleDataGetterType &ModuleDataGetter)
Use this function to update the module's user interface widget according to the module data obtained ...
Definition Module.h:1804
QMdiArea * MdiArea
Pointer to DynExpManager's QMdiArea.
Definition Module.h:1812
void UndockWindow() noexcept
Undocks Widget from MdiArea. Does nothing if any of Widget, MdiArea, MdiSubWindow,...
Definition Module.cpp:686
void SetWidgetProperties(QWidget *const WindowWidget) const
Used by InitUI() to set the widget properties (such as title, icon, size constraints) of MdiSubWindow...
Definition Module.cpp:789
virtual std::unique_ptr< QModuleWidget > MakeUIWidget()=0
Used by InitUI() as a factory function for the module's user interface widget. Create the widget here...
std::unique_ptr< QModuleDockWidget > DockWidget
Frame for Widget when the module window is undocked from MdiArea.
Definition Module.h:1809
void SetFocus() noexcept
Focuses/activates Widget and moves it on top of other windows if possible. Does nothing if any of Wid...
Definition Module.cpp:712
void HideUI()
Removes MdiSubWindow, DockWidget, and ModuleWindowFocusAction setting them to nullptr.
Definition Module.cpp:638
void SendKeyPressEventToMainWindow(QKeyEvent *Event) noexcept
Sends a Qt key press event to DynExp's main window calling DynExpManager::PostKeyPressEvent()....
Definition Module.cpp:737
void UpdateUI()
Enables the user interface controls in Widget. Does nothing if Widget is nullptr. Calls UpdateUIChild...
Definition Module.cpp:654
QAction & InitUI(DynExpManager &DynExpMgr, QMdiArea *const MdiArea)
Sets up the module's user interface widgets and window frames. Called by the main user interface thre...
Definition Module.cpp:600
std::unique_ptr< QMdiSubWindow > MdiSubWindow
Frame for Widget when the module window is docked to MdiArea.
Definition Module.h:1808
QModuleBase(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
Constructs a QModuleBase instance.
Definition Module.cpp:591
void UpdateModuleWindowFocusAction()
Updates the icon assigned to ModuleWindowFocusAction depending on whether Widget is docked to or undo...
Definition Module.cpp:663
void DockWindow() noexcept
Docks Widget to MdiArea. Does nothing if any of Widget, MdiArea, MdiSubWindow, or DockWidget are null...
Definition Module.cpp:674
std::unique_ptr< QAction > ModuleWindowFocusAction
Qt action to push module window into focus. When triggered, QModuleWidget::OnFocusWindow() in invoked...
Definition Module.h:1810
void ResetImpl(dispatch_tag< ModuleBase >) override final
Refer to DynExp::Object::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of every de...
Definition Module.cpp:802
void ResetImpl(dispatch_tag< ModuleDataBase >) override final
Refer to DynExp::ModuleDataBase::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of ...
Definition Module.cpp:537
QModuleBase & Owner
Module owning this user interface window.
Definition Module.h:1529
virtual void keyPressEvent(QKeyEvent *Event) override
Qt event indicating that keys were pressed when the QModuleDockWidget window was focused....
Definition Module.cpp:523
virtual void closeEvent(QCloseEvent *Event) override
Qt event indicating that the QModuleDockWidget window is closed. Docks the module window again to Dyn...
Definition Module.cpp:516
QModuleDockWidget(QModuleBase &Owner, QWidget *Parent, Qt::WindowFlags Flags)
Constructs a QModuleDockWidget instance.
Definition Module.cpp:511
virtual ~QModuleParamsBase()=0
Definition Module.cpp:583
void OnDockWindow()
Qt slot called when DockWindowShortcut is activated, calls QModuleBase::DockUndockWindow().
Definition Module.cpp:496
virtual bool AllowResize() const noexcept
Indicates the resizing behavior of the user interface window. Override to adjust.
Definition Module.h:1437
Qt::WindowFlags GetQtWindowFlags() const noexcept
Depending on thr return value of AllowResize(), returns either the return value of GetQtWindowFlagsRe...
Definition Module.cpp:460
void OnFocusWindow()
Qt slot called when QModuleBase::ModuleWindowFocusAction is triggered, calls QModuleBase::SetFocus().
Definition Module.cpp:501
virtual void closeEvent(QCloseEvent *Event) override
Qt event indicating that the module window is closed. Asks the user whether to terminate the module....
Definition Module.cpp:480
QModuleBase & Owner
Module owning this user interface window (reference, because it should never change nor be nullptr).
Definition Module.h:1478
static constexpr Qt::WindowFlags GetQtWindowFlagsResizable()
Default Qt window flags for resizable module windows.
Definition Module.cpp:439
QModuleWidget(QModuleBase &Owner, QWidget *Parent=nullptr)
Constructs a QModuleWidget instance.
Definition Module.cpp:451
void OnFocusMainWindow()
Qt slot called when FocusMainWindowShortcut is activated, calls QModuleBase::FocusMainWindow().
Definition Module.cpp:506
static constexpr Qt::WindowFlags GetQtWindowFlagsNonResizable()
Default Qt window flags for non-resizable module windows.
Definition Module.cpp:445
QShortcut * FocusMainWindowShortcut
Shortcut (Ctrl + 0) to activate/focus DynExp's main window.
Definition Module.h:1482
std::string GetDataSaveDirectory() const
Recalls a path where modules might save recorded data to. Used by Util::PromptSaveFilePathModule() to...
Definition Module.cpp:465
QShortcut * DockWindowShortcut
Shortcut (Ctrl + D) to dock/undock a module window to/from DynExp's main window.
Definition Module.h:1481
void SetDataSaveDirectory(std::string_view Directory) const
Sets a path where modules might save recorded data to. Used by Util::PromptSaveFilePathModule() to st...
Definition Module.cpp:470
void EnableDockWindowShortcut(bool Enable) noexcept
Enables/disables DockWindowShortcut.
Definition Module.cpp:475
DynExpManager * DynExpMgr
DynExp's main window (pointer, because it is set later by QModuleBase::InitUI()).
Definition Module.h:1479
Defines data for a thread belonging to a RunnableObject instance. This data is only accessed by the R...
Definition Object.h:3513
Defines an Object which possesses a thread it runs in. The RunnableObject can be started and stopped ...
Definition Object.h:2426
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
ParamsBase::Param< unsigned int > WindowWidth
Window width.
Definition Module.h:1612
ParamsBase::Param< int > WindowPosY
Window y coordinate.
Definition Module.h:1611
ParamsBase::Param< int > WindowPosX
Window x coordinate.
Definition Module.h:1610
ParamsBase::Param< WindowStateType > WindowState
Window show state.
Definition Module.h:1614
void FromWidget(const QWidget &Widget)
Assigns styles applied to Widget to the bundled parameters.
Definition Module.cpp:566
void ApplyTo(QWidget &Widget, bool Show=true) const
Applies the bundled style parameters to Widget.
Definition Module.cpp:542
ParamsBase::Param< unsigned int > WindowHeight
Window height.
Definition Module.h:1613
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
Data to operate on is invalid for a specific purpose. This indicates a corrupted data structure or fu...
Definition Exception.h:164
Thrown when RunnableInstance cannot lock an object to be used by another object due to an invalid lin...
Definition Exception.h:345
An operation cannot be performed currently since the related object is in an invalid state like an er...
Definition Exception.h:151
Thrown when RunnableInstance::LockObject() has not been called on an object link parameter to establi...
Definition Exception.h:330
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 UndockedWindow
constexpr auto Module
DynExp's main namespace contains the implementation of DynExp including classes to manage resources (...
int ModuleThreadMain(std::unique_ptr< RunnableInstance > &&InstancePtr, RunnableObject *BaseObject)
Modules run in their own thread. This is the module thread's main function.
Definition Module.cpp:10
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
DynExpErrorCodes
DynExp's error codes
Definition Exception.h:22
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.