4 #include "moc_Module.cpp"
12 bool IsExiting =
false;
13 std::chrono::time_point<std::chrono::system_clock> LastMainLoopExecution;
20 unsigned int NumSubsequentExceptions = 0;
21 constexpr
unsigned int MaxAllowedSubsequentExceptions = 10;
23 auto& NewEventNotifier =
Module->GetModuleData()->ModuleThreadOnly.GetNewEventNotifier();
38 Module->ModuleThreadOnly.OnPause(Instance);
44 std::this_thread::sleep_for(std::chrono::milliseconds(100));
47 else if (
Module->IsPaused())
50 Module->ModuleThreadOnly.OnResume(Instance);
54 while (
Module->GetModuleData()->GetNumEnqueuedEvents())
55 Module->ModuleThreadOnly.HandleEvent(Instance);
59 auto MainLoopDelay =
Module->GetMainLoopDelay();
60 auto Now = std::chrono::system_clock::now();
62 if (Now - LastMainLoopExecution >= MainLoopDelay || MainLoopDelay == decltype(MainLoopDelay)::max())
64 ReturnCode =
Module->ModuleThreadOnly.ModuleMainLoop(Instance);
69 LastMainLoopExecution = Now;
72 if (MainLoopDelay == decltype(MainLoopDelay)::max())
73 NewEventNotifier.Wait();
74 else if (MainLoopDelay.count() == 0)
75 std::this_thread::yield();
77 NewEventNotifier.Wait(MainLoopDelay);
80 NumSubsequentExceptions = 0;
94 ++NumSubsequentExceptions;
96 if (
Module->TreatModuleExceptionsAsWarnings() && NumSubsequentExceptions < MaxAllowedSubsequentExceptions)
101 catch (
const std::exception& e)
103 ++NumSubsequentExceptions;
105 if (
Module->TreatModuleExceptionsAsWarnings() && NumSubsequentExceptions < MaxAllowedSubsequentExceptions)
120 Module->GetModuleData()->ModuleThreadOnly.SetException(std::current_exception());
121 Module->ModuleThreadOnly.OnError(Instance);
125 catch (
const std::exception& e)
130 Module->GetModuleData()->ModuleThreadOnly.SetException(std::current_exception());
131 Module->ModuleThreadOnly.OnError(Instance);
140 Module->GetModuleData()->ModuleThreadOnly.SetException(std::current_exception());
141 Module->ModuleThreadOnly.OnError(Instance);
191 ModuleThreadOnly(*this), EventListenersOnly(*this),
232 if (!ModuleDataPtr->GetNumEnqueuedEvents())
235 EventPtr = ModuleDataPtr->PopEvent();
239 EventPtr->Invoke(Instance);
298 catch (
const std::exception& e)
330 GetModuleData()->ModuleBaseOnly.GetNewEventNotifier().Notify();
344 Util::EventLog().
Log(
"A module has been terminated whithout cleaning up since the error reported below has occurred while issuing an exit event.",
352 auto StartupDialog = std::make_unique<BusyDialog>(ParentWidget);
353 StartupDialog->SetDescriptionText(
"Starting module's dependencies...");
355 return StartupDialog;
360 using namespace std::chrono_literals;
370 using namespace std::chrono_literals;
385 for (
auto Event : Events)
386 Event->Deregister(*
this);
392 ModuleDataGetter(ModuleDataGetter)
397 :
RunnableInstance(std::move(Other)), ModuleDataGetter(Other.ModuleDataGetter)
407 return Qt::CustomizeWindowHint | Qt::WindowTitleHint |
408 Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint;
413 return Qt::CustomizeWindowHint | Qt::WindowTitleHint |
414 Qt::WindowCloseButtonHint;
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))
443 DockWindowShortcut->setEnabled(Enable);
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)
478 : QDockWidget(Parent, Flags), Owner(Owner)
491 if (Event->modifiers().testFlag(Qt::ControlModifier))
492 if (Event->key() >= Qt::Key_1 && Event->key() <= Qt::Key_1 + 8)
500 QDockWidget::keyPressEvent(Event);
511 Widget.showMinimized();
516 if (!WindowSize.isEmpty())
518 Widget.move(WindowPos);
519 Widget.resize(WindowSize);
525 Widget.showMaximized();
534 if (Widget.isMinimized())
538 WindowState = Widget.isMaximized() ? WindowStateType::Maximized : WindowStateType::Normal;
540 auto WindowPos = Widget.pos();
541 auto WindowSize = Widget.size();
558 :
ModuleBase(OwnerThreadID, std::move(Params)), Widget(nullptr), MdiArea(nullptr)
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));
617 Widget->setEnabled(
false);
708 Widget->DynExpMgr->PostKeyPressEvent(Event);
736 auto ModuleParams = DynExp::dynamic_Params_cast<QModuleBase>(
GetParams());
737 if (ModuleParams->WindowStyleParams.WindowDockingState == WindowStyleParamsExtension::WindowDockingStateType::Docked)
749 auto ModuleParams = DynExp::dynamic_Params_cast<QModuleBase>(
GetParams());
751 ModuleParams->WindowStyleParams.WindowDockingState =
IsWindowDocked() ?
752 WindowStyleParamsExtension::WindowDockingStateType::Docked : WindowStyleParamsExtension::WindowDockingStateType::Undocked;
765 WindowWidget->layout()->setSizeConstraint(QLayout::SetFixedSize);
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.
Common base class for all managers of event listeners of type TypedEventListeners....
virtual ~InterModuleEventBase()=0
Base class for modules. Modules implement programs on their own (e.g. measurement protocols or server...
void TerminateChild(const std::chrono::milliseconds Timeout) override final
Signals derived classes that terminating the RunnableObject instance's thread is about to be requeste...
ModuleDataTypeSyncPtrType GetModuleData(const std::chrono::milliseconds Timeout=GetModuleDataTimeoutDefault)
Locks the mutex of the module data class instance ModuleData assigned to this ModuleBase instance and...
virtual void OnErrorChild(ModuleInstance &Instance) const
This handler gets called just before the module thread terminates due to an exception....
void OnPause(ModuleInstance &Instance)
This handler gets called just after the module pauses due to e.g. an error in an instrument the modul...
void NotifyChild() override final
Notify derived classes that some state has changed (e.g. the termination of Thread is requested) and ...
void RunChild() override final
Refer to Run().
void OnDeregisterEvents(ModuleInstance *Instance) const
This event is triggered after the OnExit event. It calls EventListenersBase::Deregister() for all man...
static auto GetExceptionUnsafe(const ModuleDataTypeSyncPtrConstType &ModuleDataPtr)
Getter for ModuleDataBase::ModuleException assuming that the module data has already been locked.
virtual void OnInit(ModuleInstance *Instance) const
This event is triggered right before the module thread starts. Override it to lock instruments this m...
const std::unique_ptr< ModuleDataType > ModuleData
Module data belonging to this ModuleBase instance.
void ResetImpl(dispatch_tag< RunnableObject >) override final
Refer to DynExp::Object::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of every de...
virtual void OnResumeChild(ModuleInstance &Instance) const
This handler gets called just after the module resumed from a paused state. Override OnResumeChild() ...
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...
virtual void OnExit(ModuleInstance *Instance) const
This event is triggered right before the module thread terminates (not due to an exception,...
void EnqueueEvent(ModuleDataBase::EventPtrType &&Event) const
Enqueues Event at the module event queue's back. Takes ownership of the event. Notifies the module ow...
void RemoveRegisteredEvent(EventListenersBase &EventListeners)
Removes a manager of event listeners from RegisteredEvents if it was added before....
void HandleEvent(ModuleInstance &Instance)
Executes and removes the next pending event from the module's event queue.
ModuleBase(const std::thread::id OwnerThreadID, ParamsBasePtrType &&Params)
Constructs a ModuleBase instance.
Util::SynchronizedPointer< const ModuleDataType > ModuleDataTypeSyncPtrConstType
Alias for the return type of ModuleBase::GetModuleData() const. Data class instances wrapped into Uti...
void OnResume(ModuleInstance &Instance)
This handler gets called just after the module resumed from a paused state. Override OnResumeChild() ...
Util::SynchronizedPointer< ModuleDataType > ModuleDataTypeSyncPtrType
Alias for the return type of ModuleBase::GetModuleData(). Data class instances wrapped into Util::Syn...
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().
std::vector< EventListenersBase * > RegisteredEvents
Holds a list of pointers to managers of event listeners of the events this module has registered/subs...
void OnError(ModuleInstance &Instance)
This handler gets called just before the module thread terminates due to an exception....
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....
std::exception_ptr GetExceptionChild([[maybe_unused]] const std::chrono::milliseconds Timeout) const override final
static constexpr auto GetModuleDataTimeoutDefault
Determines the default timeout for GetModuleData() to lock the mutex synchronizing the module's data ...
bool IsReadyChild() const override final
Returns wheter this Object instance is ready (e.g. it is running or connected to a hardware device) a...
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...
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...
Util::DynExpErrorCodes::DynExpErrorCodes ExecModuleMainLoop(ModuleInstance &Instance)
Runs ModuleMainLoop().
virtual ~ModuleConfiguratorBase()=0
std::exception_ptr ModuleException
Used to transfer exceptions from the module thread to the main (user interface) thread....
Util::OneToOneNotifier NewEventNotifier
Notifies the thread of the module which owns the respective ModuleDataBase's instance when an event h...
std::queue< EventPtrType > EventQueueType
A module's event queue is a FIFO queue owning the enqueued events.
std::unique_ptr< EventBase > EventPtrType
Pointer owning an event.
void Reset()
Resets the ModuleDataBase's instance and calls ResetImpl(dispatch_tag<ModuleDataBase>) subsequently.
void EnqueueEvent(EventPtrType &&Event)
Enqueues Event at the module event queue's back. Takes ownership of the event. Notifies the module ow...
EventQueueType EventQueue
FIFO event queue of the module which owns the respective ModuleDataBase's instance.
virtual void ResetImpl(dispatch_tag< ModuleDataBase >)
Refer to DynExp::ModuleDataBase::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of ...
EventPtrType PopEvent()
Removes one event from the event queue's front and returns the event. Ownership of the event is trans...
Refer to ParamsBase::dispatch_tag.
Defines data for a thread belonging to a ModuleBase instance. Refer to RunnableInstance.
bool IsExiting() const noexcept
Getter for ShouldExit.
ModuleInstance(ModuleBase &Owner, std::promise< void > &&ThreadExitedPromise, const ModuleBase::ModuleDataGetterType ModuleDataGetter)
Constructs a non-empty RunnableInstance instance.
virtual ~ModuleParamsBase()=0
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...
auto GetObjectName(const std::chrono::milliseconds Timeout=GetParamsTimeoutDefault) const
Returns the name of this Object instance.
Refer to ParamsBase::dispatch_tag.
Base class for modules with a Qt-based user interface. Derive from this class to implement modules wi...
void DockUndockWindow() noexcept
Toggles the docking state of Widget. Does nothing if any of Widget, MdiArea, MdiSubWindow,...
virtual void UpdateParamsFromWindowStatesChild() override
UpdateParamsFromWindowStates() only calls UpdateParamsFromWindowStatesChild(). Override UpdateParamsF...
QModuleWidget * Widget
User interface widget belonging to the module.
virtual void RestoreWindowStatesFromParamsChild() override
RestoreWindowStatesFromParams() only calls RestoreWindowStatesFromParamsChild(). Override RestoreWind...
bool IsActiveWindow()
Checks whether Widget is docked and active.
void FocusMainWindow() noexcept
Focuses/activates DynExp's main window calling DynExpManager::FocusMainWindow(). Does nothing if Widg...
void DisableUI()
Disables all user interface controls in Widget. Does nothing if Widget is nullptr.
bool IsWindowDocked() noexcept
Checks whether Widget is docked.
virtual void UpdateUIChild(const ModuleBase::ModuleDataGetterType &ModuleDataGetter)
Use this function to update the module's user interface widget according to the module data obtained ...
QMdiArea * MdiArea
Pointer to DynExpManager's QMdiArea.
void UndockWindow() noexcept
Undocks Widget from MdiArea. Does nothing if any of Widget, MdiArea, MdiSubWindow,...
void SetWidgetProperties(QWidget *const WindowWidget) const
Used by InitUI() to set the widget properties (such as title, icon, size constraints) of MdiSubWindow...
std::unique_ptr< QModuleDockWidget > DockWidget
Frame for Widget when the module window is undocked from MdiArea.
void SetFocus() noexcept
Focuses/activates Widget and moves it on top of other windows if possible. Does nothing if any of Wid...
void HideUI()
Removes MdiSubWindow, DockWidget, and ModuleWindowFocusAction setting them to nullptr.
void SendKeyPressEventToMainWindow(QKeyEvent *Event) noexcept
Sends a Qt key press event to DynExp's main window calling DynExpManager::PostKeyPressEvent()....
void UpdateUI()
Enables the user interface controls in Widget. Does nothing if Widget is nullptr. Calls UpdateUIChild...
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...
std::unique_ptr< QMdiSubWindow > MdiSubWindow
Frame for Widget when the module window is docked to MdiArea.
QModuleBase(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
Constructs a QModuleBase instance.
void UpdateModuleWindowFocusAction()
Updates the icon assigned to ModuleWindowFocusAction depending on whether Widget is docked to or undo...
void DockWindow() noexcept
Docks Widget to MdiArea. Does nothing if any of Widget, MdiArea, MdiSubWindow, or DockWidget are null...
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< QAction > ModuleWindowFocusAction
Qt action to push module window into focus. When triggered, QModuleWidget::OnFocusWindow() in invoked...
void ResetImpl(dispatch_tag< ModuleBase >) override final
Refer to DynExp::Object::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of every de...
virtual ~QModuleConfiguratorBase()=0
void ResetImpl(dispatch_tag< ModuleDataBase >) override final
Refer to DynExp::ModuleDataBase::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of ...
virtual ~QModuleParamsBase()=0
Defines data for a thread belonging to a RunnableObject instance. This data is only accessed by the R...
std::string GetNotReadyObjectNamesString() const
Finds all linked Object instances Owner makes use of which are not in a ready state and builds a stri...
bool CareAboutWrappers()
Unregisters owned LinkedObjectWrapper instances from their destiny resources in case of the respectiv...
Defines an Object which possesses a thread it runs in. The RunnableObject can be started and stopped ...
std::promise< void > MakeThreadExitedPromise()
Helper function to be used by overridden RunChild() functions in derived classes to (re)initialize th...
static constexpr auto ShortTimeoutDefault
Default timeout e.g. used as a default for calls to InstrumentBase::GetInstrumentData or ModuleBase::...
bool IsExiting() const noexcept
Returns ShouldExit.
void StoreThread(std::thread &&Thread) noexcept
Stores a thread constructed by a derived class overriding RunChild() in Thread taking ownership of th...
void EnsureCallFromRunnableThread() const
Asserts that the call to this function is performed from the RunnableObject instance's thread by call...
bool IsRunning() const noexcept
Returns Running.
ParamsBase::Param< unsigned int > WindowWidth
Window width.
ParamsBase::Param< int > WindowPosY
Window y coordinate.
ParamsBase::Param< int > WindowPosX
Window x coordinate.
ParamsBase::Param< WindowStateType > WindowState
Window show state.
void FromWidget(const QWidget &Widget)
Assigns styles applied to Widget to the bundled parameters.
void ApplyTo(QWidget &Widget, bool Show=true) const
Applies the bundled style parameters to Widget.
ParamsBase::Param< unsigned int > WindowHeight
Window height.
Wraps a member function of some object and stores its default arguments. Moving from CallableMemberWr...
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.
DynExp exceptions are derived from this class. It contains basic information about the cause of the e...
const int ErrorCode
DynExp error code from DynExpErrorCodes::DynExpErrorCodes
An invalid argument like a null pointer has been passed to a function.
Data to operate on is invalid for a specific purpose. This indicates a corrupted data structure or fu...
Thrown when RunnableInstance cannot lock an object to be used by another object due to an invalid lin...
An operation cannot be performed currently since the related object is in an invalid state like an er...
Thrown when RunnableInstance::LockObject() has not been called on an object link parameter to establi...
void Notify()
Set notification to stop waiting (sets EventOccurred to true).
Pointer to lock a class derived from ISynchronizedPointerLockable for synchronizing between threads....
constexpr auto UndockedWindow
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.
std::unique_ptr< ParamsBase > ParamsBasePtrType
Alias for a pointer to the parameter system base class ParamsBase.
int ModuleThreadMain(ModuleInstance Instance, ModuleBase *const Module)
Modules run in their own thread. This is the module thread's main function.
DynExpErrorCodes
DynExp's error codes
void ForwardException(std::exception_ptr e)
Wraps the exception passed to the function in a ForwardedException and throws the ForwardedException....
EventLogger & EventLog()
This function holds a static EventLogger instance and returns a reference to it. DynExp uses only one...
std::chrono::duration< double > seconds
Extends std::chrono by a duration data type for seconds capable of storing fractions of seconds.
Accumulates include statements to provide a precompiled header.