PLCnext API Documentation 25.0.2.69
AppDomain.hpp
1
2//
3// Copyright Phoenix Contact GmbH & Co. KG
4//
6#pragma once
7
8#ifndef ARP_USE_ARP_SYSTEM_CORE
9
10#include "Arp/Base/Core/AppDomain.hpp"
11
12#else
13
14#include "Arp/System/Core/Arp.h"
15#include "Arp/System/Core/Singleton.hxx"
16#include <map>
17#include <stack>
18#include <typeinfo>
19#include <typeindex>
20
21
22#ifdef ARP_PLATFORM_LINUX
23 #include <pthread.h>
24#else
25 #include <mutex>
26#endif
27
28
29// forwards
30namespace Arp { namespace System { namespace Acf
31{
32class IApplication;
33}}} // end of namesapce Arp::System::Acf
34
35namespace Arp
36{
37
39
40#ifdef ARP_PLATFORM_LINUX
41class RdLockGuard
42{
43public: // construction/destruction
44
48 RdLockGuard(pthread_rwlock_t* rw_lock);
49
51 RdLockGuard(const RdLockGuard& arg) = delete;
52
54 RdLockGuard& operator=(const RdLockGuard& arg) = delete;
55
57 ~RdLockGuard(void);
58
59private: // fields
60 pthread_rwlock_t* rw_lock;
61};
62
64// inline methods of class Mutex
65
66inline RdLockGuard::RdLockGuard(pthread_rwlock_t* rw_lockArg)
67 : rw_lock(rw_lockArg)
68{
69 pthread_rwlock_rdlock(rw_lock);
70}
71
72inline RdLockGuard::~RdLockGuard()
73{
74 pthread_rwlock_unlock(rw_lock);
75}
76
77
78class WrLockGuard
79{
80public: // construction/destruction
81
85 WrLockGuard(pthread_rwlock_t* rw_lock);
86
88 WrLockGuard(const WrLockGuard& arg) = delete;
89
91 WrLockGuard& operator=(const WrLockGuard& arg) = delete;
92
94 ~WrLockGuard(void);
95
96private: // fields
97 pthread_rwlock_t* rw_lock;
98};
99
101// inline methods of class WrLockGuard
102
103inline WrLockGuard::WrLockGuard(pthread_rwlock_t* rw_lockArg)
104 : rw_lock(rw_lockArg)
105{
106 pthread_rwlock_wrlock(rw_lock);
107}
108
109inline WrLockGuard::~WrLockGuard()
110{
111 pthread_rwlock_unlock(rw_lock);
112}
113#endif //ARP_PLATFORM_LINUX
115
126class AppDomain : private Singleton<AppDomain>
127{
128 friend class Singleton<AppDomain>;
129
130public: // usings
131 using Strings = std::vector<String>;
132 using IApplication = Arp::System::Acf::IApplication;
133
134private: // usings
135 using SingletonDisposer = void(*)(void);
136 using SingletonBase = Singleton<AppDomain>;
137 using TypeKey = std::type_index;
138 using Singletons = std::map<TypeKey, void*>;
139
140public: // construction/destruction
142 AppDomain(void);
144 AppDomain(const AppDomain& arg) = delete;
146 AppDomain& operator=(const AppDomain& arg) = delete;
148 ~AppDomain(void);
149
150public: // static getter
153 static bool IsCreated(void);
154
157 static AppDomain& GetCurrent(void);
158
159public: // static operations
163 template<class TApp>
164 static TApp& Create(void);
165
170 template<class TApp>
171 static TApp& Create(const String& appName);
172
175 template<class TApp>
176 static void Dispose(void);
177
181 static void Assign(AppDomain& other);
182
183public: // getter operations
186 IApplication& GetApplication(void);
187
190 size_t GetSingletonsCount(void)const;
191
194 Strings GetSingletonsTypeName(void)const;
195
196public: // singleton operations
200 template<class TSingleton>
201 void AddSingleton(TSingleton* pSingleton);
202
206 template<class TSingleton>
207 TSingleton& GetSingleton(void);
208
212 template<class TSingleton>
213 TSingleton* GetSingletonPtr(void);
214
218 template<class TSingleton>
219 bool RemoveSingleton(void);
220
221private: // static methods
222 template<class T>
223 static TypeKey GetTypeKey(void);
224
225private: // fields
226 IApplication* pApplication;
227 Singletons singletons;
228
229#ifdef ARP_PLATFORM_LINUX
230 pthread_rwlock_t rw_lock;
231#else
232 std::mutex rw_lock;
233#endif
234};
235
237// inline methods of class AppDomain
238inline AppDomain::AppDomain()
239 : pApplication(nullptr)
240 , singletons()
241{
242#ifdef ARP_PLATFORM_LINUX
243 pthread_rwlock_init(&this->rw_lock, NULL);
244#endif
245}
246
247inline bool AppDomain::IsCreated(void)
248{
249 return SingletonBase::IsCreated();
250}
251
252inline AppDomain& AppDomain::GetCurrent(void)
253{
254 return SingletonBase::GetInstance();
255}
256
257template<class T>
258inline AppDomain::TypeKey AppDomain::GetTypeKey(void)
259{
260 return std::type_index(typeid(T));
261}
262
263template<class TApp>
264inline TApp& AppDomain::Create(void)
265{
266 // create this appDomain instance first
267 SingletonBase::CreateInstance();
268 // create app singleton next
269 TApp::CreateInstance();
270 // and get the app instance
271 SingletonBase::GetInstance().pApplication = &TApp::GetInstance();
272 // return just created app
273 return dynamic_cast<TApp&>(TApp::GetInstance());
274}
275
276template<class TApp>
277inline TApp& AppDomain::Create(const String& appName)
278{
279 // create this appDomain instance first
280 SingletonBase::CreateInstance();
281 // create app singleton next
282 TApp::CreateInstance(appName);
283 // and get the app instance
284 SingletonBase::GetInstance().pApplication = &TApp::GetInstance();
285 // return just created app
286 return dynamic_cast<TApp&>(TApp::GetInstance());
287}
288
289inline void AppDomain::Assign(AppDomain& other)
290{
291 if (!SingletonBase::IsCreated())
292 {
293 SingletonBase::GetStaticInstancePtr().reset(other.GetStaticInstancePtr().get());
294 }
295}
296
297template<class TApp>
298inline void AppDomain::Dispose(void)
299{
300 TApp::DisposeInstance();
301 SingletonBase::DisposeInstance();
302}
303
304inline AppDomain::IApplication& AppDomain::GetApplication(void)
305{
306 return *(this->pApplication);
307}
308
309inline size_t AppDomain::GetSingletonsCount()const
310{
311 return this->singletons.size();
312}
313
314template<class TSingleton>
315inline void AppDomain::AddSingleton(TSingleton* pSingleton)
316{
317#ifdef ARP_PLATFORM_LINUX
318 WrLockGuard lock(&this->rw_lock);
319#else
320 std::lock_guard<std::mutex> lock(this->rw_lock);
321#endif
322
323
324 auto result = this->singletons.insert(make_pair(AppDomain::GetTypeKey<TSingleton>(), pSingleton));
325 if (!result.second)
326 {
327 throw Exception("AppDomain Singleton of type '{0}' has been added yet", TypeName<TSingleton>());
328 }
329}
330
331template<class TSingleton>
332inline TSingleton& AppDomain::GetSingleton()
333{
334 TSingleton* pResult = this->GetSingletonPtr<TSingleton>();
335 if (pResult == nullptr)
336 {
337 throw Exception("AppDomain does not contain Singleton of type '{0}'", TypeName<TSingleton>().GetFullName());
338 }
339 return *pResult;
340}
341template<class TSingleton>
342inline TSingleton* AppDomain::GetSingletonPtr()
343{
344#ifdef ARP_PLATFORM_LINUX
345 RdLockGuard lock(&this->rw_lock);
346#else
347 std::lock_guard<std::mutex> lock(this->rw_lock);
348#endif
349
350 auto i = this->singletons.find(AppDomain::GetTypeKey<TSingleton>());
351 if (i == this->singletons.end())
352 {
353 return nullptr;
354 }
355 // else
356 return (TSingleton*)(i->second); // is there any other way than a brute force cast?
357}
358
359template<class TSingleton>
360inline bool AppDomain::RemoveSingleton()
361{
362#ifdef ARP_PLATFORM_LINUX
363 WrLockGuard lock(&this->rw_lock);
364#else
365 std::lock_guard<std::mutex> lock(this->rw_lock);
366#endif
367
368 return this->singletons.erase(AppDomain::GetTypeKey<TSingleton>()) != 0;
369}
370
371} // end of namesapce Arp
372
373#endif // ndef ARP_USE_ARP_SYSTEM_CORE
@ Create
Creates a new file. If the file already exists, it is overwritten.
Root namespace for the PLCnext API