PLCnext API Documentation 24.0.0.71
AppDomain.hpp
1
2//
3// Copyright PHOENIX CONTACT Electronics GmbH
4//
6#pragma once
8#include "Arp/System/Core/Singleton.hxx"
9#include <map>
10#include <stack>
11#include <typeinfo>
12#include <typeindex>
13
14#ifdef ARP_PLATFORM_LINUX
15 #include <pthread.h>
16#else
17 #include <mutex>
18#endif
19
20
21// forwards
22namespace Arp { namespace System { namespace Acf
23{
24class IApplication;
25}}} // end of namesapce Arp::System::Acf
26
27namespace Arp
28{
29
31
32#ifdef ARP_PLATFORM_LINUX
33class RdLockGuard // TODO(OR): replace this by std::lock or move it to namespace Arp::Internal of Core
34{
35public: // construction/destruction
36
40 RdLockGuard(pthread_rwlock_t* rw_lock);
41
43 RdLockGuard(const RdLockGuard& arg) = delete;
44
46 RdLockGuard& operator=(const RdLockGuard& arg) = delete;
47
49 ~RdLockGuard(void);
50
51private: // fields
52 pthread_rwlock_t* rw_lock;
53};
54
56// inline methods of class Mutex
57
58inline RdLockGuard::RdLockGuard(pthread_rwlock_t* rw_lockArg)
59 : rw_lock(rw_lockArg)
60{
61 pthread_rwlock_rdlock(rw_lock);
62}
63
64inline RdLockGuard::~RdLockGuard()
65{
66 pthread_rwlock_unlock(rw_lock);
67}
68
69
70class WrLockGuard
71{
72public: // construction/destruction
73
77 WrLockGuard(pthread_rwlock_t* rw_lock);
78
80 WrLockGuard(const WrLockGuard& arg) = delete;
81
83 WrLockGuard& operator=(const WrLockGuard& arg) = delete;
84
86 ~WrLockGuard(void);
87
88private: // fields
89 pthread_rwlock_t* rw_lock;
90};
91
93// inline methods of class WrLockGuard
94
95inline WrLockGuard::WrLockGuard(pthread_rwlock_t* rw_lockArg)
96 : rw_lock(rw_lockArg)
97{
98 pthread_rwlock_wrlock(rw_lock);
99}
100
101inline WrLockGuard::~WrLockGuard()
102{
103 pthread_rwlock_unlock(rw_lock);
104}
105#endif //ARP_PLATFORM_LINUX
107
118class AppDomain : private Singleton<AppDomain>
119{
120 friend class Singleton<AppDomain>;
121
122public: // usings
123 using Strings = std::vector<String>;
125
126private: // usings
127 using SingletonDisposer = void(*)(void);
129 using TypeKey = std::type_index;
130 using Singletons = std::map<TypeKey, void*>;
131
132private: // construction/destruction
134 AppDomain(void);
136 AppDomain(const AppDomain& arg) = delete;
138 ~AppDomain(void);
139
140public: // static getter
143 static bool IsCreated(void);
144
147 static AppDomain& GetCurrent(void);
148
149public: // static operations
153 template<class TApp>
154 static TApp& Create(void);
155
160 template<class TApp>
161 static TApp& Create(const String& appName);
162
165 template<class TApp>
166 static void Dispose(void);
167
171 static void Assign(AppDomain& other);
172
173public: // getter operations
176 IApplication& GetApplication(void);
177
180 size_t GetSingletonsCount(void)const;
181
184 Strings GetSingletonsTypeName(void)const;
185
186public: // singleton operations
190 template<class TSingleton>
191 void AddSingleton(TSingleton* pSingleton);
192
196 template<class TSingleton>
197 TSingleton& GetSingleton(void);
198
202 template<class TSingleton>
203 TSingleton* GetSingletonPtr(void);
204
208 template<class TSingleton>
209 bool RemoveSingleton(void);
210
211private: // static methods
212 template<class T>
213 static TypeKey GetTypeKey(void);
214
215private: // fields
216 IApplication* pApplication;
217 Singletons singletons;
218
219#ifdef ARP_PLATFORM_LINUX
220 pthread_rwlock_t rw_lock;
221#else
222 std::mutex rw_lock;
223#endif
224};
225
227// inline methods of class AppDomain
228inline AppDomain::AppDomain()
229 : pApplication(nullptr)
230 , singletons()
231{
232#ifdef ARP_PLATFORM_LINUX
233 pthread_rwlock_init(&this->rw_lock, NULL);
234#endif
235}
236
237inline bool AppDomain::IsCreated(void)
238{
240}
241
243{
245}
246
247template<class T>
248inline AppDomain::TypeKey AppDomain::GetTypeKey(void)
249{
250 return std::type_index(typeid(T));
251}
252
253template<class TApp>
254inline TApp& AppDomain::Create(void)
255{
256 // create this appDomain instance first
258 // create app singleton next
259 TApp::CreateInstance();
260 // and get the app instance
261 SingletonBase::GetInstance().pApplication = &TApp::GetInstance();
262 // return just created app
263 return dynamic_cast<TApp&>(TApp::GetInstance());
264}
265
266template<class TApp>
267inline TApp& AppDomain::Create(const String& appName)
268{
269 // create this appDomain instance first
271 // create app singleton next
272 TApp::CreateInstance(appName);
273 // and get the app instance
274 SingletonBase::GetInstance().pApplication = &TApp::GetInstance();
275 // return just created app
276 return dynamic_cast<TApp&>(TApp::GetInstance());
277}
278
279inline void AppDomain::Assign(AppDomain& other)
280{
282 {
284 }
285}
286
287template<class TApp>
288inline void AppDomain::Dispose(void)
289{
290 TApp::DisposeInstance();
292}
293
295{
296 return *(this->pApplication);
297}
298
300{
301 return this->singletons.size();
302}
303
304template<class TSingleton>
305inline void AppDomain::AddSingleton(TSingleton* pSingleton)
306{
307#ifdef ARP_PLATFORM_LINUX
308 WrLockGuard lock(&this->rw_lock);
309#else
310 std::lock_guard<std::mutex> lock(this->rw_lock);
311#endif
312
313
314 auto result = this->singletons.insert(make_pair(AppDomain::GetTypeKey<TSingleton>(), pSingleton));
315 if (!result.second)
316 {
317 throw Exception("AppDomain Singleton of type '{0}' has been added yet", TypeName<TSingleton>());
318 }
319}
320
321template<class TSingleton>
322inline TSingleton& AppDomain::GetSingleton()
323{
324 TSingleton* pResult = this->GetSingletonPtr<TSingleton>();
325 if (pResult == nullptr)
326 {
327 throw Exception("AppDomain does not contain Singleton of type '{0}'", TypeName<TSingleton>().GetFullName());
328 }
329 return *pResult;
330}
331template<class TSingleton>
332inline TSingleton* AppDomain::GetSingletonPtr()
333{
334#ifdef ARP_PLATFORM_LINUX
335 RdLockGuard lock(&this->rw_lock);
336#else
337 std::lock_guard<std::mutex> lock(this->rw_lock);
338#endif
339
340 auto i = this->singletons.find(AppDomain::GetTypeKey<TSingleton>());
341 if (i == this->singletons.end())
342 {
343 return nullptr;
344 }
345 // else
346 return (TSingleton*)(i->second); // is there any other way than a brute force cast?
347}
348
349template<class TSingleton>
351{
352#ifdef ARP_PLATFORM_LINUX
353 WrLockGuard lock(&this->rw_lock);
354#else
355 std::lock_guard<std::mutex> lock(this->rw_lock);
356#endif
357
358 return this->singletons.erase(AppDomain::GetTypeKey<TSingleton>()) != 0;
359}
360
361} // end of namesapce Arp
This class represents a single application domain for each process and is implemented as singleton.
Definition: AppDomain.hpp:119
void AddSingleton(TSingleton *pSingleton)
Adds a singleton instance to this AppDomain.
Definition: AppDomain.hpp:305
static bool IsCreated(void)
Determines if the appdomain was created yet.
Definition: AppDomain.hpp:237
IApplication & GetApplication(void)
Gets the application instance of the current process.
Definition: AppDomain.hpp:294
static void Dispose(void)
Disposes the current AppDomain and destructs the application.
Definition: AppDomain.hpp:288
TSingleton * GetSingletonPtr(void)
Gets the singleton pointer of the specified type.
Definition: AppDomain.hpp:332
static TApp & Create(void)
Creates the current AppDomain and application instances.
Definition: AppDomain.hpp:254
static AppDomain & GetCurrent(void)
Gets the current AppDomain instance.
Definition: AppDomain.hpp:242
Strings GetSingletonsTypeName(void) const
Gets the type names of currently available singletons
size_t GetSingletonsCount(void) const
Gets the count of available singletons.
Definition: AppDomain.hpp:299
TSingleton & GetSingleton(void)
Gets the singleton instance of the specified type.
Definition: AppDomain.hpp:322
static void Assign(AppDomain &other)
Assgins the current AppdDomain singleton from the as argument passed other.
Definition: AppDomain.hpp:279
bool RemoveSingleton(void)
Removes the singleton pointer of the specified type from this AppDomain.
Definition: AppDomain.hpp:350
This is the base class of all Arp exception classes.
Definition: Exception.hpp:16
This class implements the singleton pattern.
Definition: Singleton.hxx:25
static void DisposeInstance(void)
Disposes this singleton instance.
Definition: Singleton.hxx:134
static bool IsCreated(void)
Determines if this singleton instance is create yet.
Definition: Singleton.hxx:111
static Instance & CreateInstance(Args &&... args)
Creates this singleton instance.
Definition: Singleton.hxx:97
static Instance & GetInstance(void)
Gets a reference of the singleton instance.
Definition: Singleton.hxx:117
static void AssignInstanceFrom(Instance &other)
Assigns the singleton instance from another singleton instance of the same type.
Definition: Singleton.hxx:150
This interface shall be implemented by the application class.
Definition: IApplication.hpp:19
This (meta programming) class provides the C++ typename of the as template argument passed type.
Definition: TypeName.hxx:67
@ System
System components used by the System, Device, Plc or Io domains.
Root namespace for the PLCnext API