Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
depend.hpp
Go to the documentation of this file.
1/*
2 DEPEND.hpp - access point to singletons and dependencies
3
4 Copyright (C)
5 2013, Hermann Vosseler <Ichthyostega@web.de>
6 2018, Hermann Vosseler <Ichthyostega@web.de>
7
8  **Lumiera** is free software; you can redistribute it and/or modify it
9  under the terms of the GNU General Public License as published by the
10  Free Software Foundation; either version 2 of the License, or (at your
11  option) any later version. See the file COPYING for further details.
12
13*/
14
15
93#ifndef LIB_DEPEND_H
94#define LIB_DEPEND_H
95
96
97#include "lib/error.hpp"
98#include "lib/nocopy.hpp"
99#include "lib/nobug-init.hpp"
100#include "lib/sync-classlock.hpp"
101#include "lib/zombie-check.hpp"
102#include "lib/meta/util.hpp"
103
104#include <type_traits>
105#include <functional>
106#include <atomic>
107#include <memory>
108
109
110namespace lib {
111 namespace error = lumiera::error;
112
113
124 template<class OBJ>
127 {
128 using Creator = std::function<OBJ*()>;
129 using Deleter = std::function<void()>;
130
133
134 public:
135 ZombieCheck zombieCheck{util::typeStr<OBJ>()};
136
137 DependencyFactory() = default;
139 {
140 if (deleter_)
141 deleter_();
142 }
143
144 OBJ*
146 {
147 return creator_? creator_()
148 : buildAndManage();
149 }
150
151 template<typename FUN>
152 void
153 defineCreator (FUN&& ctor)
154 {
155 creator_ = std::forward<FUN> (ctor);
156 }
157
158 template<typename FUN>
159 void
161 {
162 creator_ = [this,ctor]
163 {
164 OBJ* obj = ctor();
165 atDestruction ([obj]{ delete obj; });
166 return obj;
167 };
168 }
169
170 void
172 {
173 creator_ = []() -> OBJ*
174 {
175 throw error::Fatal("Service not available at this point of the Application Lifecycle"
176 ,LERR_(LIFECYCLE));
177 };
178 }
179
180 template<typename FUN>
181 void
182 atDestruction (FUN&& additionalAction)
183 {
184 if (deleter_)
185 {
186 Deleter oldDeleter{std::move (deleter_)};
187 deleter_ = [oldDeleter, additionalAction]
188 {
189 oldDeleter();
190 additionalAction();
191 };
192 }
193 else
194 deleter_ = std::forward<FUN> (additionalAction);
195 }
196
197 void
199 {
200 creator_ = std::move (source.creator_);
201 deleter_ = std::move (source.deleter_);
202 source.creator_ = Creator();
203 source.deleter_ = Deleter(); // clear possible leftover deleter
204 }
205
206 private:
207 OBJ*
209 {
210 OBJ* obj = buildInstance<OBJ>();
211 atDestruction ([obj]{ delete obj; });
212 return obj;
213 }
214
215 // try to instantiate the default ctor
216 template<class X, typename = decltype(X())>
217 static std::true_type __try_instantiate(int);
218 template<class>
219 static std::false_type __try_instantiate(...);
220
225 template<typename X>
227 : decltype(__try_instantiate<X>(0))
228 { };
229
230
231 template<class TAR>
233 TAR* >
235 {
236 return new TAR;
237 }
238
239 template<class ABS>
241 ABS* >
243 {
244 throw error::Fatal("Attempt to create a singleton instance of an abstract class. "
245 "Application architecture or lifecycle is seriously broken.");
246 }
247 template<class ABS>
248 static meta::disable_if<std::__or_<std::is_abstract<ABS>,canDefaultConstruct<ABS>>,
249 ABS* >
251 {
252 throw error::Fatal("Desired singleton class is not default constructible. "
253 "Application architecture or lifecycle is seriously broken.");
254 }
255 };
256
257
258
263 template<class SRV>
264 class DependInject;
265
266
279 template<class SRV>
280 class Depend
281 {
282 using Instance = std::atomic<SRV*>;
285
288
289 static Factory&
291 {
292 static Factory sharedFactory;
293 return sharedFactory;
294 }
295
296 friend class DependInject<SRV>;
297
298
299 public:
306 SRV&
308 {
309 SRV* object = instance.load (std::memory_order_acquire);
310 if (!object)
311 {
312 factory().zombieCheck();
313 Lock guard;
314
315 object = instance.load (std::memory_order_relaxed);
316 if (!object)
317 {
318 object = factory().buildTarget();
319 factory().disable();
320 factory().atDestruction([]{ instance = nullptr; });
321 }
322 instance.store (object, std::memory_order_release);
323 }
324 ENSURE (object);
325 return *object;
326 }
327
328
333 explicit
334 operator bool() const
335 {
336 return instance.load (std::memory_order_acquire);
337 }
338
343 {
344 factory().zombieCheck();
345 }
346 };
347
348
349
350
351 /* === allocate Storage for static per type instance management === */
352 template<class SRV>
353 std::atomic<SRV*> Depend<SRV>::instance;
354
355
356
357} // namespace lib
358#endif /*LIB_DEPEND_H*/
A synchronisation protection guard employing a lock scoped to the parameter type as a whole,...
This framework allows to (re)configure the lib::Depend front-end for dependency-injection.
Access point to singletons and other kinds of dependencies designated by type.
Definition depend.hpp:281
SRV & operator()()
Interface to be used by clients for retrieving the service instance.
Definition depend.hpp:307
static Instance instance
shared per type
Definition depend.hpp:287
ClassLock< SRV, NonrecursiveLock_NoWait > Lock
Definition depend.hpp:284
std::atomic< SRV * > Instance
Definition depend.hpp:282
DependencyFactory< SRV > Factory
Definition depend.hpp:283
static Factory & factory()
Definition depend.hpp:290
Helper to abstract creation and lifecycle of a dependency.
Definition depend.hpp:127
void transferDefinition(DependencyFactory &&source)
Definition depend.hpp:198
static std::true_type __try_instantiate(int)
std::function< void()> Deleter
Definition depend.hpp:129
ZombieCheck zombieCheck
Definition depend.hpp:135
std::function< OBJ *()> Creator
Definition depend.hpp:128
static meta::disable_if< std::__or_< std::is_abstract< ABS >, canDefaultConstruct< ABS > >, ABS * > buildInstance()
Definition depend.hpp:250
void atDestruction(FUN &&additionalAction)
Definition depend.hpp:182
static std::false_type __try_instantiate(...)
void defineCreator(FUN &&ctor)
Definition depend.hpp:153
void defineCreatorAndManage(FUN &&ctor)
Definition depend.hpp:160
static meta::enable_if< canDefaultConstruct< TAR >, TAR * > buildInstance()
Definition depend.hpp:234
static meta::enable_if< std::is_abstract< ABS >, ABS * > buildInstance()
Definition depend.hpp:242
Automatic lifecycle tracker, to produce an alarm when accessing objects after deletion.
Any copy and copy construction prohibited.
Definition nocopy.hpp:38
Lumiera error handling (C++ interface).
#define LERR_(_NAME_)
Definition error.hpp:45
Simple and lightweight helpers for metaprogramming and type detection.
enable_if_c< Cond::value, T >::type enable_if
SFINAE helper to control the visibility of specialisations and overloads.
Definition meta/util.hpp:87
Implementation namespace for support and library code.
LumieraError< LERR_(FATAL), Logic > Fatal
Definition error.hpp:208
Trigger the basic NoBug initialisation by placing a static variable.
Mix-Ins to allow or prohibit various degrees of copying and cloning.
metafunction: can we instantiate the desired object here?
Definition depend.hpp:228
A special implementation of lib::Sync, where the storage of the object monitor is associated directly...
Detector to set off alarm when (re)using deceased objects.