From 80207ea22466cd6c1991cd671d14cb89a6f3e14a Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 30 Mar 2018 18:46:13 +0200 Subject: [PATCH] DI: (WIP) switch to totally rewritten new implementation of lib::Depend (#1086) - state-of-the-art implementation of access with Double Checked Locking + Atomics - improved design for configuration of dependencies. Now at the provider, not the consumer - support for exposing services with a lifecycle through the lib::Depend front-end --- research/try.cpp | 2 +- src/lib/depend-inject.hpp | 52 ++++--- src/lib/{depend2.hpp => depend.hpp} | 6 +- tests/core/backend/media-access-mock-test.cpp | 2 +- tests/core/proc/asset/create-asset-test.cpp | 2 +- .../core/proc/asset/dependent-assets-test.cpp | 2 +- .../proc/asset/identity-of-assets-test.cpp | 2 +- tests/core/proc/asset/make-clip-test.cpp | 2 +- .../proc/asset/ordering-of-assets-test.cpp | 2 +- .../mobject/builder/builder-tool-test.cpp | 3 +- .../proc/mobject/mobject-interface-test.cpp | 2 +- tests/core/proc/mobject/mobject-ref-test.cpp | 2 +- .../proc/mobject/placement-hierarchy-test.cpp | 2 +- tests/core/proc/mobject/session/testclip.cpp | 2 +- .../library/dependency-configuration-test.cpp | 2 +- tests/library/dependency-factory-test.cpp | 2 +- tests/library/singleton-subclass-test.cpp | 2 +- tests/library/singleton-test.cpp | 2 +- wiki/thinkPad.ichthyo.mm | 145 +++++++----------- 19 files changed, 105 insertions(+), 131 deletions(-) rename src/lib/{depend2.hpp => depend.hpp} (99%) diff --git a/research/try.cpp b/research/try.cpp index bf49a0c96..f3251cac2 100644 --- a/research/try.cpp +++ b/research/try.cpp @@ -50,7 +50,7 @@ typedef unsigned int uint; #include "lib/format-cout.hpp" -#include "lib/depend2.hpp" +#include "lib/depend.hpp" #include "lib/depend-inject.hpp" //#include "lib/meta/util.hpp" #include "lib/test/test-helper.hpp" diff --git a/src/lib/depend-inject.hpp b/src/lib/depend-inject.hpp index 59def341c..7e3238fcb 100644 --- a/src/lib/depend-inject.hpp +++ b/src/lib/depend-inject.hpp @@ -28,18 +28,18 @@ ** plants an instance of lib::Depend, templated to the actual type of the dependency. ** This is a way to express the dependency on some interface or service, while not ** expanding on any details as to when and how this dependency is created. Without - ** and explicit configuration, lib::Depend will automatically create and manage a + ** an explicit configuration, lib::Depend will automatically create and manage a ** singleton instance of the type given as type parameter. ** ** ## Architecture - ** A _dependency_ is understood as something we need to do the task at hand, yet - ** a dependency lies beyond that task and relates to concerns outside the scope - ** and theme of this actual task. The usage site of the dependency is only bound - ** and coupled to the _interface_ exposed as dependency, and the associated + ** A _dependency_ is understood as something we need to perform the task at hand, + ** yet a dependency referres beyond that task and relates to concerns outside the + ** scope and theme of this actual task. The usage site of the dependency is only + ** bound and coupled to the _interface_ exposed as dependency, and the associated ** _contract_ of a service. Initially, such a dependency is _dormant_ and will - ** be activated on first access. This simplifies the bootstrap of complex + ** be activated on first access. This simplifies the bootstrap of complexly ** interwoven structures; it suffices to ensure that none of the participating - ** entities actually starts to work before all of the setup and wiring is done. + ** entities actually starts its work before all of the setup and wiring is done. ** ** For that reason, lib::DependInject is meant to be used at the site providing ** the _actual_ service or implementation subtype -- not at the site consuming a @@ -56,7 +56,7 @@ ** function, a functor or lambda can be installed into the static factory of lib::Depend. ** Especially, a lambda could be bound into the internal context of the service provider. ** This function is expected to deliver a heap allocated instance on invocation, which - ** will be owned and managed by lib::Depend::singleton (An InstanceHolder). + ** will be owned and managed by lib::Depend::factory (A DependencyFactory). ** ** \paragraph Service Lifecycle ** Whenever a module or subsystem can be started and stopped, several interconnected @@ -117,7 +117,7 @@ #include "lib/error.hpp" #include "lib/nocopy.hpp" -#include "lib/depend2.hpp" +#include "lib/depend.hpp" #include "lib/meta/trait.hpp" #include "lib/meta/function.hpp" #include "lib/sync-classlock.hpp" @@ -139,9 +139,9 @@ namespace lib { /** * This framework allows to (re)configure the lib::Depend front-end for dependency-injection. * By default, `Depend` will create a singleton instance of `TY` lazily, on demand. - * When instantiating one of the configuration handles provided here -- _prior_ to using + * When instantiating one of the configuration handles provided here -- _prior_ to anyone * retrieving the instance through `Depend` -- this default (singleton) behaviour - * can be reconfigured in various ways, without the client being aware of it + * can be reconfigured in various ways, without the client being aware of it: * - instead of a singleton, a service instance with well defined lifecycle can be * exposed through the `Depend` front-end. When the service is shut down, * clients will receive an exception on access. @@ -150,6 +150,7 @@ namespace lib { * singleton type, which still happens lazily, on demand * - the current state and configuration can be shadowed temporarily by a test mock instance, * which is managed automatically and removed when leaving the scope of the test. + * @note DependInject is declared fried by Depend to reconfigure the latter's internals */ template class DependInject @@ -159,7 +160,7 @@ namespace lib { using Lock = typename Depend::Lock; public: - /** configure dependency-injection for type SRV to build a subclass singleton + /** configure dependency-injection for type SRV to build a subclass singleton. * @note actually a delegation to `Depend` is installed into `Depend` * @tparam SUB concrete subclass type to build on demand when invoking `Depend` * @throws error::Logic (LUMIERA_ERROR_LIFECYCLE) when the default factory has already @@ -174,19 +175,19 @@ namespace lib { } /** configure dependency-injection for type SRV to manage a subclass singleton, - * which is created lazily on demand by invoking the given builder function + * which is created lazily on demand by invoking the given builder function. * @note actual Subclass type is determined from the given functor and then * a delegation to `Depend` is installed into `Depend` - * @param ctor functor to create a heap allocated instance of subclass + * @param ctor functor to create a heap allocated instance of the subclass * @throws error::Logic (LUMIERA_ERROR_LIFECYCLE) when the default factory has already * been invoked at the point when calling this (re)configuration function. */ template static void - useSingleton(FUN&& ctor) + useSingleton (FUN&& ctor) { - using Fun = typename SubclassFactoryType::Fun; - using Sub = typename SubclassFactoryType::Sub; + using Sub = typename SubclassFactoryType::Subclass; + using Fun = typename SubclassFactoryType::Functor; __assert_compatible(); installFactory (forward (ctor)); @@ -214,7 +215,7 @@ namespace lib { public: template ServiceInstance(ARGS&& ...ctorArgs) - : instance_(new IMP(forward (ctorArgs)...)) + : instance_{new IMP(forward (ctorArgs)...)} { __assert_compatible(); activateServiceAccess (*instance_); @@ -239,7 +240,7 @@ namespace lib { } IMP* - operator-> () const + operator->() const { ENSURE (instance_); return instance_.get(); @@ -274,7 +275,7 @@ namespace lib { Local (FUN&& buildInstance) { __assert_compatible(); - __assert_compatible::Sub>(); + __assert_compatible::Subclass>(); temporarilyInstallAlternateFactory (origInstance_, origFactory_ ,[=]() @@ -341,11 +342,11 @@ namespace lib { static_assert (meta::_Fun(), "Need a Lambda or Function object to create a heap allocated instance"); - using Fun = typename meta::_Fun::Functor; // suitable type to store for later invocation - using Res = typename meta::_Fun::Ret; - using Sub = typename meta::Strip::TypePlain; + using Functor = typename meta::_Fun::Functor; // suitable type to store for later invocation + using ResultVal = typename meta::_Fun::Ret; + using Subclass = typename meta::Strip::TypePlain; - static_assert (std::is_pointer::value, + static_assert (std::is_pointer::value, "Function must yield a pointer to a heap allocated instance"); }; @@ -378,6 +379,7 @@ namespace lib { __ensure_pristine(); Depend::factory.defineCreator ([]{ return & Depend{}(); }); } + // note: we do not install an actual factory; rather we use the default for SUB } @@ -424,4 +426,4 @@ namespace lib { } // namespace lib -#endif +#endif /*LIB_DEPEND_INJECT_H*/ diff --git a/src/lib/depend2.hpp b/src/lib/depend.hpp similarity index 99% rename from src/lib/depend2.hpp rename to src/lib/depend.hpp index b171ca4b4..ece8c3d00 100644 --- a/src/lib/depend2.hpp +++ b/src/lib/depend.hpp @@ -85,8 +85,8 @@ */ -#ifndef WIP_LIB_DEPEND_H -#define WIP_LIB_DEPEND_H +#ifndef LIB_DEPEND_H +#define LIB_DEPEND_H #include "lib/error.hpp" @@ -324,4 +324,4 @@ namespace lib { } // namespace lib -#endif +#endif /*LIB_DEPEND_H*/ diff --git a/tests/core/backend/media-access-mock-test.cpp b/tests/core/backend/media-access-mock-test.cpp index 6d4113bb8..707d865cb 100644 --- a/tests/core/backend/media-access-mock-test.cpp +++ b/tests/core/backend/media-access-mock-test.cpp @@ -27,7 +27,7 @@ #include "backend/media-access-facade.hpp" #include "backend/media-access-mock.hpp" -#include "lib/test/depend-4test.hpp" +#include "lib/depend-inject.hpp" #include "lib/format-cout.hpp" #include "lib/test/run.hpp" diff --git a/tests/core/proc/asset/create-asset-test.cpp b/tests/core/proc/asset/create-asset-test.cpp index 100530366..df6c30e00 100644 --- a/tests/core/proc/asset/create-asset-test.cpp +++ b/tests/core/proc/asset/create-asset-test.cpp @@ -35,7 +35,7 @@ #include "proc/asset/asset-diagnostics.hpp" #include "backend/media-access-mock.hpp" -#include "lib/test/depend-4test.hpp" +#include "lib/depend-inject.hpp" using lib::test::Depend4Test; using util::isnil; diff --git a/tests/core/proc/asset/dependent-assets-test.cpp b/tests/core/proc/asset/dependent-assets-test.cpp index 6d5eb8077..a132fb2c5 100644 --- a/tests/core/proc/asset/dependent-assets-test.cpp +++ b/tests/core/proc/asset/dependent-assets-test.cpp @@ -29,7 +29,7 @@ #include "proc/asset/testasset.hpp" #include "proc/asset/asset-diagnostics.hpp" #include "backend/media-access-mock.hpp" -#include "lib/test/depend-4test.hpp" +#include "lib/depend-inject.hpp" #include "proc/asset/media.hpp" #include "proc/asset/clip.hpp" #include "lib/util.hpp" diff --git a/tests/core/proc/asset/identity-of-assets-test.cpp b/tests/core/proc/asset/identity-of-assets-test.cpp index 3ba2119a1..69dd322d2 100644 --- a/tests/core/proc/asset/identity-of-assets-test.cpp +++ b/tests/core/proc/asset/identity-of-assets-test.cpp @@ -35,7 +35,7 @@ #include "proc/asset/asset-diagnostics.hpp" #include "backend/media-access-mock.hpp" -#include "lib/test/depend-4test.hpp" +#include "lib/depend-inject.hpp" using lib::test::Depend4Test; using util::isnil; diff --git a/tests/core/proc/asset/make-clip-test.cpp b/tests/core/proc/asset/make-clip-test.cpp index d298c39d4..a9a0644e7 100644 --- a/tests/core/proc/asset/make-clip-test.cpp +++ b/tests/core/proc/asset/make-clip-test.cpp @@ -35,7 +35,7 @@ #include "proc/mobject/session/clip.hpp" #include "proc/asset/asset-diagnostics.hpp" #include "backend/media-access-mock.hpp" -#include "lib/test/depend-4test.hpp" +#include "lib/depend-inject.hpp" using lib::test::Depend4Test; using util::contains; diff --git a/tests/core/proc/asset/ordering-of-assets-test.cpp b/tests/core/proc/asset/ordering-of-assets-test.cpp index 22677093c..042d579b1 100644 --- a/tests/core/proc/asset/ordering-of-assets-test.cpp +++ b/tests/core/proc/asset/ordering-of-assets-test.cpp @@ -34,7 +34,7 @@ #include "proc/asset/asset-diagnostics.hpp" #include "backend/media-access-mock.hpp" -#include "lib/test/depend-4test.hpp" +#include "lib/depend-inject.hpp" using lib::test::Depend4Test; using util::isnil; diff --git a/tests/core/proc/mobject/builder/builder-tool-test.cpp b/tests/core/proc/mobject/builder/builder-tool-test.cpp index ded2de8dd..a7bb23071 100644 --- a/tests/core/proc/mobject/builder/builder-tool-test.cpp +++ b/tests/core/proc/mobject/builder/builder-tool-test.cpp @@ -34,13 +34,12 @@ #include "proc/mobject/session/clip.hpp" #include "proc/mobject/test-dummy-mobject.hpp" #include "backend/media-access-mock.hpp" -#include "lib/test/depend-4test.hpp" +#include "lib/depend-inject.hpp" #include "lib/format-cout.hpp" #include "lib/util.hpp" using util::cStr; using std::string; -using std::cout; diff --git a/tests/core/proc/mobject/mobject-interface-test.cpp b/tests/core/proc/mobject/mobject-interface-test.cpp index 698db1e7f..eab0deb4b 100644 --- a/tests/core/proc/mobject/mobject-interface-test.cpp +++ b/tests/core/proc/mobject/mobject-interface-test.cpp @@ -40,7 +40,7 @@ //#include "proc/mobject/explicitplacement.hpp" #include "proc/mobject/test-dummy-mobject.hpp" #include "backend/media-access-mock.hpp" -#include "lib/test/depend-4test.hpp" +#include "lib/depend-inject.hpp" #include "lib/time/timevalue.hpp" #include "lib/format-cout.hpp" diff --git a/tests/core/proc/mobject/mobject-ref-test.cpp b/tests/core/proc/mobject/mobject-ref-test.cpp index 364d01e8e..6014bb107 100644 --- a/tests/core/proc/mobject/mobject-ref-test.cpp +++ b/tests/core/proc/mobject/mobject-ref-test.cpp @@ -37,7 +37,7 @@ #include "proc/mobject/explicitplacement.hpp" #include "proc/mobject/test-dummy-mobject.hpp" #include "backend/media-access-mock.hpp" -#include "lib/test/depend-4test.hpp" +#include "lib/depend-inject.hpp" #include "lib/test/test-helper.hpp" #include "lib/time/timevalue.hpp" #include "lib/format-cout.hpp" diff --git a/tests/core/proc/mobject/placement-hierarchy-test.cpp b/tests/core/proc/mobject/placement-hierarchy-test.cpp index a04d266a9..654238d0e 100644 --- a/tests/core/proc/mobject/placement-hierarchy-test.cpp +++ b/tests/core/proc/mobject/placement-hierarchy-test.cpp @@ -27,7 +27,7 @@ #include "lib/test/run.hpp" #include "lib/test/test-helper.hpp" -#include "lib/test/depend-4test.hpp" +#include "lib/depend-inject.hpp" #include "backend/media-access-mock.hpp" #include "proc/mobject/test-dummy-mobject.hpp" #include "proc/mobject/session/clip.hpp" diff --git a/tests/core/proc/mobject/session/testclip.cpp b/tests/core/proc/mobject/session/testclip.cpp index 9edd7df3f..f6a06f592 100644 --- a/tests/core/proc/mobject/session/testclip.cpp +++ b/tests/core/proc/mobject/session/testclip.cpp @@ -28,7 +28,7 @@ #include "proc/mobject/session/testclip.hpp" #include "backend/media-access-facade.hpp" #include "backend/media-access-mock.hpp" -#include "lib/test/depend-4test.hpp" +#include "lib/depend-inject.hpp" #include "proc/asset/media.hpp" #include "proc/asset/clip.hpp" #include "lib/depend.hpp" diff --git a/tests/library/dependency-configuration-test.cpp b/tests/library/dependency-configuration-test.cpp index 897122626..12d595f2a 100644 --- a/tests/library/dependency-configuration-test.cpp +++ b/tests/library/dependency-configuration-test.cpp @@ -34,7 +34,7 @@ #include "lib/test/test-helper.hpp" #include "lib/util.hpp" -#include "lib/depend2.hpp" +#include "lib/depend.hpp" #include "lib/depend-inject.hpp" diff --git a/tests/library/dependency-factory-test.cpp b/tests/library/dependency-factory-test.cpp index f0679b6bf..3ac29aa6c 100644 --- a/tests/library/dependency-factory-test.cpp +++ b/tests/library/dependency-factory-test.cpp @@ -33,7 +33,7 @@ #include "lib/format-obj.hpp" #include "lib/util.hpp" -#include "lib/depend2.hpp" +#include "lib/depend.hpp" #include "lib/depend-inject.hpp" #include "test-target-obj.hpp" diff --git a/tests/library/singleton-subclass-test.cpp b/tests/library/singleton-subclass-test.cpp index 04634edf6..bb4afa389 100644 --- a/tests/library/singleton-subclass-test.cpp +++ b/tests/library/singleton-subclass-test.cpp @@ -32,7 +32,7 @@ #include "lib/util.hpp" #include "test-target-obj.hpp" -#include "lib/depend2.hpp" +#include "lib/depend.hpp" #include "lib/depend-inject.hpp" #include diff --git a/tests/library/singleton-test.cpp b/tests/library/singleton-test.cpp index 519060060..bee1e11d5 100644 --- a/tests/library/singleton-test.cpp +++ b/tests/library/singleton-test.cpp @@ -31,7 +31,7 @@ #include "lib/util.hpp" #include "test-target-obj.hpp" -#include "lib/depend2.hpp" +#include "lib/depend.hpp" #include diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index dcda9c6f1..07d2d7f13 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -26507,8 +26507,7 @@ - - + @@ -26527,8 +26526,7 @@ habe einen usleep(1000) getimed

- - +
@@ -26561,8 +26559,7 @@ Außerdem ist ja auch noch der Aufruf des Funktors mit im Spiel, wenngleich der auch typischerweise geinlined wird

- - + @@ -26583,8 +26580,7 @@ volatile Variable außen, im Aufrufkontext

- - +
@@ -26603,8 +26599,7 @@ daß x86_64 tatsächlich cache-kohärent ist

- - +
@@ -26869,15 +26864,25 @@ - + - - - + + + + + + + + + + + + + @@ -27433,8 +27438,7 @@ Thema: Memory access order constraints

- - + @@ -27449,8 +27453,7 @@ Grundidee: synchronizes-with-Beziehung herstellen auf Guard-Variable

- - +
@@ -27474,8 +27477,7 @@ - - + @@ -27490,8 +27492,7 @@ auf einer temporären lokalen Instanz-Variable zu arbeiten

- -
+
@@ -27519,8 +27520,7 @@ die verschiedenen Belange im Quelltext nicht zu vermischen

- - +
@@ -27548,8 +27548,7 @@ Daher werfen wir ja auch error::Fatal

- - +
@@ -27566,8 +27565,7 @@ das auch in fehlerhaftem Double-Checked-Locking auftritt

- - +
@@ -27598,8 +27596,7 @@ der andere Thread ihn grade nutzt.

- - +
@@ -27614,8 +27611,7 @@ daß dieser Fall nicht relevant ist

- -
+ @@ -27642,8 +27638,7 @@ daß dieser "andere Thread" nicht (mehr) aktiv sein darf, wenn der Shutdown erfolgt.

- -
+
@@ -27660,8 +27655,7 @@ hier ist ein Segfault möglich

- - +
@@ -27689,8 +27683,7 @@ ...denn wir sind auf x86_64 -- und diese Plattform ist per default fast überall sequentially coherent

- - +
@@ -27759,8 +27752,7 @@ Der kaskadierende Aufruf liest dann einfach dessen Instanz-Pointer

- - +
@@ -27780,8 +27772,7 @@ Das könnte mit dem Factory-Management einer bereits installierten Konfiguration kollidieren

- - +
@@ -27845,8 +27836,7 @@ damit nicht doch noch der Deleter läuft.

- - +
@@ -27859,8 +27849,7 @@ ...und man stattdessen explizit eine gefährliche Funktion  aufrufen muß

- - +
@@ -27979,8 +27968,7 @@ Konsequenz: das ist keine Library-Implementierung

- - +
@@ -28020,7 +28008,8 @@ - + + @@ -28081,8 +28070,7 @@ die von der alten DependencyFactory abhängen

- - + @@ -28120,9 +28108,10 @@
- - - + + + + @@ -28157,8 +28146,7 @@ Und dann wäre es ziemlich pervasiv, sowas zum Freund zu erklären.

- - +
@@ -28170,8 +28158,7 @@ DependencyFactory ist viel besser geeignet

- -
+
@@ -29859,8 +29846,7 @@ das sind verschiedene Blickwinkel auf das gleiche Thema

- - + @@ -29887,8 +29873,7 @@ - - + @@ -29922,8 +29907,7 @@ eine Solche konstituiert die synchronizes-with-Beziehuung

- - +
@@ -29937,8 +29921,7 @@ Grundbeziehung: synchronizes-with

- - +
@@ -29960,8 +29943,7 @@ das gilt nur im Rahmen der synchronizes-with-Beziehung

- - +
@@ -29973,8 +29955,7 @@ das heißt, nur für einen vom gleichen Mutex geschützen  Bereich!

- -
+
@@ -30007,8 +29988,7 @@ Allerdinsg nicht auf einer Plattform, die ohnehin sequentiell-konsistent ist. Wie "zum Beispiel" x86/64

- -
+
@@ -30023,8 +30003,7 @@ ...haben wir es hier mit einem Pattern zu tun

- - + @@ -30036,8 +30015,7 @@ ich nenne es "synchronised visibility cones"

- -
+
@@ -30055,8 +30033,7 @@ In Realität arbeiten mehrere Threads/Cores mit mehreren Entitäten

- -
+
@@ -30072,8 +30049,7 @@ die shared zone anzufassen!

- - +
@@ -31283,8 +31259,7 @@ END

- - + @@ -31348,8 +31323,7 @@ weil sich die Threads gegenseitig ihre Counter inkrementieren.

- - +
@@ -31374,8 +31348,7 @@ verwenden globale Variable oder überhaupt keine Objektfelder

- - +