PLCnext API Documentation  22.9.0.33
AppDomain.hpp
1 //
3 // Copyright PHOENIX CONTACT Electronics GmbH
4 //
6 #pragma once
7 #include "Arp/System/Core/Arp.h"
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
22 namespace Arp { namespace System { namespace Acf
23 {
24 class IApplication;
25 }}} // end of namesapce Arp::System::Acf
26 
27 namespace Arp
28 {
29 
30 using namespace Arp::System::Acf;
31 
32 
34 
35 #ifdef ARP_PLATFORM_LINUX
36 class RdLockGuard // TODO(OR): replace this by std::lock or move it to namespace Arp::Internal of Core
37 {
38 public: // 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 
54 private: // fields
55  pthread_rwlock_t* rw_lock;
56 };
57 
59 // inline methods of class Mutex
60 
61 inline RdLockGuard::RdLockGuard(pthread_rwlock_t* rw_lockArg)
62  : rw_lock(rw_lockArg)
63 {
64  pthread_rwlock_rdlock(rw_lock);
65 }
66 
67 inline RdLockGuard::~RdLockGuard()
68 {
69  pthread_rwlock_unlock(rw_lock);
70 }
71 
72 
73 class WrLockGuard
74 {
75 public: // 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 
91 private: // fields
92  pthread_rwlock_t* rw_lock;
93 };
94 
96 // inline methods of class WrLockGuard
97 
98 inline WrLockGuard::WrLockGuard(pthread_rwlock_t* rw_lockArg)
99  : rw_lock(rw_lockArg)
100 {
101  pthread_rwlock_wrlock(rw_lock);
102 }
103 
104 inline WrLockGuard::~WrLockGuard()
105 {
106  pthread_rwlock_unlock(rw_lock);
107 }
108 #endif //ARP_PLATFORM_LINUX
110 
121 class AppDomain : private Singleton<AppDomain>
122 {
123  friend class Singleton<AppDomain>;
124 
125 private: // typedefs
126  typedef void(*SingletonDisposer)(void);
128  typedef std::type_index TypeKey;
129  typedef std::map<TypeKey, void*> Singletons;
130 
131 private: // construction/destruction
133  AppDomain(void);
135  AppDomain(const AppDomain& arg) = delete;
137  ~AppDomain(void);
138 
139 public: // static getter
142  static bool IsCreated(void);
143 
146  static AppDomain& GetCurrent(void);
147 
148 public: // static operations
152  template<class TApp>
153  static TApp& Create(void);
154 
159  template<class TApp>
160  static TApp& Create(const String& appName);
161 
164  template<class TApp>
165  static void Dispose(void);
166 
170  static void Assign(AppDomain& other);
171 
172 public: // getter operations
175  IApplication& GetApplication(void);
176 
177 public: // singleton operations
181  template<class TSingleton>
182  void AddSingleton(TSingleton* pSingleton);
183 
187  template<class TSingleton>
188  TSingleton& GetSingleton(void);
189 
193  template<class TSingleton>
194  TSingleton* GetSingletonPtr(void);
195 
199  template<class TSingleton>
200  bool RemoveSingleton(void);
201 
202 private: // static methods
203  template<class T>
204  static TypeKey GetTypeKey(void);
205 
206 private: // fields
207  IApplication* pApplication;
208  Singletons singletons;
209 
210 #ifdef ARP_PLATFORM_LINUX
211  pthread_rwlock_t rw_lock;
212 #else
213  std::mutex rw_lock;
214 #endif
215 };
216 
218 // inline methods of class AppDomain
219 inline AppDomain::AppDomain()
220  : pApplication(nullptr)
221  , singletons()
222 {
223 #ifdef ARP_PLATFORM_LINUX
224  pthread_rwlock_init(&this->rw_lock, NULL);
225 #endif
226 }
227 
228 inline bool AppDomain::IsCreated(void)
229 {
230  return SingletonBase::IsCreated();
231 }
232 
234 {
236 }
237 
238 template<class T>
239 inline AppDomain::TypeKey AppDomain::GetTypeKey(void)
240 {
241  return std::type_index(typeid(T));
242 }
243 
244 template<class TApp>
245 inline TApp& AppDomain::Create(void)
246 {
247  // create this appDomain instance first
249  // create app singleton next
250  TApp::CreateInstance();
251  // and get the app instance
252  SingletonBase::GetInstance().pApplication = TApp::GetInstancePtr();
253  // return just created app
254  return dynamic_cast<TApp&>(TApp::GetInstance());
255 }
256 
257 template<class TApp>
258 inline TApp& AppDomain::Create(const String& appName)
259 {
260  // create this appDomain instance first
262  // create app singleton next
263  TApp::CreateInstance(appName);
264  // and get the app instance
265  SingletonBase::GetInstance().pApplication = TApp::GetInstancePtr();
266  // return just created app
267  return dynamic_cast<TApp&>(TApp::GetInstance());
268 }
269 
270 inline void AppDomain::Assign(AppDomain& other)
271 {
273  {
275  }
276 }
277 
278 template<class TApp>
279 inline void AppDomain::Dispose(void)
280 {
281  TApp::DisposeInstance();
283 }
284 
286 {
287  return *(this->pApplication);
288 }
289 
290 template<class TSingleton>
291 inline void AppDomain::AddSingleton(TSingleton* pSingleton)
292 {
293 #ifdef ARP_PLATFORM_LINUX
294  WrLockGuard lock(&this->rw_lock);
295 #else
296  std::lock_guard<std::mutex> lock(this->rw_lock);
297 #endif
298 
299 
300  auto result = this->singletons.insert(make_pair(AppDomain::GetTypeKey<TSingleton>(), pSingleton));
301  if (!result.second)
302  {
303  throw Exception("AppDomain Singleton of type '{0}' has been added yet", TypeName<TSingleton>().Value);
304  }
305 }
306 
307 template<class TSingleton>
308 inline TSingleton& AppDomain::GetSingleton()
309 {
310  TSingleton* pResult = this->GetSingletonPtr<TSingleton>();
311  if (pResult == nullptr)
312  {
313  throw Exception("AppDomain does not contain Singleton of type '{0}'", TypeName<TSingleton>().Value);
314  }
315  return *pResult;
316 }
317 template<class TSingleton>
318 inline TSingleton* AppDomain::GetSingletonPtr()
319 {
320 #ifdef ARP_PLATFORM_LINUX
321  RdLockGuard lock(&this->rw_lock);
322 #else
323  std::lock_guard<std::mutex> lock(this->rw_lock);
324 #endif
325 
326  auto i = this->singletons.find(AppDomain::GetTypeKey<TSingleton>());
327  if (i == this->singletons.end())
328  {
329  return nullptr;
330  }
331  // else
332  return (TSingleton*)(i->second); // is there any other way than a brute force cast?
333 }
334 
335 template<class TSingleton>
337 {
338 #ifdef ARP_PLATFORM_LINUX
339  WrLockGuard lock(&this->rw_lock);
340 #else
341  std::lock_guard<std::mutex> lock(this->rw_lock);
342 #endif
343 
344  return this->singletons.erase(AppDomain::GetTypeKey<TSingleton>()) != 0;
345 }
346 
347 } // 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:291
static bool IsCreated(void)
Determines if the appdomain was created yet.
Definition: AppDomain.hpp:228
static void Dispose(void)
Disposes the current AppDomain and destructs the application.
Definition: AppDomain.hpp:279
TSingleton * GetSingletonPtr(void)
Gets the singleton pointer of the specified type.
Definition: AppDomain.hpp:318
static TApp & Create(void)
Creates the current AppDomain and application instances.
Definition: AppDomain.hpp:245
IApplication & GetApplication(void)
Gets the application instance of the current process.
Definition: AppDomain.hpp:285
static AppDomain & GetCurrent(void)
Gets the current AppDomain instance.
Definition: AppDomain.hpp:233
TSingleton & GetSingleton(void)
Gets the singleton instance of the specified type.
Definition: AppDomain.hpp:308
static void Assign(AppDomain &other)
Assgins the current AppdDomain singleton from the as argument passed other.
Definition: AppDomain.hpp:270
bool RemoveSingleton(void)
Removes the singleton pointer of the specified type from this AppDomain.
Definition: AppDomain.hpp:336
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:56
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