PLCnext API Documentation 23.0.2.9
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
30using namespace Arp::System::Acf;
31
32
34
35#ifdef ARP_PLATFORM_LINUX
36class RdLockGuard // TODO(OR): replace this by std::lock or move it to namespace Arp::Internal of Core
37{
38public: // construction/destruction
39
43 RdLockGuard(pthread_rwlock_t* rw_lock);
44
46 RdLockGuard(const RdLockGuard& arg) = delete;
47
49 RdLockGuard& operator=(const RdLockGuard& arg) = delete;
50
52 ~RdLockGuard(void);
53
54private: // fields
55 pthread_rwlock_t* rw_lock;
56};
57
59// inline methods of class Mutex
60
61inline RdLockGuard::RdLockGuard(pthread_rwlock_t* rw_lockArg)
62 : rw_lock(rw_lockArg)
63{
64 pthread_rwlock_rdlock(rw_lock);
65}
66
67inline RdLockGuard::~RdLockGuard()
68{
69 pthread_rwlock_unlock(rw_lock);
70}
71
72
73class WrLockGuard
74{
75public: // construction/destruction
76
80 WrLockGuard(pthread_rwlock_t* rw_lock);
81
83 WrLockGuard(const WrLockGuard& arg) = delete;
84
86 WrLockGuard& operator=(const WrLockGuard& arg) = delete;
87
89 ~WrLockGuard(void);
90
91private: // fields
92 pthread_rwlock_t* rw_lock;
93};
94
96// inline methods of class WrLockGuard
97
98inline WrLockGuard::WrLockGuard(pthread_rwlock_t* rw_lockArg)
99 : rw_lock(rw_lockArg)
100{
101 pthread_rwlock_wrlock(rw_lock);
102}
103
104inline WrLockGuard::~WrLockGuard()
105{
106 pthread_rwlock_unlock(rw_lock);
107}
108#endif //ARP_PLATFORM_LINUX
110
121class AppDomain : private Singleton<AppDomain>
122{
123 friend class Singleton<AppDomain>;
124
125public: // usings
126 using Strings = std::vector<String>;
127
128private: // usings
129 using SingletonDisposer = void(*)(void);
131 using TypeKey = std::type_index;
132 using Singletons = std::map<TypeKey, void*>;
133
134private: // construction/destruction
136 AppDomain(void);
138 AppDomain(const AppDomain& arg) = delete;
140 ~AppDomain(void);
141
142public: // static getter
145 static bool IsCreated(void);
146
149 static AppDomain& GetCurrent(void);
150
151public: // static operations
155 template<class TApp>
156 static TApp& Create(void);
157
162 template<class TApp>
163 static TApp& Create(const String& appName);
164
167 template<class TApp>
168 static void Dispose(void);
169
173 static void Assign(AppDomain& other);
174
175public: // getter operations
178 IApplication& GetApplication(void);
179
182 size_t GetSingletonsCount(void)const;
183
186 Strings GetSingletonsTypeName(void)const;
187
188public: // singleton operations
192 template<class TSingleton>
193 void AddSingleton(TSingleton* pSingleton);
194
198 template<class TSingleton>
199 TSingleton& GetSingleton(void);
200
204 template<class TSingleton>
205 TSingleton* GetSingletonPtr(void);
206
210 template<class TSingleton>
211 bool RemoveSingleton(void);
212
213private: // static methods
214 template<class T>
215 static TypeKey GetTypeKey(void);
216
217private: // fields
218 IApplication* pApplication;
219 Singletons singletons;
220
221#ifdef ARP_PLATFORM_LINUX
222 pthread_rwlock_t rw_lock;
223#else
224 std::mutex rw_lock;
225#endif
226};
227
229// inline methods of class AppDomain
230inline AppDomain::AppDomain()
231 : pApplication(nullptr)
232 , singletons()
233{
234#ifdef ARP_PLATFORM_LINUX
235 pthread_rwlock_init(&this->rw_lock, NULL);
236#endif
237}
238
239inline bool AppDomain::IsCreated(void)
240{
242}
243
245{
247}
248
249template<class T>
250inline AppDomain::TypeKey AppDomain::GetTypeKey(void)
251{
252 return std::type_index(typeid(T));
253}
254
255template<class TApp>
256inline TApp& AppDomain::Create(void)
257{
258 // create this appDomain instance first
260 // create app singleton next
261 TApp::CreateInstance();
262 // and get the app instance
263 SingletonBase::GetInstance().pApplication = TApp::GetInstancePtr();
264 // return just created app
265 return dynamic_cast<TApp&>(TApp::GetInstance());
266}
267
268template<class TApp>
269inline TApp& AppDomain::Create(const String& appName)
270{
271 // create this appDomain instance first
273 // create app singleton next
274 TApp::CreateInstance(appName);
275 // and get the app instance
276 SingletonBase::GetInstance().pApplication = TApp::GetInstancePtr();
277 // return just created app
278 return dynamic_cast<TApp&>(TApp::GetInstance());
279}
280
281inline void AppDomain::Assign(AppDomain& other)
282{
284 {
286 }
287}
288
289template<class TApp>
290inline void AppDomain::Dispose(void)
291{
292 TApp::DisposeInstance();
294}
295
297{
298 return *(this->pApplication);
299}
300
302{
303 return this->singletons.size();
304}
305
306template<class TSingleton>
307inline void AppDomain::AddSingleton(TSingleton* pSingleton)
308{
309#ifdef ARP_PLATFORM_LINUX
310 WrLockGuard lock(&this->rw_lock);
311#else
312 std::lock_guard<std::mutex> lock(this->rw_lock);
313#endif
314
315
316 auto result = this->singletons.insert(make_pair(AppDomain::GetTypeKey<TSingleton>(), pSingleton));
317 if (!result.second)
318 {
319 throw Exception("AppDomain Singleton of type '{0}' has been added yet", TypeName<TSingleton>().Value);
320 }
321}
322
323template<class TSingleton>
324inline TSingleton& AppDomain::GetSingleton()
325{
326 TSingleton* pResult = this->GetSingletonPtr<TSingleton>();
327 if (pResult == nullptr)
328 {
329 throw Exception("AppDomain does not contain Singleton of type '{0}'", TypeName<TSingleton>().Value);
330 }
331 return *pResult;
332}
333template<class TSingleton>
334inline TSingleton* AppDomain::GetSingletonPtr()
335{
336#ifdef ARP_PLATFORM_LINUX
337 RdLockGuard lock(&this->rw_lock);
338#else
339 std::lock_guard<std::mutex> lock(this->rw_lock);
340#endif
341
342 auto i = this->singletons.find(AppDomain::GetTypeKey<TSingleton>());
343 if (i == this->singletons.end())
344 {
345 return nullptr;
346 }
347 // else
348 return (TSingleton*)(i->second); // is there any other way than a brute force cast?
349}
350
351template<class TSingleton>
353{
354#ifdef ARP_PLATFORM_LINUX
355 WrLockGuard lock(&this->rw_lock);
356#else
357 std::lock_guard<std::mutex> lock(this->rw_lock);
358#endif
359
360 return this->singletons.erase(AppDomain::GetTypeKey<TSingleton>()) != 0;
361}
362
363} // end of namesapce Arp
This class represents a single application domain for each process and is implemented as singleton.
Definition: AppDomain.hpp:122
void AddSingleton(TSingleton *pSingleton)
Adds a singleton instance to this AppDomain.
Definition: AppDomain.hpp:307
static bool IsCreated(void)
Determines if the appdomain was created yet.
Definition: AppDomain.hpp:239
static void Dispose(void)
Disposes the current AppDomain and destructs the application.
Definition: AppDomain.hpp:290
TSingleton * GetSingletonPtr(void)
Gets the singleton pointer of the specified type.
Definition: AppDomain.hpp:334
static TApp & Create(void)
Creates the current AppDomain and application instances.
Definition: AppDomain.hpp:256
IApplication & GetApplication(void)
Gets the application instance of the current process.
Definition: AppDomain.hpp:296
static AppDomain & GetCurrent(void)
Gets the current AppDomain instance.
Definition: AppDomain.hpp:244
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:301
TSingleton & GetSingleton(void)
Gets the singleton instance of the specified type.
Definition: AppDomain.hpp:324
static void Assign(AppDomain &other)
Assgins the current AppdDomain singleton from the as argument passed other.
Definition: AppDomain.hpp:281
bool RemoveSingleton(void)
Removes the singleton pointer of the specified type from this AppDomain.
Definition: AppDomain.hpp:352
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:130
static bool IsCreated(void)
Determines if this singleton instance is create yet.
Definition: Singleton.hxx:107
static Instance & CreateInstance(Args &&... args)
Creates this singleton instance.
Definition: Singleton.hxx:93
static Instance & GetInstance(void)
Gets a reference of the singleton instance.
Definition: Singleton.hxx:113
static void AssignInstanceFrom(Instance &other)
Assigns the singleton instance from another singleton instance of the same type.
Definition: Singleton.hxx:146
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
This is the namespace of the Application Component Framework.
Definition: ComponentBase.hpp:13
@ System
System components used by the System, Device, Plc or Io domains.
Root namespace for the PLCnext API