PLCnext API Documentation  21.0.0.35466
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 std;
31 using namespace Arp::System::Acf;
32 
33 
35 
36 #ifdef ARP_PLATFORM_LINUX
37 class RdLockGuard // TODO(OR): replace this by std::lock or move it to namespace Arp::Internal of Core
38 {
39 public: // construction/destruction
40 
44  RdLockGuard(pthread_rwlock_t* rw_lock);
45 
47  RdLockGuard(const RdLockGuard& arg) = delete;
48 
50  RdLockGuard& operator=(const RdLockGuard& arg) = delete;
51 
53  ~RdLockGuard(void);
54 
55 private: // fields
56  pthread_rwlock_t* rw_lock;
57 };
58 
60 // inline methods of class Mutex
61 
62 inline RdLockGuard::RdLockGuard(pthread_rwlock_t* rw_lockArg)
63  : rw_lock(rw_lockArg)
64 {
65  pthread_rwlock_rdlock(rw_lock);
66 }
67 
68 inline RdLockGuard::~RdLockGuard()
69 {
70  pthread_rwlock_unlock(rw_lock);
71 }
72 
73 
74 class WrLockGuard
75 {
76 public: // construction/destruction
77 
81  WrLockGuard(pthread_rwlock_t* rw_lock);
82 
84  WrLockGuard(const WrLockGuard& arg) = delete;
85 
87  WrLockGuard& operator=(const WrLockGuard& arg) = delete;
88 
90  ~WrLockGuard(void);
91 
92 private: // fields
93  pthread_rwlock_t* rw_lock;
94 };
95 
97 // inline methods of class WrLockGuard
98 
99 inline WrLockGuard::WrLockGuard(pthread_rwlock_t* rw_lockArg)
100  : rw_lock(rw_lockArg)
101 {
102  pthread_rwlock_wrlock(rw_lock);
103 }
104 
105 inline WrLockGuard::~WrLockGuard()
106 {
107  pthread_rwlock_unlock(rw_lock);
108 }
109 #endif //ARP_PLATFORM_LINUX
110 
122 class AppDomain : private Singleton<AppDomain>
123 {
124  friend class Singleton<AppDomain>;
125 
126 private: // typedefs
127  typedef void(*SingletonDisposer)(void);
129  typedef std::type_index TypeKey;
130  typedef std::map<TypeKey, void*> Singletons;
131 
132 private: // construction/destruction
134  AppDomain(void);
136  AppDomain(const AppDomain& arg) = delete;
138  ~AppDomain(void);
139 
140 public: // static getter
143  static bool IsCreated(void);
144 
147  static AppDomain& GetCurrent(void);
148 
149 public: // 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 
173 public: // getter operations
176  IApplication& GetApplication(void);
177 
178 public: // singleton operations
182  template<class TSingleton>
183  void AddSingleton(TSingleton* pSingleton);
184 
188  template<class TSingleton>
189  TSingleton& GetSingleton(void);
190 
194  template<class TSingleton>
195  TSingleton* GetSingletonPtr(void);
196 
200  template<class TSingleton>
201  bool RemoveSingleton(void);
202 
203 private: // static methods
204  template<class T>
205  static TypeKey GetTypeKey(void);
206 
207 private: // fields
208  IApplication* pApplication;
209  Singletons singletons;
210 
211 #ifdef ARP_PLATFORM_LINUX
212  pthread_rwlock_t rw_lock;
213 #else
214  std::mutex rw_lock;
215 #endif
216 };
217 
219 // inline methods of class AppDomain
220 inline AppDomain::AppDomain()
221  : pApplication(nullptr)
222  , singletons()
223 {
224 #ifdef ARP_PLATFORM_LINUX
225  pthread_rwlock_init(&this->rw_lock, NULL);
226 #endif
227 }
228 
229 inline bool AppDomain::IsCreated(void)
230 {
231  return SingletonBase::IsCreated();
232 }
233 
235 {
236  return SingletonBase::GetInstance();
237 }
238 
239 template<class T>
240 inline AppDomain::TypeKey AppDomain::GetTypeKey(void)
241 {
242  return std::type_index(typeid(T));
243 }
244 
245 template<class TApp>
246 inline TApp& AppDomain::Create(void)
247 {
248  // create this appDomain instance first
249  SingletonBase::CreateInstance();
250  // create app singleton next
251  TApp::CreateInstance();
252  // and get the app instance
253  SingletonBase::GetInstance().pApplication = TApp::GetInstancePtr();
254  // return just created app
255  return dynamic_cast<TApp&>(TApp::GetInstance());
256 }
257 
258 template<class TApp>
259 inline TApp& AppDomain::Create(const String& appName)
260 {
261  // create this appDomain instance first
262  SingletonBase::CreateInstance();
263  // create app singleton next
264  TApp::CreateInstance(appName);
265  // and get the app instance
266  SingletonBase::GetInstance().pApplication = TApp::GetInstancePtr();
267  // return just created app
268  return dynamic_cast<TApp&>(TApp::GetInstance());
269 }
270 
271 inline void AppDomain::Assign(AppDomain& other)
272 {
273  if (!SingletonBase::IsCreated())
274  {
275  SingletonBase::AssignInstanceFrom(other);
276  }
277 }
278 
279 template<class TApp>
280 inline void AppDomain::Dispose(void)
281 {
282  TApp::DisposeInstance();
283  SingletonBase::DisposeInstance();
284 }
285 
287 {
288  return *(this->pApplication);
289 }
290 
291 template<class TSingleton>
292 inline void AppDomain::AddSingleton(TSingleton* pSingleton)
293 {
294 #ifdef ARP_PLATFORM_LINUX
295  WrLockGuard lock(&this->rw_lock);
296 #else
297  std::lock_guard<std::mutex> lock(this->rw_lock);
298 #endif
299 
300 
301  auto result = this->singletons.insert(make_pair(AppDomain::GetTypeKey<TSingleton>(), pSingleton));
302  if (!result.second)
303  {
304  throw Exception("AppDomain Singleton of type '{0}' has been added yet", TypeName<TSingleton>().Value);
305  }
306 }
307 
308 template<class TSingleton>
309 inline TSingleton& AppDomain::GetSingleton()
310 {
311  TSingleton* pResult = this->GetSingletonPtr<TSingleton>();
312  if (pResult == nullptr)
313  {
314  throw Exception("AppDomain does not contain Singleton of type '{0}'", TypeName<TSingleton>().Value);
315  }
316  return *pResult;
317 }
318 template<class TSingleton>
319 inline TSingleton* AppDomain::GetSingletonPtr()
320 {
321 #ifdef ARP_PLATFORM_LINUX
322  RdLockGuard lock(&this->rw_lock);
323 #else
324  std::lock_guard<std::mutex> lock(this->rw_lock);
325 #endif
326 
327  auto i = this->singletons.find(AppDomain::GetTypeKey<TSingleton>());
328  if (i == this->singletons.end())
329  {
330  return nullptr;
331  }
332  // else
333  return (TSingleton*)(i->second); // is there any other way than a brute force cast?
334 }
335 
336 template<class TSingleton>
338 {
339 #ifdef ARP_PLATFORM_LINUX
340  WrLockGuard lock(&this->rw_lock);
341 #else
342  std::lock_guard<std::mutex> lock(this->rw_lock);
343 #endif
344 
345  return this->singletons.erase(AppDomain::GetTypeKey<TSingleton>()) != 0;
346 }
347 
348 } // end of namesapce Arp
bool RemoveSingleton(void)
Removes the singleton pointer of the specified type from this AppDomain.
Definition: AppDomain.hpp:337
This (meta programming) class provides the C++ typename of the as template argument passed type...
Definition: TypeName.hxx:55
Namespace of the C++ standard library
static void Assign(AppDomain &other)
Assgins the current AppdDomain singleton from the as argument passed other.
Definition: AppDomain.hpp:271
TSingleton & GetSingleton(void)
Gets the singleton instance of the specified type.
Definition: AppDomain.hpp:309
void AddSingleton(TSingleton *pSingleton)
Adds a singleton instance to this AppDomain.
Definition: AppDomain.hpp:292
This interface shall be implemented by the application class.
Definition: IApplication.hpp:18
This class represents a single application domain for each process and is implemented as singleton...
Definition: AppDomain.hpp:122
This class implements the singleton pattern.
Definition: Singleton.hxx:24
static XmlWriter Create(const String &filename, bool indent, const char *encoding="UTF-8")
Creates a new Instance of the XmlWriter
IApplication & GetApplication(void)
Gets the application instance of the current process.
Definition: AppDomain.hpp:286
Root namespace for the PLCnext API
static bool IsCreated(void)
Determines if the appdomain was created yet.
Definition: AppDomain.hpp:229
TSingleton * GetSingletonPtr(void)
Gets the singleton pointer of the specified type.
Definition: AppDomain.hpp:319
static AppDomain & GetCurrent(void)
Gets the current AppDomain instance.
Definition: AppDomain.hpp:234
static TApp & Create(void)
Creates the current AppDomain and application instances.
Definition: AppDomain.hpp:246
System components used by the System, Device, Plc or Io domains.
This is the base class of all Arp exception classes.
Definition: Exception.hpp:15
This is the namespace of the Application Component Framework.
Definition: ComponentBase.hpp:12
static void Dispose(void)
Disposes the current AppDomain and destructs the application.
Definition: AppDomain.hpp:280