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(ModuleInstance Instance, ModuleBase* const Module)
11 {
12 bool IsExiting = false;
13 std::chrono::time_point<std::chrono::system_clock> LastMainLoopExecution; // LastUpdate.time_since_epoch() == 0 now.
14 auto ReturnCode = Util::DynExpErrorCodes::NoError;
15
16 try
17 {
18 // Throw if Module->TreatModuleExceptionsAsWarnings() is true, but MaxAllowedSubsequentExceptions have been occurred
19 // in a row to avoid infinite loops due to an exception occurring in each pass.
20 unsigned int NumSubsequentExceptions = 0;
21 constexpr unsigned int MaxAllowedSubsequentExceptions = 10;
22
23 auto& NewEventNotifier = Module->GetModuleData()->ModuleThreadOnly.GetNewEventNotifier();
24
25 while (!IsExiting)
26 {
27 try
28 {
29 if (Module->IsExiting() || Instance.IsExiting())
30 IsExiting = true;
31
32 if (!IsExiting)
33 {
34 if (!Instance.CareAboutWrappers())
35 {
36 if (!Module->IsPaused())
37 {
38 Module->ModuleThreadOnly.OnPause(Instance);
39 Module->SetPaused(true, Instance.GetNotReadyObjectNamesString());
40 }
41 else
42 Module->ModuleThreadOnly.SetReasonWhyPaused(Instance.GetNotReadyObjectNamesString());
43
44 std::this_thread::sleep_for(std::chrono::milliseconds(100));
45 continue;
46 }
47 else if (Module->IsPaused())
48 {
49 Module->SetPaused(false);
50 Module->ModuleThreadOnly.OnResume(Instance);
51 }
52 }
53
54 while (Module->GetModuleData()->GetNumEnqueuedEvents())
55 Module->ModuleThreadOnly.HandleEvent(Instance);
56
57 if (!IsExiting)
58 {
59 auto MainLoopDelay = Module->GetMainLoopDelay();
60 auto Now = std::chrono::system_clock::now();
61
62 if (Now - LastMainLoopExecution >= MainLoopDelay || MainLoopDelay == decltype(MainLoopDelay)::max())
63 {
64 ReturnCode = Module->ModuleThreadOnly.ModuleMainLoop(Instance);
65
66 if (ReturnCode != Util::DynExpErrorCodes::NoError)
67 IsExiting = true;
68
69 LastMainLoopExecution = Now;
70 }
71
72 if (MainLoopDelay == decltype(MainLoopDelay)::max())
73 NewEventNotifier.Wait();
74 else if (MainLoopDelay.count() == 0)
75 std::this_thread::yield();
76 else
77 NewEventNotifier.Wait(MainLoopDelay);
78 }
79
80 NumSubsequentExceptions = 0;
81 }
82 catch ([[maybe_unused]] const Util::LinkedObjectNotLockedException& e)
83 {
84 // In this case, terminate the module since this error cannot be fixed while the module is running.
85 throw;
86 }
87 catch ([[maybe_unused]] const Util::InvalidObjectLinkException& e)
88 {
89 // In this case, terminate the module since this error cannot be fixed while the module is running.
90 throw;
91 }
92 catch (const Util::Exception& e)
93 {
94 ++NumSubsequentExceptions;
95
96 if (Module->TreatModuleExceptionsAsWarnings() && NumSubsequentExceptions < MaxAllowedSubsequentExceptions)
97 Module->SetWarning(e);
98 else
99 throw;
100 }
101 catch (const std::exception& e)
102 {
103 ++NumSubsequentExceptions;
104
105 if (Module->TreatModuleExceptionsAsWarnings() && NumSubsequentExceptions < MaxAllowedSubsequentExceptions)
106 Module->SetWarning(e.what(), Util::DynExpErrorCodes::GeneralError);
107 else
108 throw;
109 }
110 // No catch (...) to terminate module in that case regardless of TreatExceptionsAsWarnings
111 // since we do not know at all what has happened.
112 }
113 }
114 catch (const Util::Exception& e)
115 {
116 Util::EventLog().Log("A module has been terminated because of the error reported below.", Util::ErrorType::Error);
117 Util::EventLog().Log(e);
118
119 // std::abort() is called when (e.g. timeout) exception occurrs while setting the caught exception.
120 Module->GetModuleData()->ModuleThreadOnly.SetException(std::current_exception());
121 Module->ModuleThreadOnly.OnError(Instance);
122
123 return e.ErrorCode;
124 }
125 catch (const std::exception& e)
126 {
127 Util::EventLog().Log("A module has been terminated because of the following error: " + std::string(e.what()), Util::ErrorType::Error);
128
129 // std::abort() is called when (e.g. timeout) exception occurrs while setting the caught exception.
130 Module->GetModuleData()->ModuleThreadOnly.SetException(std::current_exception());
131 Module->ModuleThreadOnly.OnError(Instance);
132
134 }
135 catch (...)
136 {
137 Util::EventLog().Log("A module has been terminated because of an unknown error.", Util::ErrorType::Error);
138
139 // std::abort() is called when (e.g. timeout) exception occurrs while setting the caught exception.
140 Module->GetModuleData()->ModuleThreadOnly.SetException(std::current_exception());
141 Module->ModuleThreadOnly.OnError(Instance);
142
144 }
145
146 return ReturnCode;
147 }
148
152
154 {
155 if (!Event)
156 throw Util::InvalidArgException("Event cannot be nullptr.");
157
158 EventQueue.push(std::move(Event));
160 }
161
163 {
164 if (EventQueue.empty())
165 return nullptr;
166
167 auto Event = std::move(EventQueue.front());
168 EventQueue.pop();
169
170 return Event;
171 }
172
174 {
175 ModuleException = nullptr;
176 EventQueueType().swap(EventQueue); // clear EventQueue
177
179 }
180
184
188
189 ModuleBase::ModuleBase(const std::thread::id OwnerThreadID, ParamsBasePtrType&& Params)
190 : RunnableObject(OwnerThreadID, std::move(Params)),
191 ModuleThreadOnly(*this), EventListenersOnly(*this),
192 ModuleData(std::move(dynamic_Params_cast<ModuleBase>(GetParams())->ModuleData))
193 {
194 if (!ModuleData)
195 throw Util::InvalidArgException("ModuleData cannot be nullptr.");
196 }
197
201
203 {
204 return ModuleDataTypeSyncPtrType(ModuleData.get(), Timeout);
205 }
206
207 ModuleBase::ModuleDataTypeSyncPtrConstType ModuleBase::GetModuleData(const std::chrono::milliseconds Timeout) const
208 {
209 return ModuleDataTypeSyncPtrConstType(ModuleData.get(), Timeout);
210 }
211
213 {
214 GetNonConstModuleData()->EnqueueEvent(std::move(Event));
215 }
216
218 {
219 return ModuleDataTypeSyncPtrType(ModuleData.get(), Timeout);
220 }
221
223 {
225
227
228 {
229 // Locks ModuleData
230 auto ModuleDataPtr = GetModuleData();
231
232 if (!ModuleDataPtr->GetNumEnqueuedEvents())
233 return;
234
235 EventPtr = ModuleDataPtr->PopEvent();
236 } // ModuleData unlocked here
237
238 if (EventPtr)
239 EventPtr->Invoke(Instance);
240 }
241
243 {
245
246 auto RegisteredEvent = std::find(RegisteredEvents.cbegin(), RegisteredEvents.cend(), &EventListeners);
247 if (RegisteredEvent != RegisteredEvents.cend())
248 return;
249
250 RegisteredEvents.push_back(&EventListeners);
251 }
252
254 {
256
257 auto RegisteredEvent = std::find(RegisteredEvents.cbegin(), RegisteredEvents.cend(), &EventListeners);
258 if (RegisteredEvent == RegisteredEvents.cend())
259 return;
260
261 RegisteredEvents.erase(RegisteredEvent);
262 }
263
270
272 {
274
275 OnPauseChild(Instance);
276 }
277
279 {
281
282 OnResumeChild(Instance);
283 }
284
286 {
288
289 try
290 {
291 OnErrorChild(Instance);
292 }
293 catch (const Util::Exception& e)
294 {
295 Util::EventLog().Log("Calling a module's error handler, the error listed below occurred.", Util::ErrorType::Error);
296 Util::EventLog().Log(e);
297 }
298 catch (const std::exception& e)
299 {
300 Util::EventLog().Log("Calling a module's error handler, the error listed below occurred.", Util::ErrorType::Error);
301 Util::EventLog().Log(e.what());
302 }
303 catch (...)
304 {
305 Util::EventLog().Log("Calling a module's error handler, an unknown error occurred.", Util::ErrorType::Error);
306 }
307 }
308
310 {
311 ModuleData->ModuleBaseOnly.Reset();
312 RegisteredEvents.clear();
313
315 }
316
327
329 {
330 GetModuleData()->ModuleBaseOnly.GetNewEventNotifier().Notify();
331 }
332
333 void ModuleBase::TerminateChild(const std::chrono::milliseconds Timeout)
334 {
335 try
336 {
339 }
340 catch (const Util::Exception& e)
341 {
342 // Exception occurring while trying to issue an OnExit event is swallowed and logged. It is tried to terminate
343 // the module anyway.
344 Util::EventLog().Log("A module has been terminated whithout cleaning up since the error reported below has occurred while issuing an exit event.",
346 Util::EventLog().Log(e);
347 }
348 }
349
350 std::unique_ptr<BusyDialog> ModuleBase::MakeStartupBusyDialogChild(QWidget* ParentWidget) const
351 {
352 auto StartupDialog = std::make_unique<BusyDialog>(ParentWidget);
353 StartupDialog->SetDescriptionText("Starting module's dependencies...");
354
355 return StartupDialog;
356 }
357
358 std::exception_ptr ModuleBase::GetExceptionChild(const std::chrono::milliseconds Timeout) const
359 {
360 using namespace std::chrono_literals;
361
362 // If ModuleData cannot be locked because it is continuously locked by main/module thread, dead lock
363 // is avoided since GetModuleData throws Util::TimeoutException after timeout in this case.
364 // Short timeout only since main thread should not block.
366 }
367
369 {
370 using namespace std::chrono_literals;
371 auto LockedModuleData = GetModuleData(ShortTimeoutDefault);
372
373 auto Exception = GetExceptionUnsafe(LockedModuleData);
374 Util::ForwardException(Exception);
375
376 return IsRunning() && !IsExiting();
377 }
378
380 {
381 // Copy vector since EventListenersBase::Deregister() removes entry from RegisteredEvents
382 // via call to ModuleBase::RemoveRegisteredEvent().
383 auto Events = RegisteredEvents;
384
385 for (auto Event : Events)
386 Event->Deregister(*this);
387 }
388
389 ModuleInstance::ModuleInstance(ModuleBase& Owner, std::promise<void>&& ThreadExitedPromise,
390 const ModuleBase::ModuleDataGetterType ModuleDataGetter)
391 : RunnableInstance(Owner, std::move(ThreadExitedPromise)),
392 ModuleDataGetter(ModuleDataGetter)
393 {
394 }
395
397 : RunnableInstance(std::move(Other)), ModuleDataGetter(Other.ModuleDataGetter)
398 {
399 }
400
404
406 {
407 return Qt::CustomizeWindowHint | Qt::WindowTitleHint |
408 Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint;
409 }
410
412 {
413 return Qt::CustomizeWindowHint | Qt::WindowTitleHint |
414 Qt::WindowCloseButtonHint;
415 }
416
418 : QWidget(Parent), Owner(Owner), DynExpMgr(nullptr),
419 DockWindowShortcut(new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_D), this)),
420 FocusMainWindowShortcut(new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_0), this))
421 {
422 connect(DockWindowShortcut, &QShortcut::activated, this, &QModuleWidget::OnDockWindow);
423 connect(FocusMainWindowShortcut, &QShortcut::activated, this, &QModuleWidget::OnFocusMainWindow);
424 }
425
426 Qt::WindowFlags QModuleWidget::GetQtWindowFlags() const noexcept
427 {
429 }
430
432 {
434 }
435
436 void QModuleWidget::SetDataSaveDirectory(std::string_view Directory) const
437 {
439 }
440
442 {
443 DockWindowShortcut->setEnabled(Enable);
444 }
445
446 void QModuleWidget::closeEvent(QCloseEvent* Event)
447 {
448 if (DynExpMgr)
449 if (QMessageBox::question(this, "DynExp - Stop module?",
450 QString::fromStdString("Do you want to stop this module?"),
451 QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, QMessageBox::StandardButton::No)
452 == QMessageBox::StandardButton::Yes)
453 if (DynExpMgr->StopItem(&Owner))
454 {
455 Event->accept();
456 return;
457 }
458
459 Event->ignore();
460 }
461
466
468 {
469 Owner.SetFocus();
470 }
471
476
477 QModuleDockWidget::QModuleDockWidget(QModuleBase& Owner, QWidget* Parent, Qt::WindowFlags Flags)
478 : QDockWidget(Parent, Flags), Owner(Owner)
479 {
480 }
481
482 void QModuleDockWidget::closeEvent(QCloseEvent* Event)
483 {
484 Event->ignore();
486 }
487
488 // Delegate Ctrl+1 - Ctrl+9 to main window
489 void QModuleDockWidget::keyPressEvent(QKeyEvent* Event)
490 {
491 if (Event->modifiers().testFlag(Qt::ControlModifier))
492 if (Event->key() >= Qt::Key_1 && Event->key() <= Qt::Key_1 + 8)
493 {
496
497 return;
498 }
499
500 QDockWidget::keyPressEvent(Event);
501 }
502
507
508 void WindowStyleParamsExtension::ApplyTo(QWidget& Widget, bool Show) const
509 {
511 Widget.showMinimized();
512 else
513 {
514 QPoint WindowPos(WindowPosX, WindowPosY);
515 QSize WindowSize(Util::NumToT<int>(WindowWidth.Get()), Util::NumToT<int>(WindowHeight.Get()));
516 if (!WindowSize.isEmpty())
517 {
518 Widget.move(WindowPos);
519 Widget.resize(WindowSize);
520 }
521
522 if (Show)
523 {
525 Widget.showMaximized();
526 else
527 Widget.showNormal();
528 }
529 }
530 }
531
532 void WindowStyleParamsExtension::FromWidget(const QWidget& Widget)
533 {
534 if (Widget.isMinimized())
536 else
537 {
539
540 auto WindowPos = Widget.pos();
541 auto WindowSize = Widget.size();
542 WindowPosX = WindowPos.x();
543 WindowPosY = WindowPos.y();
544 WindowWidth = WindowSize.width();
545 WindowHeight = WindowSize.height();
546 }
547 }
548
552
556
557 QModuleBase::QModuleBase(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType&& Params)
558 : ModuleBase(OwnerThreadID, std::move(Params)), Widget(nullptr), MdiArea(nullptr)
559 {
560 }
561
565
566 QAction& QModuleBase::InitUI(DynExpManager& DynExpMgr, QMdiArea* const MdiArea)
567 {
568 if (!MdiArea)
569 throw Util::InvalidArgException("MdiArea cannot be nullptr.");
570
571 // Make UI
572 auto WidgetPtr = MakeUIWidget();
573 if (!WidgetPtr)
574 throw Util::InvalidDataException("Overridden QModuleBase::MakeUIWidget() must not return nullptr.");
575 Widget = WidgetPtr.get();
576 Widget->DynExpMgr = &DynExpMgr;
577
578 // Initialize container widgets
579 this->MdiArea = MdiArea;
580 MdiSubWindow = std::make_unique<QMdiSubWindow>(); // Gets a parent when inserting into MdiArea
581 DockWidget = std::make_unique<QModuleDockWidget>(*this, nullptr, Widget->GetQtWindowFlags()); // nullptr parent to make it floating.
582 DockWidget->setAllowedAreas(Qt::DockWidgetArea::NoDockWidgetArea);
583 DockWidget->setFeatures(QDockWidget::DockWidgetFeature::DockWidgetClosable | QDockWidget::DockWidgetFeature::DockWidgetFloatable);
584 DockWidget->setLocale(QLocale(QLocale::Language::English, QLocale::Country::UnitedStates)); // For number format.
585
586 // Insert new Widget into main MDI area. MdiSubWindow becomes Widget's parent.
587 MdiSubWindow->setWidget(WidgetPtr.release());
588 MdiArea->addSubWindow(MdiSubWindow.get(), Widget->GetQtWindowFlags());
590
593
594 // Create action to push module's window into focus.
595 // Longer timeout while fetching object name since it could take longer if the entire project is started (empiric value).
596 ModuleWindowFocusAction = std::make_unique<QAction>(QString::fromStdString(GetObjectName(std::chrono::seconds(1))));
597 QObject::connect(ModuleWindowFocusAction.get(), &QAction::triggered, Widget, &QModuleWidget::OnFocusWindow);
598
599 MdiSubWindow->show();
600
602 }
603
605 {
606 // Widget is deleted by its respective parent's destructor.
607 MdiSubWindow.reset();
608 DockWidget.reset();
610 }
611
613 {
614 if (!Widget)
615 return;
616
617 Widget->setEnabled(false);
618 }
619
621 {
622 if (!Widget)
623 return;
624
625 Widget->setEnabled(true);
627 }
628
630 {
632 throw Util::InvalidStateException("UI widget has not been created yet.");
633
634 if (Widget->parent() != MdiSubWindow.get())
636 else
637 ModuleWindowFocusAction->setIcon(QIcon());
638 }
639
641 {
642 if (!Widget || !MdiArea || !MdiSubWindow || !DockWidget)
643 return;
644
645 DockWidget->hide();
646 MdiSubWindow->setWidget(Widget); // Sets Widget parent.
647 MdiArea->addSubWindow(MdiSubWindow.get(), Widget->GetQtWindowFlags());
648 MdiSubWindow->show();
650 }
651
653 {
654 if (!Widget || !MdiArea || !MdiSubWindow || !DockWidget)
655 return;
656
657 MdiArea->removeSubWindow(MdiSubWindow.get());
658 MdiSubWindow->setWidget(nullptr);
659 Widget->setParent(DockWidget.get());
660 DockWidget->setWidget(Widget);
661 DockWidget->showNormal();
663 }
664
666 {
667 if (!Widget || !MdiArea || !MdiSubWindow || !DockWidget)
668 return;
669
670 if (Widget->parent() == MdiSubWindow.get())
671 UndockWindow();
672 else
673 DockWindow();
674
675 SetFocus();
676 }
677
678 void QModuleBase::SetFocus() noexcept
679 {
680 if (!Widget || !MdiArea || !MdiSubWindow || !DockWidget)
681 return;
682
683 if (Widget->parent() != MdiSubWindow.get())
684 {
685 Widget->activateWindow();
686 Widget->raise();
687 }
688 else
689 {
691 MdiArea->setActiveSubWindow(MdiSubWindow.get());
692 }
693 }
694
696 {
697 if (!Widget)
698 return;
699
701 }
702
703 void QModuleBase::SendKeyPressEventToMainWindow(QKeyEvent* Event) noexcept
704 {
705 if (!Widget)
706 return;
707
708 Widget->DynExpMgr->PostKeyPressEvent(Event);
709 }
710
712 {
713 // Just because this is the default and we don't want to throw here.
714 if (!Widget || !MdiSubWindow)
715 return true;
716
717 return Widget->parent() == MdiSubWindow.get();
718 }
719
721 {
722 if (!Widget || !MdiSubWindow)
723 throw Util::InvalidStateException("UI widget has not been created yet.");
724
725 if (Widget->parent() != MdiSubWindow.get())
726 return false;
727
728 return MdiArea->currentSubWindow() == MdiSubWindow.get();
729 }
730
732 {
733 if (!Widget || !MdiArea || !MdiSubWindow || !DockWidget)
734 return;
735
736 auto ModuleParams = DynExp::dynamic_Params_cast<QModuleBase>(GetParams());
737 if (ModuleParams->WindowStyleParams.WindowDockingState == WindowStyleParamsExtension::WindowDockingStateType::Docked)
738 DockWindow();
739 else
740 UndockWindow();
741 ModuleParams->WindowStyleParams.ApplyTo(IsWindowDocked() ? static_cast<QWidget&>(*MdiSubWindow) : static_cast<QWidget&>(*DockWidget));
742 }
743
745 {
746 if (!Widget || !MdiArea || !MdiSubWindow || !DockWidget)
747 return;
748
749 auto ModuleParams = DynExp::dynamic_Params_cast<QModuleBase>(GetParams());
750 ModuleParams->WindowStyleParams.FromWidget(IsWindowDocked() ? static_cast<QWidget&>(*MdiSubWindow) : static_cast<QWidget&>(*DockWidget));
751 ModuleParams->WindowStyleParams.WindowDockingState = IsWindowDocked() ?
753 }
754
755 void QModuleBase::SetWidgetProperties(QWidget* const WindowWidget) const
756 {
757 if (!WindowWidget)
758 throw Util::InvalidArgException("WindowWidget cannot be nullptr.");
759
760 // Longer timeout while fetching object name since it could take longer if the entire project is started (empiric value).
761 WindowWidget->setWindowTitle(QString::fromStdString(GetObjectName(std::chrono::seconds(1))));
762 WindowWidget->setWindowIcon(QIcon(DynExpUI::Icons::Module));
763
764 if (!Widget->AllowResize())
765 WindowWidget->layout()->setSizeConstraint(QLayout::SetFixedSize);
766 }
767
772}
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:149
Common base class for all managers of event listeners of type TypedEventListeners....
Definition Module.h:866
virtual ~InterModuleEventBase()=0
Definition Module.cpp:401
Base class for modules. Modules implement programs on their own (e.g. measurement protocols or server...
Definition Module.h:392
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:333
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:202
virtual void OnErrorChild(ModuleInstance &Instance) const
This handler gets called just before the module thread terminates due to an exception....
Definition Module.h:673
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:271
void NotifyChild() override final
Notify derived classes that some state has changed (e.g. the termination of Thread is requested) and ...
Definition Module.cpp:328
void RunChild() override final
Refer to Run().
Definition Module.cpp:317
void OnDeregisterEvents(ModuleInstance *Instance) const
This event is triggered after the OnExit event. It calls EventListenersBase::Deregister() for all man...
Definition Module.cpp:379
static auto GetExceptionUnsafe(const ModuleDataTypeSyncPtrConstType &ModuleDataPtr)
Getter for ModuleDataBase::ModuleException assuming that the module data has already been locked.
Definition Module.h:610
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:719
const std::unique_ptr< ModuleDataType > ModuleData
Module data belonging to this ModuleBase instance.
Definition Module.h:743
virtual ~ModuleBase()=0
Definition Module.cpp:198
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:309
virtual void OnResumeChild(ModuleInstance &Instance) const
This handler gets called just after the module resumed from a paused state. Override OnResumeChild() ...
Definition Module.h:672
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:780
virtual void OnExit(ModuleInstance *Instance) const
This event is triggered right before the module thread terminates (not due to an exception,...
Definition Module.h:728
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:212
void RemoveRegisteredEvent(EventListenersBase &EventListeners)
Removes a manager of event listeners from RegisteredEvents if it was added before....
Definition Module.cpp:253
void HandleEvent(ModuleInstance &Instance)
Executes and removes the next pending event from the module's event queue.
Definition Module.cpp:222
ModuleBase(const std::thread::id OwnerThreadID, ParamsBasePtrType &&Params)
Constructs a ModuleBase instance.
Definition Module.cpp:189
Util::SynchronizedPointer< const ModuleDataType > ModuleDataTypeSyncPtrConstType
Alias for the return type of ModuleBase::GetModuleData() const. Data class instances wrapped into Uti...
Definition Module.h:462
void OnResume(ModuleInstance &Instance)
This handler gets called just after the module resumed from a paused state. Override OnResumeChild() ...
Definition Module.cpp:278
Util::SynchronizedPointer< ModuleDataType > ModuleDataTypeSyncPtrType
Alias for the return type of ModuleBase::GetModuleData(). Data class instances wrapped into Util::Syn...
Definition Module.h:456
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:350
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:750
void OnError(ModuleInstance &Instance)
This handler gets called just before the module thread terminates due to an exception....
Definition Module.cpp:285
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 if it was not already added before....
Definition Module.cpp:242
static constexpr auto GetModuleDataTimeoutDefault
Determines the default timeout for GetModuleData() to lock the mutex synchronizing the module's data ...
Definition Module.h:513
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:358
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:368
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:671
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:217
Util::DynExpErrorCodes::DynExpErrorCodes ExecModuleMainLoop(ModuleInstance &Instance)
Runs ModuleMainLoop().
Definition Module.cpp:264
virtual ~ModuleConfiguratorBase()=0
Definition Module.cpp:185
std::exception_ptr ModuleException
Used to transfer exceptions from the module thread to the main (user interface) thread....
Definition Module.h:330
Util::OneToOneNotifier NewEventNotifier
Notifies the thread of the module which owns the respective ModuleDataBase's instance when an event h...
Definition Module.h:323
std::queue< EventPtrType > EventQueueType
A module's event queue is a FIFO queue owning the enqueued events.
Definition Module.h:181
std::unique_ptr< EventBase > EventPtrType
Pointer owning an event.
Definition Module.h:176
void Reset()
Resets the ModuleDataBase's instance and calls ResetImpl(dispatch_tag<ModuleDataBase>) subsequently.
Definition Module.cpp:173
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:153
EventQueueType EventQueue
FIFO event queue of the module which owns the respective ModuleDataBase's instance.
Definition Module.h:316
virtual void ResetImpl(dispatch_tag< ModuleDataBase >)
Refer to DynExp::ModuleDataBase::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of ...
Definition Module.h:310
EventPtrType PopEvent()
Removes one event from the event queue's front and returns the event. Ownership of the event is trans...
Definition Module.cpp:162
Refer to ParamsBase::dispatch_tag.
Definition Module.h:189
Defines data for a thread belonging to a ModuleBase instance. Refer to RunnableInstance.
Definition Module.h:793
bool IsExiting() const noexcept
Getter for ShouldExit.
Definition Module.h:820
ModuleInstance(ModuleBase &Owner, std::promise< void > &&ThreadExitedPromise, const ModuleBase::ModuleDataGetterType ModuleDataGetter)
Constructs a non-empty RunnableInstance instance.
Definition Module.cpp:389
virtual ~ModuleParamsBase()=0
Definition Module.cpp:181
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:1344
void DockUndockWindow() noexcept
Toggles the docking state of Widget. Does nothing if any of Widget, MdiArea, MdiSubWindow,...
Definition Module.cpp:665
virtual ~QModuleBase()=0
Definition Module.cpp:562
virtual void UpdateParamsFromWindowStatesChild() override
UpdateParamsFromWindowStates() only calls UpdateParamsFromWindowStatesChild(). Override UpdateParamsF...
Definition Module.cpp:744
QModuleWidget * Widget
User interface widget belonging to the module.
Definition Module.h:1491
virtual void RestoreWindowStatesFromParamsChild() override
RestoreWindowStatesFromParams() only calls RestoreWindowStatesFromParamsChild(). Override RestoreWind...
Definition Module.cpp:731
bool IsActiveWindow()
Checks whether Widget is docked and active.
Definition Module.cpp:720
void FocusMainWindow() noexcept
Focuses/activates DynExp's main window calling DynExpManager::FocusMainWindow(). Does nothing if Widg...
Definition Module.cpp:695
void DisableUI()
Disables all user interface controls in Widget. Does nothing if Widget is nullptr.
Definition Module.cpp:612
bool IsWindowDocked() noexcept
Checks whether Widget is docked.
Definition Module.cpp:711
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:1488
QMdiArea * MdiArea
Pointer to DynExpManager's QMdiArea.
Definition Module.h:1496
void UndockWindow() noexcept
Undocks Widget from MdiArea. Does nothing if any of Widget, MdiArea, MdiSubWindow,...
Definition Module.cpp:652
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:755
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:1493
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:678
void HideUI()
Removes MdiSubWindow, DockWidget, and ModuleWindowFocusAction setting them to nullptr.
Definition Module.cpp:604
void SendKeyPressEventToMainWindow(QKeyEvent *Event) noexcept
Sends a Qt key press event to DynExp's main window calling DynExpManager::PostKeyPressEvent()....
Definition Module.cpp:703
void UpdateUI()
Enables the user interface controls in Widget. Does nothing if Widget is nullptr. Calls UpdateUIChild...
Definition Module.cpp:620
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:566
std::unique_ptr< QMdiSubWindow > MdiSubWindow
Frame for Widget when the module window is docked to MdiArea.
Definition Module.h:1492
QModuleBase(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
Constructs a QModuleBase instance.
Definition Module.cpp:557
void UpdateModuleWindowFocusAction()
Updates the icon assigned to ModuleWindowFocusAction depending on whether Widget is docked to or undo...
Definition Module.cpp:629
void DockWindow() noexcept
Docks Widget to MdiArea. Does nothing if any of Widget, MdiArea, MdiSubWindow, or DockWidget are null...
Definition Module.cpp:640
std::unique_ptr< QAction > ModuleWindowFocusAction
Qt action to push module window into focus. When triggered, QModuleWidget::OnFocusWindow() in invoked...
Definition Module.h:1494
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:768
void ResetImpl(dispatch_tag< ModuleDataBase >) override final
Refer to DynExp::ModuleDataBase::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of ...
Definition Module.cpp:503
QModuleBase & Owner
Module owning this user interface window.
Definition Module.h:1213
virtual void keyPressEvent(QKeyEvent *Event) override
Qt event indicating that keys were pressed when the QModuleDockWidget window was focused....
Definition Module.cpp:489
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:482
QModuleDockWidget(QModuleBase &Owner, QWidget *Parent, Qt::WindowFlags Flags)
Constructs a QModuleDockWidget instance.
Definition Module.cpp:477
virtual ~QModuleParamsBase()=0
Definition Module.cpp:549
void OnDockWindow()
Qt slot called when DockWindowShortcut is activated, calls QModuleBase::DockUndockWindow().
Definition Module.cpp:462
virtual bool AllowResize() const noexcept
Indicates the resizing behavior of the user interface window. Override to adjust.
Definition Module.h:1121
Qt::WindowFlags GetQtWindowFlags() const noexcept
Depending on thr return value of AllowResize(), returns either the return value of GetQtWindowFlagsRe...
Definition Module.cpp:426
void OnFocusWindow()
Qt slot called when QModuleBase::ModuleWindowFocusAction is triggered, calls QModuleBase::SetFocus().
Definition Module.cpp:467
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:446
QModuleBase & Owner
Module owning this user interface window (reference, because it should never change nor be nullptr).
Definition Module.h:1162
static constexpr Qt::WindowFlags GetQtWindowFlagsResizable()
Default Qt window flags for resizable module windows.
Definition Module.cpp:405
QModuleWidget(QModuleBase &Owner, QWidget *Parent=nullptr)
Constructs a QModuleWidget instance.
Definition Module.cpp:417
void OnFocusMainWindow()
Qt slot called when FocusMainWindowShortcut is activated, calls QModuleBase::FocusMainWindow().
Definition Module.cpp:472
static constexpr Qt::WindowFlags GetQtWindowFlagsNonResizable()
Default Qt window flags for non-resizable module windows.
Definition Module.cpp:411
QShortcut * FocusMainWindowShortcut
Shortcut (Ctrl + 0) to activate/focus DynExp's main window.
Definition Module.h:1166
std::string GetDataSaveDirectory() const
Recalls a path where modules might save recorded data to. Used by Util::PromptSaveFilePathModule() to...
Definition Module.cpp:431
QShortcut * DockWindowShortcut
Shortcut (Ctrl + D) to dock/undock a module window to/from DynExp's main window.
Definition Module.h:1165
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:436
void EnableDockWindowShortcut(bool Enable) noexcept
Enables/disables DockWindowShortcut.
Definition Module.cpp:441
DynExpManager * DynExpMgr
DynExp's main window (pointer, because it is set later by QModuleBase::InitUI()).
Definition Module.h:1163
Defines data for a thread belonging to a RunnableObject instance. This data is only accessed by the R...
Definition Object.h:3505
std::string GetNotReadyObjectNamesString() const
Finds all linked Object instances Owner makes use of which are not in a ready state and builds a stri...
Definition Object.cpp:815
bool CareAboutWrappers()
Unregisters owned LinkedObjectWrapper instances from their destiny resources in case of the respectiv...
Definition Object.cpp:776
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
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
ParamsBase::Param< unsigned int > WindowWidth
Window width.
Definition Module.h:1296
ParamsBase::Param< int > WindowPosY
Window y coordinate.
Definition Module.h:1295
ParamsBase::Param< int > WindowPosX
Window x coordinate.
Definition Module.h:1294
ParamsBase::Param< WindowStateType > WindowState
Window show state.
Definition Module.h:1298
void FromWidget(const QWidget &Widget)
Assigns styles applied to Widget to the bundled parameters.
Definition Module.cpp:532
void ApplyTo(QWidget &Widget, bool Show=true) const
Applies the bundled style parameters to Widget.
Definition Module.cpp:508
ParamsBase::Param< unsigned int > WindowHeight
Window height.
Definition Module.h:1297
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
Data to operate on is invalid for a specific purpose. This indicates a corrupted data structure or fu...
Definition Exception.h:163
Thrown when RunnableInstance cannot lock an object to be used by another object due to an invalid lin...
Definition Exception.h:344
An operation cannot be performed currently since the related object is in an invalid state like an er...
Definition Exception.h:150
Thrown when RunnableInstance::LockObject() has not been called on an object link parameter to establi...
Definition Exception.h:329
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 (...
std::unique_ptr< ParamsBase > ParamsBasePtrType
Alias for a pointer to the parameter system base class ParamsBase.
Definition Object.h:1807
int ModuleThreadMain(ModuleInstance Instance, ModuleBase *const Module)
Modules run in their own thread. This is the module thread's main function.
Definition Module.cpp:10
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:509
Accumulates include statements to provide a precompiled header.