DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
Object.cpp
Go to the documentation of this file.
1// This file is part of DynExp.
2
3#include "stdafx.h"
4#include "Object.h"
5#include "DynExpCore.h"
6
7namespace DynExp
8{
9 Util::ILockable::LockType ObjectUserList::AcquireLock(const std::chrono::milliseconds Timeout) const
10 {
11 return ILockable::AcquireLock(Timeout);
12 }
13
14 void ObjectUserList::Register(const Object& User, const std::chrono::milliseconds Timeout)
15 {
16 auto lock = AcquireLock(Timeout);
17
18 RegisterUnsafe(User);
19 }
20
22 {
23 RegisterUnsafe(User);
24
25 return std::move(Lock);
26 }
27
28 void ObjectUserList::Deregister(const Object& User, const std::chrono::milliseconds Timeout)
29 {
30 auto lock = AcquireLock(Timeout);
31
32 DeregisterUnsafe(User);
33 }
34
35 size_t ObjectUserList::CountUsers(const std::chrono::milliseconds Timeout) const
36 {
37 auto lock = AcquireLock(Timeout);
38
39 return CountUsersUnsafe();
40 }
41
42 ItemIDListType ObjectUserList::GetUserIDs(std::chrono::milliseconds Timeout) const
43 {
44 auto lock = AcquireLock(Timeout);
45
46 return GetUserIDsUnsafe();
47 }
48
49 std::string ObjectUserList::GetUserNamesString(const std::chrono::milliseconds Timeout) const
50 {
51 auto lock = AcquireLock(Timeout);
52
54 }
55
57 {
58 for (auto& User : UserList)
59 User.first->CheckLinkedObjectStates();
60
61 UserList.clear();
62 }
63
65 {
66 return std::accumulate<decltype(UserList.cbegin()), size_t>(UserList.cbegin(), UserList.cend(),
67 0, [](size_t CurrentValue, const auto& User) {
68 return CurrentValue + User.second;
69 });
70 }
71
73 {
75
76 for (const auto& User : UserList)
77 IDs.push_back(User.first->GetID());
78
79 return IDs;
80 }
81
83 {
84 std::string Names("Items making use of this item:");
85 for (const auto& User : UserList)
86 Names += "\n- " + User.first->GetObjectName() + " (" + User.first->GetCategoryAndName() + ")";
87
88 return Names;
89 }
90
92 {
93 auto& Value = UserList[&User];
94
95 if (Value == std::numeric_limits<std::remove_reference_t<decltype(Value)>>::max())
96 throw Util::OverflowException("Cannot increment the user list counter since an overflow would occur.");
97
98 ++Value;
99 }
100
102 {
103 auto ValueIt = UserList.find(&User);
104 if (ValueIt == UserList.cend())
105 return;
106
107 if (ValueIt->second == 0)
108 throw Util::UnderflowException("Cannot decrement the user list counter since an underflow would occur.");
109 if (--ValueIt->second == 0)
110 UserList.erase(ValueIt);
111 }
112
114 std::string ParamName, std::string_view ParamTitle, std::string_view ParamDescription, bool NeedsResetToApplyChange)
115 : ParamsBaseOnly(*this), Owner(Owner), UserEditable(true),
116 ParamName(ParamName), ParamTitle(ParamTitle), ParamDescription(ParamDescription), NeedsResetToApplyChange(NeedsResetToApplyChange)
117 {
118 // Since classes derived from ParamBase are declared within the scope of class ParamsBase, this is allowed.
119 // This is safe since OwnedParams is declared before any member derived from ParamBase within the inheritance hierarchy.
120 // Intended call to a virtual function (Owner.GetParamClassTag()) during construction of ParamsBase. See declaration of
121 // ParamsBase::GetParamClassTag().
122 Owner.OwnedParams.emplace_back(Owner.GetParamClassTag(), std::ref(*this));
123 }
124
125 ParamsBase::ParamBase::ParamBase(ParamsBase& Owner, std::string ParamName)
126 : ParamsBaseOnly(*this), Owner(Owner), UserEditable(false),
127 ParamName(ParamName), NeedsResetToApplyChange(false)
128 {
129 // See above.
130 Owner.OwnedParams.emplace_back(Owner.GetParamClassTag(), std::ref(*this));
131 }
132
136
137 QDomElement ParamsBase::ParamBase::ToXMLNode(QDomDocument& Document) const
138 {
139 QDomElement Node = Document.createElement(GetParamName().data());
140 ToXMLNodeChild(Document, Node);
141
142 return Node;
143 }
144
145 void ParamsBase::ParamBase::FromXMLNode(const QDomElement& XMLElement)
146 {
147 try
148 {
149 FromXMLNodeChild(XMLElement);
150 }
151 catch ([[maybe_unused]] const Util::NotFoundException& e)
152 {
153 Reset();
154
155 Util::EventLog().Log("Parameter \"" + std::string(GetParamName()) + "\" has not been found in configuration file. Assuming default value.",
157 }
158 catch (...)
159 {
160 throw;
161 }
162 }
163
165 {
166 bool IsValid = ValidateChild();
167
168 if (!IsValid)
169 {
170 Reset();
171
172 Util::EventLog().Log("Parameter \"" + std::string(GetParamName()) + "\" has been reset to its default value since it was invalid.",
174 }
175
176 return IsValid;
177 }
178
180 {
181 if (CurrentParam == Params.ObjectLinkParams.cend())
182 return true;
183
184 if (!EnsureReadyStateCalledForCurrentParam)
185 {
186 CurrentParam->get().EnsureReadyState();
187 EnsureReadyStateCalledForCurrentParam = true;
188 }
189 else if (CurrentParam->get().IsReady())
190 {
191 ++CurrentParam;
192 EnsureReadyStateCalledForCurrentParam = false;
193 }
194
195 return false;
196 }
197
201
202 QDomElement ParamsBase::ConfigToXML(QDomDocument& Document) const
203 {
204 QDomElement MainNode = Document.createElement(ParamsBase::GetParamClassTag());
205 QDomElement CurrentNode = MainNode; // shallow copy
206
207 for (const auto& OwnedParam : OwnedParams)
208 {
209 if (CurrentNode.tagName() != OwnedParam.ClassTag)
210 {
211 QDomElement SubNode = Document.createElement(OwnedParam.ClassTag);
212 CurrentNode = CurrentNode.appendChild(SubNode).toElement();
213 }
214
215 if (!OwnedParam.OwnedParam.get().GetParamName().empty())
216 CurrentNode.appendChild(OwnedParam.OwnedParam.get().ToXMLNode(Document));
217 }
218
219 return MainNode;
220 }
221
222 void ParamsBase::ConfigFromXML(const QDomElement& XMLElement) const
223 {
224 QDomElement CurrentNode = Util::GetSingleChildDOMElement(XMLElement, ParamsBase::GetParamClassTag());
225
226 for (const auto& OwnedParam : OwnedParams)
227 {
228 try
229 {
230 if (CurrentNode.tagName() != OwnedParam.ClassTag)
231 CurrentNode = Util::GetSingleChildDOMElement(CurrentNode, OwnedParam.ClassTag);
232 }
233 catch ([[maybe_unused]] const Util::NotFoundException& e)
234 {
235 std::string MissingParamName(OwnedParam.OwnedParam.get().GetParamName());
236 Util::EventLog().Log("Node \"" + std::string(OwnedParam.ClassTag) +
237 "\" has not been found in configuration file." +
238 (MissingParamName.empty() ? "" :
239 (" Assuming default value for parameter \"" + MissingParamName + "\".")),
241
242 // Assume default values if hierarchy levels in the XML structure are missing.
243 // Params classes without any parameters do get reflected in the XML hierarchy.
244 OwnedParam.OwnedParam.get().Reset();
245
246 continue;
247 }
248 catch (...)
249 {
250 throw;
251 }
252
253 if (!OwnedParam.OwnedParam.get().GetParamName().empty())
254 OwnedParam.OwnedParam.get().FromXMLNode(CurrentNode);
255 }
256
257 Validate();
258 }
259
261 {
263
264 for (const auto& OwnedParam : OwnedParams)
265 if (OwnedParam.OwnedParam.get().IsUserEditable())
266 OwnedParam.OwnedParam.get().ParamsBaseOnly.AddToDialog(Dialog);
267
268 Validate();
269 }
270
272 {
273 bool AllValid = true;
274
275 std::for_each(OwnedParams.cbegin(), OwnedParams.cend(), [&AllValid](auto OwnedParams) {
276 AllValid &= OwnedParams.OwnedParam.get().Validate();
277 });
278
279 return AllValid;
280 }
281
283 {
285 { "Allow usage by only a single other item", UsageType::Unique },
286 { "Allow usage by multiple other items", UsageType::Shared }
287 };
288
289 return List;
290 }
291
293 {
294 Param.ParamsBaseOnly.DisableUserEditable();
295 }
296
304
305 std::filesystem::path ParamsBase::ToAbsolutePath(const std::filesystem::path& Path) const
306 {
307 return GetCore().ToAbsolutePath(Path);
308 }
309
313
315 {
316 auto Params = MakeParams(ID, Core);
317 auto ConfigDlg = std::make_unique<ParamsConfigDialog>(DialogParent, Core, std::string("New ") + Params->ObjectName.Get());
318
319 Params->ConfigFromDialog(*ConfigDlg);
320
321 return ConfigDlg->Display() ? std::move(Params) : nullptr;
322 }
323
325 {
326 auto Params = MakeParams(ID, Core);
327
328 Params->ConfigFromXML(XMLElement);
329
330 return Params;
331 }
332
334 QWidget* const DialogParent) const
335 {
336 std::unique_ptr<ParamsConfigDialog> ConfigDlg;
337
338 {
339 auto ParamsPtr = Obj->GetParams();
340 ConfigDlg = std::make_unique<ParamsConfigDialog>(DialogParent, Core, std::string("Edit ") + ParamsPtr->ObjectName.Get());
341
342 ParamsPtr->ConfigFromDialog(*ConfigDlg);
343 } // Params unlocked here. ParamsConfigDialog::accept() locks itself again when user has accepted.
344
345 auto Accepted = ConfigDlg->Display(Obj);
346
347 return { Accepted, ConfigDlg->IsResetRequired() };
348 }
349
350 std::string Object::CategoryAndNameToStr(const std::string& Category, const std::string& Name)
351 {
352 if (Category.empty())
353 return Name;
354 else
355 return Category + " -> " + Name;
356 }
357
358 Object::Object(const std::thread::id OwnerThreadID, ParamsBasePtrType&& Params)
359 : LinkedObjectWrapperOnly(*this), OwnerThreadID(OwnerThreadID), Params(std::move(Params))
360 {
361 if (OwnerThreadID == std::thread::id())
362 throw Util::InvalidArgException("OwnerThreadID is not a valid thread identifier.");
363
364 if (!this->Params)
365 throw Util::InvalidArgException("Params cannot be nullptr.");
366 }
367
369 {
370#ifdef DYNEXP_DEBUG
371 Util::EventLog().Log("Item \"" + GetObjectName() + "\" is being removed.");
372#endif // DYNEXP_DEBUG
373 }
374
375 void Object::LinkedObjectWrapperOnlyType::RegisterUser(const Object& User, const std::chrono::milliseconds Timeout) const
376 {
377 // Longer timeout in case a module is started which itself starts an instrument (empiric value...)
378 // since the instrument might have locked its Params while starting up.
379 // If longer timeout is not allowed, this might throw Util::TimeoutException.
380 auto IsSharedUsage = Parent.IsSharedUsageEnabled(std::chrono::milliseconds(1000));
381
382 // Now, race condition between Object::IsReady() and Object::BlockIfUnused() is avoided.
383 auto lock = Parent.UserList.AcquireLock(Timeout);
384
385 // Just a check for the moment, no guarantee, that the required object stays in a healthy state...
386 if (!Parent.IsReady())
387 throw Util::InvalidStateException("The required item is in an invalid state or in an error state.");
388
389 if (!IsSharedUsage && !Parent.IsUnusedUnsafe())
391 "According to the item's \"Usage type\" setting, it can only be used by a single other item. Since it is already in use, it cannot be used by another item."
392 + std::string("\n\n") + Parent.UserList.GetUserNamesStringUnsafe(),
394
395 Parent.UserList.Register(User, std::move(lock));
396 }
397
398 void Object::LinkedObjectWrapperOnlyType::DeregisterUser(const Object& User, const std::chrono::milliseconds Timeout) const
399 {
400 Parent.UserList.Deregister(User, Timeout);
401 }
402
404 {
406
407 // Now, objects trying to make use of this object cannot register themselves here anymore.
408 // They have to wait until reset is done.
409 auto lock = UserList.AcquireLock();
410
411 if (!IsUnusedUnsafe())
413 "This item is currently being used by at least another item. Stop and reset these items before resetting this item."
414 + std::string("\n\n") + UserList.GetUserNamesStringUnsafe());
415
416 ClearWarning();
417
419 }
420
421 void Object::BlockIfUnused(const std::chrono::milliseconds Timeout)
422 {
424
425 // Now, race condition between Object::IsReady() and Object::BlockIfUnused() is avoided.
426 auto lock = UserList.AcquireLock(Timeout);
427
428 if (!IsUnusedUnsafe())
430 "This item is currently being used by at least another item. Stop and reset these items before deleting this item."
431 + std::string("\n\n") + UserList.GetUserNamesStringUnsafe());
432
433 IsBlocked = true;
434 }
435
436 Object::ParamsConstTypeSyncPtrType Object::GetParams(const std::chrono::milliseconds Timeout) const
437 {
438 return ParamsConstTypeSyncPtrType(Params.get(), Timeout);
439 }
440
441 Object::ParamsTypeSyncPtrType Object::GetParams(const std::chrono::milliseconds Timeout)
442 {
443 return ParamsTypeSyncPtrType(Params.get(), Timeout);
444 }
445
446 void Object::EnsureReadyState(bool IsAutomaticStartup)
447 {
448 // EnsureCallFromOwningThread(); does not work here because hardware adapters are connected asynchronously
449 // from another thread in DynExpManager::OnRunProject().
450
451 EnsureReadyStateChild(IsAutomaticStartup);
452 }
453
454 void Object::SetWarning(std::string Description, int ErrorCode) const
455 {
456 Warning = Util::Warning(std::move(Description), ErrorCode);
457
458 LogWarning();
459 }
460
462 {
463 Warning = e;
464
465 LogWarning();
466 }
467
469 {
470 if (std::this_thread::get_id() != OwnerThreadID)
472 "This function must be called from the thread managing this object. A call from another instrument or module thread is not supported.");
473 }
474
475 Object::ParamsTypeSyncPtrType Object::GetNonConstParams(const std::chrono::milliseconds Timeout) const
476 {
477 return ParamsTypeSyncPtrType(Params.get(), Timeout);
478 }
479
481 {
483 }
484
488
490 {
492 { "Start item as soon as it is created", RunnableObjectParams::StartupType::OnCreation },
493 { "Start item as soon as it is required by another item", RunnableObjectParams::StartupType::Automatic },
494 { "Start item only manually", RunnableObjectParams::StartupType::Manual }
495 };
496
497 return List;
498 }
499
501 {
502 if (!ConfigureStartupType())
503 DisableUserEditable(Startup);
504
505 ConfigureParamsImpl(dispatch_tag<RunnableObjectParams>());
506 }
507
511
513 {
514 return "This item is currently being used by at least another item. Stop and reset these items before stopping this item."
515 + std::string("\n\n") + GetUserNames().data();
516 }
517
519 : Object(OwnerThreadID, std::move(Params)), RunnableInstanceOnly(*this)
520 {
521 Init();
522 }
523
525 {
526 try
527 {
528 // Better call terminate before destruction manually to handle errors.
529 TerminateImpl(false);
530 }
531 catch (const Util::TimeoutException& e)
532 {
533 Util::EventLog().Log(e);
534 Util::EventLog().Log("Could not terminate thread in the runnable's destructor. Timeout occurred. Execution cannot continue.",
536
537 std::terminate();
538 }
539 catch (const Util::NotAvailableException& e)
540 {
541 // Should never happen since modules are destroyed first in DynExpCore.
542 Util::EventLog().Log(e);
543 Util::EventLog().Log("Could not terminate thread in the runnable's destructor. The runnable is still in use. Execution cannot continue.",
545
546 std::terminate();
547 }
548 }
549
550 bool RunnableObject::Run(QWidget* ParentWidget)
551 {
553
554 if (GetException())
556 "A runnable is in an error state. It requires to be reset in order to transition into a ready state.");
557
558 auto StartupDialog = MakeStartupBusyDialogChild(ParentWidget);
559 int Result = QDialog::Accepted;
560 if (StartupDialog)
561 {
562 auto Params = GetParams();
563 ParamsBase::LinkParamStarter LinkParamStarter(*Params);
564 StartupDialog->SetCheckFinishedFunction(LinkParamStarter);
565
566 // StartupDialog->exec() blocks and starts new event loop for the modal dialog (in the same thread).
567 Result = StartupDialog->exec();
568 }
569
570 if (StartupDialog && Result != QDialog::Accepted)
571 {
572 if (StartupDialog->GetException())
573 std::rethrow_exception(StartupDialog->GetException());
574
575 return false;
576 }
577 if (IsRunning())
578 return false;
579
580 // Always call Reset() before starting to allow using Reset() for initialization.
581 // 'if (IsExiting())' could in principle be used here to determine whether the
582 // RunnableObject is not being started for the first time.
583 Reset();
584
585 auto Params = dynamic_Params_cast<RunnableObject>(GetParams());
586 Startup = Params->Startup;
587
588 RunChild();
589 Running = true;
590
591 return true;
592 }
593
595 {
596 auto Params = dynamic_Params_cast<RunnableObject>(GetParams());
597
599 return Run();
600 else if (!IsRunning())
601 throw Util::NotAvailableException("The required item " + Params->ObjectName.Get() + " (" + GetCategoryAndName() +
602 ") cannot be started since automatic startup has been disabled for this item.", Util::ErrorType::Error);
603
604 return false;
605 }
606
608 {
609 auto Params = dynamic_Params_cast<RunnableObject>(GetParams());
610
612 return Run();
613
614 return false;
615 }
616
617 void RunnableObject::Terminate(bool Force, const std::chrono::milliseconds Timeout)
618 {
620
621 TerminateImpl(Force, Timeout);
622 }
623
624 void RunnableObject::SetPaused(bool Pause, std::string Description)
625 {
626 Paused = Pause;
627
628 if (Pause)
629 SetReasonWhyPaused(std::move(Description));
630 else
632 }
633
635 {
636 Running = false;
637 Paused = false;
639 ShouldExit = false;
641 }
642
644 {
645 std::promise<void> ThreadExitedPromise;
646 ThreadExitedSignal = ThreadExitedPromise.get_future();
647
648 return ThreadExitedPromise;
649 }
650
651 void RunnableObject::StoreThread(std::thread&& Thread) noexcept
652 {
653 this->Thread = std::move(Thread);
654 }
655
657 {
658 return std::this_thread::get_id() == Thread.get_id();
659 }
660
662 {
665 "This function must be called from this runnable's thread. A call from another thread is not supported.");
666 }
667
675
676 void RunnableObject::EnsureReadyStateChild(bool IsAutomaticStartup)
677 {
678 IsAutomaticStartup ? RunIfRunAutomatic() : RunIfRunOnCreation();
679 }
680
681 void RunnableObject::TerminateImpl(bool Force, const std::chrono::milliseconds Timeout)
682 {
683 // Now, objects trying to make use of this object cannot register themselves here anymore.
684 auto lock = LockUserList();
685 auto IsUnused = IsUnusedUnsafe();
686
687 if (!Force && !IsUnused)
688 throw NotUnusedException(*this);
689
690 if (!IsUnused)
692 TerminateUnsafe(Force, Timeout);
693 }
694
695 void RunnableObject::TerminateUnsafe(bool Force, const std::chrono::milliseconds Timeout)
696 {
697 if (!Thread.joinable())
698 return;
699
700 TerminateChild(Timeout);
701
702 ShouldExit = true;
703 NotifyChild();
704 if (ThreadExitedSignal.wait_for(Timeout) != std::future_status::ready)
706
707 Thread.join();
708 Thread = std::thread();
709 Running = false;
710 Paused = false;
711 }
712
714 {
715 // Just indicate status changes. All the clean up is performed in the main thread when
716 // 1) Terminate() is called (calls TerminateUnsafe(), Thread is still joinable)
717 // 2) Reset() is called (calls TerminateUnsafe())
718 // 3) Run() is called (it calls Reset())
719 // There is no race condition since TerminateChild() also sets Running to false and
720 // Running is not read in between (IsRunning() is not called).
721 ShouldExit = true;
722 Running = false;
723 Paused = false;
724
725 // This is necessary if the RunnableObject is not terminated regularly but by an error.
727 }
728
732
734 {
735 return Owner.GetOwner();
736 }
737
741
748
752
753 RunnableInstance::RunnableInstance(RunnableObject& Owner, std::promise<void>&& ThreadExitedPromise)
755 Owner(Owner), ThreadExitedPromise(std::move(ThreadExitedPromise))
756 {
757 }
758
759 // Not noexcept since move-constructor of std::list is not noexcept.
761 : ParamsGetter(Other.ParamsGetter), Owner(Other.Owner), ThreadExitedPromise(std::move(Other.ThreadExitedPromise)),
762 OwnedLinkedObjectWrappers(std::move(Other.OwnedLinkedObjectWrappers))
763 {
764 Other.Empty = true;
765 }
766
768 {
770
771 std::for_each(OwnedLinkedObjectWrappers.cbegin(), OwnedLinkedObjectWrappers.cend(), [](const auto& i) {
772 i.OwnedLinkedObjectWrapperContainer.Reset();
773 });
774 }
775
777 {
778 bool AnyDestinyNotReady = false;
779
780 if (GetOwner().RunnableInstanceOnly.IsLinkedObjStateCheckRequested())
781 {
782 GetOwner().RunnableInstanceOnly.ResetLinkedObjStateCheckRequested();
783
784 for (auto& Wrapper : OwnedLinkedObjectWrappers)
785 Wrapper.OwnedLinkedObjectWrapperContainer.CheckIfReady();
786 }
787
788 for (auto& Wrapper : OwnedLinkedObjectWrappers)
789 {
790 if (Wrapper.OwnedLinkedObjectWrapperContainer.GetState() == LinkedObjectWrapperContainerBase::LinkedObjectStateType::NotReady)
791 {
792 AnyDestinyNotReady = true;
793
794 if (Wrapper.OwnedLinkedObjectWrapperPtr->IsRegistered())
795 Wrapper.OwnedLinkedObjectWrapperPtr->Deregister(std::chrono::milliseconds(100));
796 else
797 {
798 try
799 {
800 Wrapper.OwnedLinkedObjectWrapperPtr->Register(ObjectLinkBase::LockObjectTimeoutDefault);
801 Wrapper.OwnedLinkedObjectWrapperContainer.LinkedObjectState = LinkedObjectWrapperContainerBase::LinkedObjectStateType::Ready;
802 }
803 catch (...)
804 {
805 // Registering failed because underlying object is still in an error state.
806 // Swallow the exception and try again next time this function is called.
807 }
808 }
809 }
810 }
811
812 return !AnyDestinyNotReady;
813 }
814
816 {
817 std::string Names("Linked items not being in a ready state:");
818 for (auto& Wrapper : OwnedLinkedObjectWrappers)
819 if (Wrapper.OwnedLinkedObjectWrapperContainer.GetState() == LinkedObjectWrapperContainerBase::LinkedObjectStateType::NotReady)
820 Names += "\n- " + Wrapper.OwnedLinkedObjectWrapperContainer.GetLinkedObjectDesc();
821
822 return Names;
823 }
824
826 {
827 if (!Empty)
828 {
829 // ThreadExitedPromise.set_value_at_thread_exit(); does not work, because
830 // ThreadExitedSignal.wait_for(Timeout) in InstrumentBase::Terminate() would not
831 // return in case of timeout since the value is already stored.
832 ThreadExitedPromise.set_value();
833
834 GetOwner().RunnableInstanceOnly.OnThreadHasExited();
835 }
836 }
837}
Defines DynExp's core module as an interface between the UI and DynExp objects.
Implementation of DynExp objects as the base for derived resources and implementation of the object p...
virtual ~ConfiguratorBase()=0
Definition Object.cpp:310
ParamsBasePtrType MakeConfigFromXML(ItemIDType ID, const DynExpCore &Core, const QDomElement &XMLElement) const
Retrieves the configuration from an XML node to create an instance of the related Object's parameter ...
Definition Object.cpp:324
ParamsBasePtrType MakeConfigFromDialog(ItemIDType ID, const DynExpCore &Core, QWidget *const DialogParent) const
Sets up and displays a configuration dialog. The user input is used to create an instance of the rela...
Definition Object.cpp:314
UpdateConfigFromDialogResult UpdateConfigFromDialog(Object *Obj, const DynExpCore &Core, QWidget *const DialogParent) const
Updates an Object's Obj parameters from a configuration dialog. Sets up and displays this dialog.
Definition Object.cpp:333
DynExp's core class acts as the interface between the user interface and DynExp's internal data like ...
Definition DynExpCore.h:127
const Object & GetOwner() const noexcept
Returns the owner of this wrapper.
Definition Object.cpp:733
const RunnableInstance & Owner
Instance of class RunnableInstance managing the wrapper.
Definition Object.h:2809
void Reset() noexcept
Removes any linked LinkedObjectWrapper and updates LinkedObjectState.
Definition Object.cpp:742
LinkedObjectStateType LinkedObjectState
Stores the current state of this LinkedObjectWrapperContainerBase instance. Refer to LinkedObjectStat...
Definition Object.h:3117
virtual void ResetChild() noexcept=0
Removes any linked LinkedObjectWrapper and updates LinkedObjectState.
virtual ~ObjectLinkBase()=0
Definition Object.cpp:749
static constexpr std::chrono::milliseconds LockObjectTimeoutDefault
Default timeout used by classes ObjectLinkt and RunnableInstance to be passed to LinkedObjectWrapper:...
Definition Object.h:3359
std::string GetUserNamesString(std::chrono::milliseconds Timeout=std::chrono::milliseconds(0)) const
Builds a string describing which users are registered containing their object names,...
Definition Object.cpp:49
void Deregister(const Object &User, const std::chrono::milliseconds Timeout=std::chrono::milliseconds(0))
Deregisters a user in a thread-safe way.
Definition Object.cpp:28
std::string GetUserNamesStringUnsafe() const
Definition Object.cpp:82
void Register(const Object &User, const std::chrono::milliseconds Timeout=std::chrono::milliseconds(0))
Registers a user in a thread-safe way.
Definition Object.cpp:14
std::unordered_map< const Object *, size_t > UserList
Map containing pointers to all users making use of this ObjectUserList instance's owner as keys and t...
Definition Object.h:176
void DeregisterAllUnsafe()
Deregisters all users and notifies them that they need to check the states of their used linked objec...
Definition Object.cpp:56
size_t CountUsersUnsafe() const
Definition Object.cpp:64
size_t CountUsers(std::chrono::milliseconds Timeout=std::chrono::milliseconds(0)) const
Counts the registered useres in a thread-safe way.
Definition Object.cpp:35
ItemIDListType GetUserIDsUnsafe() const
Definition Object.cpp:72
void DeregisterUnsafe(const Object &User)
Deregisters a user.
Definition Object.cpp:101
void RegisterUnsafe(const Object &User)
Registers a user.
Definition Object.cpp:91
Util::ILockable::LockType AcquireLock(const std::chrono::milliseconds Timeout=DefaultTimeout) const
Locks the user list for thread-safe manipulation.
Definition Object.cpp:9
ItemIDListType GetUserIDs(std::chrono::milliseconds Timeout=std::chrono::milliseconds(0)) const
Returns a list of the IDs of the registered users in a thread-safe way.
Definition Object.cpp:42
void DeregisterUser(const Object &User, const std::chrono::milliseconds Timeout) const
Deregisters a user in a thread-safe way.
Definition Object.cpp:398
Object & Parent
Owning Object instance.
Definition Object.h:2068
void RegisterUser(const Object &User, const std::chrono::milliseconds Timeout) const
Registers a user in a thread-safe way.
Definition Object.cpp:375
Base class for all DynExp Objects like hardware adapters (DynExp::HardwareAdapterBase),...
Definition Object.h:1971
Object(const std::thread::id OwnerThreadID, ParamsBasePtrType &&Params)
Constructs an Object instance.
Definition Object.cpp:358
void SetWarning(std::string Description, int ErrorCode) const
Setter for Object::Warning. Sets the warning by a description and an error code.
Definition Object.cpp:454
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
std::string GetCategoryAndName() const
Builds a string from an Object's category and name to allow the user to identify an Object's type.
Definition Object.h:2158
Util::SynchronizedPointer< const ParamsType > ParamsConstTypeSyncPtrType
Alias for the return type of Object::GetParams() const. Parameters wrapped into Util::SynchronizedPoi...
Definition Object.h:1989
Util::Warning Warning
Last warning which occurred within this Object instance. (Logical const-ness: see above....
Definition Object.h:2305
virtual void EnsureReadyStateChild(bool IsAutomaticStartup)=0
Ensures that this Object instance is ready by possibly starting its worker thread or by opening conne...
void LogWarning() const
Writes Object::Warning to the event log returned by Util::EventLog().
Definition Object.cpp:480
virtual ~Object()=0
Definition Object.cpp:368
const std::thread::id OwnerThreadID
Thread id of the thread which has constructed (and owns) this Object instance.
Definition Object.h:2302
virtual void ResetImpl(dispatch_tag< Object >)=0
Refer to DynExp::Object::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of every de...
void BlockIfUnused(const std::chrono::milliseconds Timeout=Util::ILockable::DefaultTimeout)
Blocks this Object instance setting Object::IsBlocked to true. Refer to Object::IsBlocked for the con...
Definition Object.cpp:421
bool IsUnusedUnsafe()
Returns whether this Object instance is used by other instances (not thread-safe).
Definition Object.h:2273
bool IsUnused(const std::chrono::milliseconds Timeout=Util::ILockable::DefaultTimeout) const
Returns whether this Object instance is used by other instances.
Definition Object.h:2223
void ClearWarning() const
Resets Object::Warning.
Definition Object.h:2190
void Reset()
Resets this Object instance (including all its derived classes) by calling ResetImpl()....
Definition Object.cpp:403
const ParamsBasePtrType Params
Pointer to the parameter class instance belonging to this Object instance.
Definition Object.h:2303
static constexpr std::chrono::milliseconds GetParamsTimeoutDefault
Default timeout used by Object::GetParams() to lock the mutex of the parameter instance assigned to t...
Definition Object.h:2010
ParamsTypeSyncPtrType GetNonConstParams(const std::chrono::milliseconds Timeout=GetParamsTimeoutDefault) const
Allows derived Objects to edit their own parameters - even in const task functions (for instruments) ...
Definition Object.cpp:475
ObjectUserList UserList
List of Object instances making use of this Object instance. Other Object instances making use of thi...
Definition Object.h:2312
bool IsReady() const
Returns wheter this Object instance is ready (e.g. it is running or connected to a hardware device) a...
Definition Object.h:2211
bool IsBlocked
This flag indicates whether this Object instance is blocked in order to be destroyed subsequently....
Definition Object.h:2320
void EnsureReadyState(bool IsAutomaticStartup)
Ensures that this Object instance is ready by possibly starting its worker thread or by opening conne...
Definition Object.cpp:446
std::exception_ptr GetException(const std::chrono::milliseconds Timeout=Util::ILockable::DefaultTimeout) const
Returns a pointer to the exception which has caused this Object instance to fail.
Definition Object.h:2204
void DeregisterAllUnsafe()
Deregisters all users and notifies them that they need to check the states of their used linked objec...
Definition Object.h:2265
bool IsSharedUsageEnabled(const std::chrono::milliseconds Timeout=GetParamsTimeoutDefault) const
Returns whether shared usage has been enabled for this Object instance. Refer to ParamsBase::UsageTyp...
Definition Object.h:2136
auto GetObjectName(const std::chrono::milliseconds Timeout=GetParamsTimeoutDefault) const
Returns the name of this Object instance.
Definition Object.h:2128
Util::SynchronizedPointer< ParamsType > ParamsTypeSyncPtrType
Alias for the return type of Object::GetParams(). Parameters wrapped into Util::SynchronizedPointer c...
Definition Object.h:1983
static std::string CategoryAndNameToStr(const std::string &Category, const std::string &Name)
Builds a string from an Object's category and name to allow the user to identify an Object's type.
Definition Object.cpp:350
auto LockUserList(const std::chrono::milliseconds Timeout=Util::ILockable::DefaultTimeout)
Locks the user list for thread-safe manipulation.
Definition Object.h:2264
void EnsureCallFromOwningThread() const
Asserts that the call to this function is performed from the thread which constructed this Object ins...
Definition Object.cpp:468
Refer to ParamsBase::dispatch_tag.
Definition Object.h:2018
Makes sure the object link parameters of the associated ParamsBase instance are in a ready state by p...
Definition Object.h:1589
bool operator()()
Performs the initialization stepwise. This functions is to be called as long as it returns true....
Definition Object.cpp:179
Abstract base class for a single object parameter. Parameters derived from this class are automatical...
Definition Object.h:378
ParamBase(ParamsBase &Owner, std::string ParamName, std::string_view ParamTitle, std::string_view ParamDescription, bool NeedsResetToApplyChange)
Base constructor of any parameter to be used if a parameter should be displayed in a settings dialog ...
Definition Object.cpp:113
void FromXMLNode(const QDomElement &XMLElement)
Restores this parameter's value from the given Qt dom element (describing an XML node)
Definition Object.cpp:145
bool Validate()
Checks whether a valid value is assigned to this parameter. This function is not const since it is al...
Definition Object.cpp:164
ParamsBase & Owner
Owner of this parameter. Owner always lives longer than this object.
Definition Object.h:498
QDomElement ToXMLNode(QDomDocument &Document) const
Converts this parameter to a Qt dom element (describing an XML node containing this parameter's name ...
Definition Object.cpp:137
Abstract base class for object parameter classes. Each class derived from class Object must be accomp...
Definition Object.h:326
virtual const char * GetParamClassTag() const noexcept
This function is intended to be overridden once in each derived class returning the name of the respe...
Definition Object.h:1643
QDomElement ConfigToXML(QDomDocument &Document) const
Creates an XML node with a tag name as determined by GetParamClassTag() containing all parameters bel...
Definition Object.cpp:202
bool ConfigureUsageType() const noexcept
Determines whether the Usage parameter should be configurable in the settings dialog....
Definition Object.h:1733
Param< UsageType > Usage
Determines whether an object can be used by only one other ("unique") or by multiple other ("shared")...
Definition Object.h:1725
virtual void ConfigureParamsImpl(dispatch_tag< ParamsBase >)
Called by DynExp::ParamsBase::ConfigureParams() as a starting point for the tag dispatch mechanism to...
Definition Object.h:1762
const auto & GetCore() const noexcept
Returns a reference to DynExp's core.
Definition Object.h:1677
bool Validate() const
Refer to ParamBase::Validate().
Definition Object.cpp:271
void ConfigureParams()
Called by ConfigFromDialog() to apply changes to parameters owned by this parameter class instance be...
Definition Object.cpp:297
void ConfigFromXML(const QDomElement &XMLElement) const
Retrieves all parameters belonging to this ParamsBase instance from an XML node with a tag name as de...
Definition Object.cpp:222
OwnedParamsType OwnedParams
List of all parameters owned by this parameter class instance.
Definition Object.h:1712
static void DisableUserEditable(ParamBase &Param) noexcept
Sets the UserEditable property of the parameter Param to false. Refer to ParamBase::UserEditable.
Definition Object.cpp:292
const ItemIDType ID
ID of the Object this parameter class instance belongs to.
Definition Object.h:1779
void ConfigFromDialog(ParamsConfigDialog &Dialog)
Adds all parameters belonging to this ParamsBase instance to a settings dialog to let the user config...
Definition Object.cpp:260
virtual ~ParamsBase()=0
Definition Object.cpp:198
std::filesystem::path ToAbsolutePath(const std::filesystem::path &Path) const
Transforms the path Path into an absolute path relative to ProjectParams::ProjectFilename.
Definition Object.cpp:305
const DynExpCore & Core
Reference to DynExp's core.
Definition Object.h:1780
static Util::TextValueListType< UsageType > AvlblUsageTypeStrList()
Maps description strings to the ParamsBase::UsageType enum's items.
Definition Object.cpp:282
Tag for function dispatching mechanism within this class used when derived classes are not intended t...
Definition Object.h:349
Defines data for a thread belonging to a RunnableObject instance. This data is only accessed by the R...
Definition Object.h:3505
RunnableInstance(RunnableObject &Owner, std::promise< void > &&ThreadExitedPromise)
Constructs a non-empty RunnableInstance instance.
Definition Object.cpp:753
LinkedObjectWrapperBase::ListType OwnedLinkedObjectWrappers
List of all LinkedObjectWrapper instances owned by this RunnableInstance instance (thus belonging to ...
Definition Object.h:3726
void SetThreadExited()
Signals that Owner's thread has exited. Refer to RunnableObject::OnThreadHasExited().
Definition Object.cpp:825
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
const RunnableObject & Owner
RunnableObject instance which operates on this RunnableInstance (by its thread). The RunnableObject i...
Definition Object.h:3705
bool Empty
Set to true if it was moved from this instance to indicate that ThreadExitedPromise has no shared sta...
Definition Object.h:3718
std::promise< void > ThreadExitedPromise
Signals the RunnableObject instance owning the thread that its thread has terminated....
Definition Object.h:3712
const auto & GetOwner() const noexcept
Returns Owner.
Definition Object.h:3524
static Util::TextValueListType< StartupType > AvlblStartupTypeStrList()
Maps description strings to the RunnableObjectParams::StartupType enum's items.
Definition Object.cpp:489
void ConfigureParamsImpl(dispatch_tag< ParamsBase >) override final
Called by DynExp::ParamsBase::ConfigureParams() as a starting point for the tag dispatch mechanism to...
Definition Object.cpp:500
virtual ~RunnableObjectParams()=0
Definition Object.cpp:485
Exception type thrown by TerminateImpl() if the RunnableObject cannot be terminated for being used by...
Definition Object.h:2454
std::string GetErrorMessage() const
Genereates a user-readable error message containing the content of UserNames.
Definition Object.cpp:512
Defines an Object which possesses a thread it runs in. The RunnableObject can be started and stopped ...
Definition Object.h:2426
std::atomic< bool > Running
Indicates whether the RunnableObject instance is running.
Definition Object.h:2684
void ResetImpl(dispatch_tag< Object >) override final
Refer to DynExp::Object::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of every de...
Definition Object.cpp:668
bool IsCallFromRunnableThread() const
Checks whether Thread's id matches the id of the calling thread. This is thread-safe if the function ...
Definition Object.cpp:656
std::promise< void > MakeThreadExitedPromise()
Helper function to be used by overridden RunChild() functions in derived classes to (re)initialize th...
Definition Object.cpp:643
virtual std::unique_ptr< BusyDialog > MakeStartupBusyDialogChild(QWidget *ParentWidget) const
Override to make this function return a pointer to a BusyDialog instance. Refer to Run().
Definition Object.h:2646
void Init()
Initializes member variables in case of a reset.
Definition Object.cpp:634
bool Run(QWidget *ParentWidget=nullptr)
Starts the RunnableObject instance's thread and ensures that all Object instances linked to this inst...
Definition Object.cpp:550
std::future< void > ThreadExitedSignal
Future which signals that Thread has terminated. Refer to OnThreadHasExited().
Definition Object.h:2683
virtual void NotifyChild()
Notify derived classes that some state has changed (e.g. the termination of Thread is requested) and ...
Definition Object.h:2629
virtual void RunChild()=0
Refer to Run().
RunnableObject(const std::thread::id OwnerThreadID, ParamsBasePtrType &&Params)
Constructs an Object instance.
Definition Object.cpp:518
void TerminateUnsafe(bool Force, const std::chrono::milliseconds Timeout=TerminateTimeoutDefault)
Notifies the RunnableObject instance's thread to terminate and waits until it has ended....
Definition Object.cpp:695
virtual ~RunnableObject()=0
Definition Object.cpp:524
std::thread Thread
The RunnableObject instance's thread.
Definition Object.h:2682
bool RunIfRunAutomatic()
Calls Run() if RunnableObjectParams::Startup is set to RunnableObjectParams::Automatic.
Definition Object.cpp:594
std::atomic< RunnableObjectParams::StartupType > Startup
Reflects the value of RunnableObjectParams::Startup. This variable is only updated when Run() is call...
Definition Object.h:2680
void TerminateImpl(bool Force, const std::chrono::milliseconds Timeout=TerminateTimeoutDefault)
Notifies the RunnableObject instance's thread to terminate and waits until it has ended....
Definition Object.cpp:681
std::atomic< bool > Paused
Indicates whether the RunnableObject instance is paused.
Definition Object.h:2685
std::atomic< bool > ShouldExit
Indicates whether this RunnableObject instance's thread should terminate.
Definition Object.h:2693
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
Util::Warning ReasonWhyPaused
Holds information about why the RunnableObject instance is paused.
Definition Object.h:2686
void OnThreadHasExited() noexcept
This function is called when the RunnableObject instance's thread terminates. The thread receives a R...
Definition Object.cpp:713
std::atomic< bool > LinkedObjStateCheckRequested
Indicates whether the RunnableInstance instance belonging to this RunnableObject instance's thread sh...
Definition Object.h:2700
void ClearReasonWhyPaused()
Removes the reason why this RunnableObject instance has been paused (since it is resumed).
Definition Object.h:2610
void SetReasonWhyPaused(std::string Description)
Sets the reason why this RunnableObject instance has been paused.
Definition Object.h:2599
void EnsureCallFromRunnableThread() const
Asserts that the call to this function is performed from the RunnableObject instance's thread by call...
Definition Object.cpp:661
void EnsureReadyStateChild(bool IsAutomaticStartup) override final
Ensures that this Object instance is ready by possibly starting its worker thread or by opening conne...
Definition Object.cpp:676
void SetPaused(bool Pause, std::string Description="")
Pauses or resumes a RunnableObject instance. Its thread stays running, but the instance does not perf...
Definition Object.cpp:624
bool IsRunning() const noexcept
Returns Running.
Definition Object.h:2550
bool RunIfRunOnCreation()
Calls Run() if RunnableObjectParams::Startup is set to RunnableObjectParams::OnCreation.
Definition Object.cpp:607
void Terminate(bool Force=false, const std::chrono::milliseconds Timeout=TerminateTimeoutDefault)
Notifies the RunnableObject instance's thread to terminate and waits until it has ended....
Definition Object.cpp:617
virtual void TerminateChild(const std::chrono::milliseconds Timeout)
Signals derived classes that terminating the RunnableObject instance's thread is about to be requeste...
Definition Object.h:2638
Defines the configuration dialog. The dialog must be displayed by calling ParamsConfigDialog::Display...
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
std::unique_lock< MutexType > LockType
Definition Util.h:66
An invalid argument like a null pointer has been passed to a function.
Definition Exception.h:137
Thrown when a function call is not allowed to a specific thread in a multi-threading context.
Definition Exception.h:175
An operation cannot be performed currently since the related object is in an invalid state like an er...
Definition Exception.h:150
Thrown when some operation or feature is temporarily or permanently not available.
Definition Exception.h:286
Thrown when a requested ressource does not exist.
Definition Exception.h:236
Thrown when a numeric operation would result in an overflow (e.g. due to incompatible data types)
Definition Exception.h:199
Pointer to lock a class derived from ISynchronizedPointerLockable for synchronizing between threads....
Definition Util.h:170
Thrown in a multi-threading context when an answer is expected from another thread an when the commun...
Definition Exception.h:274
Thrown when an operation timed out before it could be completed, especially used for locking shared d...
Definition Exception.h:261
Thrown when a numeric operation would result in an underflow (e.g. due to incompatible data types)
Definition Exception.h:187
Class to store information about warnings in a thread-safe manner (deriving from ILockable)....
Definition Util.h:966
void Reset()
Clears the warning data.
Definition Util.cpp:273
DynExp's main namespace contains the implementation of DynExp including classes to manage resources (...
ParamsBasePtrType MakeParams(ItemIDType ID, const DynExpCore &Core)
Factory function to generate an Object's parameters.
Definition Object.h:1818
std::vector< ItemIDType > ItemIDListType
Type of a list of IDs belonging to objects managed by DynExp.
Definition Object.h:40
std::unique_ptr< ParamsBase > ParamsBasePtrType
Alias for a pointer to the parameter system base class ParamsBase.
Definition Object.h:1807
size_t ItemIDType
ID type of objects/items managed by DynExp.
QDomElement GetSingleChildDOMElement(const QDomElement &Parent, const QString &ChildTagName)
Behaves like GetSingleChildDOMNode() but returns the node converted to a DOM element.
Definition QtUtil.cpp:62
EventLogger & EventLog()
This function holds a static EventLogger instance and returns a reference to it. DynExp uses only one...
Definition Util.cpp:509
std::vector< std::pair< TextType, ValueType > > TextValueListType
Type of a list containing key-value pairs where key is a text of type Util::TextType.
Definition QtUtil.h:37
Accumulates include statements to provide a precompiled header.
Return type of ConfiguratorBase::UpdateConfigFromDialog() indicating the result of the configurator d...
Definition Object.h:1889