diff --git a/src/lib/factory.hpp b/src/lib/factory.hpp index 5645cfba6..e7e568bf8 100644 --- a/src/lib/factory.hpp +++ b/src/lib/factory.hpp @@ -28,16 +28,15 @@ -namespace lumiera - { - namespace factory - { +namespace lumiera { + namespace factory { + /** * Wrapping any object created by the Factory into some smart ptr class. - * The Factory class inherits this functionallity, so it can be exchanged + * The Factory class inherits this functionality, so it can be exchanged * independently from the actual object creation behaviour. For example, * an Factory implementing some elaborate subclass creation scheme could - * be intantiated to either procuce auto-ptrs or shared-ptrs. + * be instantiated to either produce auto-ptrs or shared-ptrs. */ template < class T, // the product to be created @@ -54,7 +53,7 @@ namespace lumiera /** - * Basic Factory Template, for definig flexible Factory classes. + * Basic Factory Template, for defining flexible Factory classes. * These encapsulate the logic for creating of new objects, maybe * delegating the memory allocation to the backend layer. Usually, * the clients get just a smart-pointer or similar handle to the @@ -83,13 +82,13 @@ namespace lumiera - /* -- some example and default instantiiations -- */ + /* -- some example and default instantiations -- */ using std::tr1::shared_ptr; /** * a frequently used instantiation of the Wrapper, - * utilizing the refcounting shared_ptr from Boost. + * Utilising the refcounting tr1::shared_ptr. */ template class Wrapper > @@ -105,10 +104,10 @@ namespace lumiera /** * Shortcut: commonly used (partial) instantiation of the Factory, * generating refcounting shared_ptr wrapped Objects. Built upon - * the corresponding special intstantiation of the Wrapper template. + * the corresponding special instantiation of the Wrapper template. */ template - class RefcountPtr : public Factory > > + class RefcountFac : public Factory > > { public: typedef shared_ptr PType; @@ -116,16 +115,16 @@ namespace lumiera /** - * another convienience instantiiation: auto_ptr-to-Impl-Factory. + * another convenience instantiation: auto_ptr-to-Impl-Factory. * Creating an implementation subclass and wraps into auto_ptr. - * @warning the TImpl object will typically be destoyed by the + * @warning the TImpl object will typically be destroyed by the * smart ptr using an T*, so ~T() needs to be virtual. */ template < class T, // Interface class class TImpl // Implementation class to be created > - class PImplPtr : public Factory > + class PImplFac : public Factory > { public: typedef std::auto_ptr PType; diff --git a/tests/components/proc/mobject/session/defsregistryimpltest.cpp b/tests/components/proc/mobject/session/defsregistryimpltest.cpp index 3a04e4aa4..b625cddab 100644 --- a/tests/components/proc/mobject/session/defsregistryimpltest.cpp +++ b/tests/components/proc/mobject/session/defsregistryimpltest.cpp @@ -110,8 +110,8 @@ namespace mobject { // fabricating Objects wrapped into smart-ptrs - lumiera::factory::RefcountPtr > oFac; - lumiera::factory::RefcountPtr > pFac; + lumiera::factory::RefcountFac > oFac; + lumiera::factory::RefcountFac > pFac; O o1, o2, o3; Q13 q1, q2, q3, q4, q5; diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am index cea678415..323750462 100644 --- a/tests/lib/Makefile.am +++ b/tests/lib/Makefile.am @@ -40,7 +40,7 @@ test_lib_SOURCES = \ $(testlib_srcdir)/appconfigtest.cpp \ $(testlib_srcdir)/customsharedptrtest.cpp \ $(testlib_srcdir)/exceptionerrortest.cpp \ - $(testlib_srcdir)/factoryspecialtest.cpp \ + $(testlib_srcdir)/factory-special-test.cpp \ $(testlib_srcdir)/factorytest.cpp \ $(testlib_srcdir)/hash-indexed-test.cpp \ $(testlib_srcdir)/helloworldtest.cpp \ diff --git a/tests/lib/factory-special-test.cpp b/tests/lib/factory-special-test.cpp new file mode 100644 index 000000000..c8cc078d3 --- /dev/null +++ b/tests/lib/factory-special-test.cpp @@ -0,0 +1,322 @@ +/* + Factory-Special(Test) - testing the more advanced features of factory + + Copyright (C) Lumiera.org + 2008, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "lib/test/run.hpp" +#include "lib/util.hpp" + +#include "testtargetobj.hpp" +#include "lib/factory.hpp" + +#include +#include +#include + +using boost::lexical_cast; +using boost::format; +using util::isnil; +using std::string; +using std::cout; + + +namespace lumiera { +namespace test { + + /** + * Example Allocator using plain C memory management. + */ + class MallocAllocator + { + public: + void* operator new (size_t siz) { return malloc (siz); }; + void operator delete (void* p) { if (p) free (p); }; + }; + + + /** + * Simple subclass used for custom alloc and as Interface class + */ + class TargetO : public TestTargetObj + { + long additional_member; + + public: + TargetO (uint cnt) : TestTargetObj(cnt) {} + virtual ~TargetO () {}; + + /** Example Base/Interface function */ + virtual void funky() + { + cout << string(*this) << "\n"; + } + }; + + + /** + * Subclass of the Interface class TargetO, could be an implementation class. + */ + class ImplObj : public TargetO + { + public: + ImplObj () : TargetO(12) {} + + /** Example Implementation function */ + virtual void funky() + { + cout << ".....ImplObj::funky() called\n"; + TargetO::funky(); + } + }; + + + /** + * Another special Subclass, using custom allocation. + */ + class MallocO : public TestTargetObj, public MallocAllocator + { + public: + MallocO () : TestTargetObj (7) {} + }; + + + + class Factory2; + + /** + * Special Subclass prohibiting public use of ctor + */ + class ParanoidObj : public TestTargetObj + { + private: + ParanoidObj (uint cnt) : TestTargetObj(cnt) {} + ~ParanoidObj () {} + + friend class Factory2; + }; + + + + + /* ===== several specialised Factories ====== */ + + using std::tr1::shared_ptr; + + /** + * Factory creating refcounting TargetO pointers + * and using placement Allocation. + */ + class Factory1 : public Factory + { + public: + typedef shared_ptr PType; + + /** Specialised Factory method + * doing placement new and invoking + * a special constructor. */ + PType operator() (uint param) { return wrap (new(alloc()) TargetO(param) ); } + + protected: + PType wrap (TargetO* tO) { return PType (tO, &destroy); } ///< note: providing custom deleter function + + static void destroy (TargetO* victim) { victim->~TargetO(); } ///< call dtor but don't delete mem + static void* alloc () { return buff; } ///< returning raw mem for new object + static char buff[]; ///< we place our (single) instance here + }; + char Factory1::buff[sizeof(TargetO)]; + + + + /** + * Factory usable if object can be constructed only by friends + */ + class Factory2 : public Factory + { + public: + typedef shared_ptr PType; + + /** allowed to call ctor because + * it's a friend of ParanoidObj. + * Note passing custom deleter. + */ + PType operator() (uint param) { return PType (new ParanoidObj(param), &destroy); } + + protected: + /** custom deleter func is allowed to call + * ~ParanoidObj() because of friendship + */ + static void destroy (ParanoidObj* victim) { delete victim; } + + }; + + + + /* === Factory instances ==============*/ + + typedef Factory FactoryM; + typedef factory::PImplFac FactoryP; + + static Factory1 placement_fac; + static Factory2 paranoid_fac; + static FactoryM malloc_fac; + static FactoryP pimpl_fac; + + + + + + + /******************************************************************* + * testing the more advanced Factory variants and possibilities. + * We use several customised Factory subclasses supporting custom + * allocation, placement allocation, private constructors and + * the PIpmpl design pattern. All creating smart pointers. + */ + class Factory_special_test : public Test + { + virtual void run(Arg arg) + { + uint num= isnil(arg)? 1 : lexical_cast(arg[1]); + + checkPlacement (num); + checkPrivate (num); + checkMalloc (); + checkPImpl () ; + } + + + /** @test using direct object placement instead of heap allocation. + * Factory1 will place every new object into the same static buffer + * and return a refcounting pointer + */ + void checkPlacement (uint cnt) + { + cout << "checkPlacement--------\n"; + + typedef Factory1::PType P; + format msg ("created %d shared_ptrs to Object placed in static buffer.\n"); + void* raw (0); + P pX; + ASSERT (0 == pX.use_count()); + + { + P p1 (placement_fac (cnt)); + P p2 (p1); + P pX = p2; + + cout << msg % p2.use_count() + << string (*pX) << "\n"; + + raw = p1.get(); // remember raw mem address + } + + ASSERT (0 == pX.use_count()); + + { + P p1 (placement_fac (cnt+1)); + P p2 (p1); + P p3 (p1); + P pX = p2; + + cout << msg % p2.use_count(); + + ASSERT (raw == p1.get(), "explicit object placement at fixed buffer doesn't work."); + } + + ASSERT (0 == pX.use_count()); + } + + + + + /** @test simple factory creating std::auto_ptr wrapped instances + * of an object with only private ctor and dtor. + */ + void checkPrivate (uint cnt) + { + cout << "checkPrivate--------\n"; + + typedef Factory2::PType P; + format msg ("created %d shared_ptrs to paranoid Object.\n"); + P pX; + + ASSERT (0 == pX.use_count()); + { + P p1 (paranoid_fac (cnt)); + P p2 (p1); + P pX = p2; + + cout << msg % p2.use_count() + << string (*pX) << "\n"; + } + ASSERT (0 == pX.use_count()); + } + + + + + /** @test simple factory creating std::auto_ptr wrapped instances, + * but of a class using a custom allocation scheme (here implemented + * by direct C-style malloc calls) + */ + void checkMalloc (void) + { + cout << "checkMalloc--------\n"; + + typedef FactoryM::PType P; + + P p1 (malloc_fac ()); + P p2 = p1; + cout << ("created auto_ptr to malloc-ed Object.\n") + << string (*p2) << "\n"; + + ASSERT (!p1.get()); + } + + + + + /** @test using direct object placement instead of heap allocation. + * Factory1 will place every new object into the same static buffer + * and return a refcounting pointer + */ + void checkPImpl (void) + { + cout << "checkPImpl--------\n"; + + typedef FactoryP::PType P; + + P p1 (pimpl_fac ()); + P p2 = p1; + cout << ("created auto_ptr to Interface Object.\n"); + p2->funky(); // call a Interface function + + ASSERT (!p1.get()); + } + }; + + + /** Register this test class... */ + LAUNCHER (Factory_special_test, "unit common"); + + + +}} // namespace lumiera::test diff --git a/tests/lib/factoryspecialtest.cpp b/tests/lib/factoryspecialtest.cpp deleted file mode 100644 index 26fda9084..000000000 --- a/tests/lib/factoryspecialtest.cpp +++ /dev/null @@ -1,326 +0,0 @@ -/* - Factory-Special(Test) - testing the more advanced features of factory - - Copyright (C) Lumiera.org - 2008, Hermann Vosseler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -* *****************************************************/ - - -#include "lib/test/run.hpp" -#include "lib/util.hpp" - -#include "testtargetobj.hpp" -#include "lib/factory.hpp" - -#include -#include -#include - -using boost::lexical_cast; -using boost::format; -using util::isnil; -using std::string; -using std::cout; - - -namespace lumiera - { - namespace test - { - - /** - * Example Allocator using plain C memory management. - */ - class MallocAllocator - { - public: - void* operator new (size_t siz) { return malloc (siz); }; - void operator delete (void* p) { if (p) free (p); }; - }; - - - /** - * Simple subclass used for custom alloc and as Interface class - */ - class TargetO : public TestTargetObj - { - long additional_member; - - public: - TargetO (uint cnt) : TestTargetObj(cnt) {} - virtual ~TargetO () {}; - - /** Example Base/Interface function */ - virtual void funky() - { - cout << string(*this) << "\n"; - } - }; - - - /** - * Subclass of the Interface class TargetO, could be an implementation class. - */ - class ImplObj : public TargetO - { - public: - ImplObj () : TargetO(12) {} - - /** Example Implementation function */ - virtual void funky() - { - cout << ".....ImplObj::funky() called\n"; - TargetO::funky(); - } - }; - - - /** - * Another special Subclass, using custom allocation. - */ - class MallocO : public TestTargetObj, public MallocAllocator - { - public: - MallocO () : TestTargetObj (7) {} - }; - - - - class Factory2; - - /** - * Special Subclass prohibiting public use of ctor - */ - class ParanoidObj : public TestTargetObj - { - private: - ParanoidObj (uint cnt) : TestTargetObj(cnt) {} - ~ParanoidObj () {} - - friend class Factory2; - }; - - - - - /* ===== several specialized Factories ====== */ - - using std::tr1::shared_ptr; - - /** - * Factory creating refcounting TargetO pointers - * and using placement Allocation. - */ - class Factory1 : public Factory - { - public: - typedef shared_ptr PType; - - /** specialized Factory method - * doing placement new and invoking - * a special constructor. */ - PType operator() (uint param) { return wrap (new(alloc()) TargetO(param) ); } - - protected: - PType wrap (TargetO* tO) { return PType (tO, &destroy); } ///< note: providing custom deleter func - - static void destroy (TargetO* victim) { victim->~TargetO(); } ///< call dtor but don't delete mem - static void* alloc () { return buff; } ///< returning raw mem for new object - static char buff[]; ///< we place our (single) instance here - }; - char Factory1::buff[sizeof(TargetO)]; - - - - /** - * Factory usable if object can be constructed only by friends - */ - class Factory2 : public Factory - { - public: - typedef shared_ptr PType; - - /** allowed to call ctor because - * it's a friend of ParanoidObj. - * Note passing custom deleter. - */ - PType operator() (uint param) { return PType (new ParanoidObj(param), &destroy); } - - protected: - /** custom deleter func is allowed to call - * ~ParanoidObj() because of friendship - */ - static void destroy (ParanoidObj* victim) { delete victim; } - - }; - - - - /* === Factory instances ==============*/ - - typedef Factory FactoryM; - typedef factory::PImplPtr FactoryP; - - static Factory1 placement_fac; - static Factory2 paranoid_fac; - static FactoryM malloc_fac; - static FactoryP pimpl_fac; - - - - - - - /******************************************************************* - * testing the more advanced Factory variants and possibilities. - * We use several customised Factory subclasses supporting custom - * allocation, placement allocation, private constructors and - * the PIpmpl design pattern. All creating smart pointers. - */ - class Factory_special_test : public Test - { - virtual void run(Arg arg) - { - uint num= isnil(arg)? 1 : lexical_cast(arg[1]); - - checkPlacement (num); - checkPrivate (num); - checkMalloc (); - checkPImpl () ; - } - - - /** @test using direct object placement instead of heap allocation. - * Factory1 will place every new object into the same static buffer - * and return a refcounting pointer - */ - void checkPlacement (uint cnt) - { - cout << "checkPlacement--------\n"; - - typedef Factory1::PType P; - format msg ("created %d shared_ptrs to Object placed in static buffer.\n"); - void* raw (0); - P pX; - ASSERT (0 == pX.use_count()); - - { - P p1 (placement_fac (cnt)); - P p2 (p1); - P pX = p2; - - cout << msg % p2.use_count() - << string (*pX) << "\n"; - - raw = p1.get(); // remember raw mem address - } - - ASSERT (0 == pX.use_count()); - - { - P p1 (placement_fac (cnt+1)); - P p2 (p1); - P p3 (p1); - P pX = p2; - - cout << msg % p2.use_count(); - - ASSERT (raw == p1.get(), "explicit object placement at fixed buffer doesn't work."); - } - - ASSERT (0 == pX.use_count()); - } - - - - - /** @test simple factory creating std::auto_ptr wrapped instances - * of an object with only private ctor and dtor. - */ - void checkPrivate (uint cnt) - { - cout << "checkPrivate--------\n"; - - typedef Factory2::PType P; - format msg ("created %d shared_ptrs to paranoid Object.\n"); - P pX; - - ASSERT (0 == pX.use_count()); - { - P p1 (paranoid_fac (cnt)); - P p2 (p1); - P pX = p2; - - cout << msg % p2.use_count() - << string (*pX) << "\n"; - } - ASSERT (0 == pX.use_count()); - } - - - - - /** @test simple factory creating std::auto_ptr wrapped instances, - * but of a class using a custom allocation scheme (here implemented - * by direct C-style malloc calls) - */ - void checkMalloc (void) - { - cout << "checkMalloc--------\n"; - - typedef FactoryM::PType P; - - P p1 (malloc_fac ()); - P p2 = p1; - cout << ("created auto_ptr to malloc-ed Object.\n") - << string (*p2) << "\n"; - - ASSERT (!p1.get()); - } - - - - - /** @test using direct object placement instead of heap allocation. - * Factory1 will place every new object into the same static buffer - * and return a refcounting pointer - */ - void checkPImpl (void) - { - cout << "checkPImpl--------\n"; - - typedef FactoryP::PType P; - - P p1 (pimpl_fac ()); - P p2 = p1; - cout << ("created auto_ptr to Interface Object.\n"); - p2->funky(); // call a Interface function - - ASSERT (!p1.get()); - } - }; - - - /** Register this test class... */ - LAUNCHER (Factory_special_test, "unit common"); - - - - } // namespace test - -} // namespace lumiera diff --git a/tests/lib/factorytest.cpp b/tests/lib/factorytest.cpp index 578c63085..d1026f7b4 100644 --- a/tests/lib/factorytest.cpp +++ b/tests/lib/factorytest.cpp @@ -36,93 +36,89 @@ using std::string; using std::cout; -namespace lumiera - { - namespace test +namespace lumiera { +namespace test { + + class ObjFactory; + + + /** + * Target object to be created by the Test-Factory. + * Allocates a variable amount of additional heap memory + * and prints diagnostic messages. Note we provide a + * static member TargetObj::create for the client + * code to generate smart ptr wrapped instances. + */ + class TargetObj : public TestTargetObj { - - class ObjFactory; - - - /** - * Target object to be created by the Test-Factory. - * Allocates a variable amount of additional heap memory - * and prints diagnostic messages. Note we provide a - * static member TargetObj::create for the client - * code to generate smart ptr wrapped instances. - */ - class TargetObj : public TestTargetObj - { - public: - TargetObj (uint cnt) : TestTargetObj(cnt) {} - - static ObjFactory create; - }; - - - - /** Test-Factory specialized to create TargetObj instances - * using the 1-argument constructor TargetObj::TargetObj(int). - * It will create boost::shared_ptr instances, because - * factory::RefcountPtr was parametrized with this smart pointer type. - */ - class ObjFactory : public factory::RefcountPtr - { - public: - /** specialized Factory method for creating TargetObj instances. - * Here, we invoke a special constructor, but basically we could - * do everything we want, creating instances of sub classes, - * registering objects etc. Further, we could have used a - * custom allocator or a special deleter function. - */ - PType operator() (uint param) { return wrap (new TargetObj(param) ); } - - }; - - - /** shorthand for the created smart-pointer class, - * here it's a (refcounting) boost::shared_ptr - */ - typedef ObjFactory::PType pTarget; - - ObjFactory TargetObj::create; - - - - - - - /******************************************************************* - * @test the basic object creation Factory behaviour: We declared - * a static field TargetObj::create to be a ObjFactory. So, - * by invoking this functor, we get a boost::shared_ptr - * wrapping a new TargetObj instance. From this we copy - * further shared-ptrs, invoke a member function and - * finally, when leaving the scope, our TargetObj - * will be destroyed automatically. - * @see lumiera::Factory - */ - class Factory_test : public Test - { - virtual void run(Arg arg) - { - uint num= isnil(arg)? 1 : lexical_cast(arg[1]); - - pTarget p1 (TargetObj::create (num)); - pTarget p2 (p1); - pTarget p3 = p2; - - cout << "now the smart-ptr has refcount=" << p1.use_count() << "\n" - << string (*p3) << "\n"; - } - }; - - - /** Register this test class... */ - LAUNCHER (Factory_test, "unit common"); - - - - } // namespace test - -} // namespace lumiera + public: + TargetObj (uint cnt) : TestTargetObj(cnt) {} + + static ObjFactory create; + }; + + + + /** Test-Factory specialised to create TargetObj instances + * using the 1-argument constructor TargetObj::TargetObj(int). + * It will create boost::shared_ptr instances, because + * factory::RefcountFac was parametrised with this smart pointer type. + */ + class ObjFactory : public factory::RefcountFac + { + public: + /** specialised Factory method for creating TargetObj instances. + * Here, we invoke a special constructor, but basically we could + * do everything we want, creating instances of sub classes, + * registering objects etc. Further, we could have used a + * custom allocator or a special deleter function. + */ + PType operator() (uint param) { return wrap (new TargetObj(param) ); } + + }; + + + /** shorthand for the created smart-pointer class, + * here it's a (refcounting) boost::shared_ptr + */ + typedef ObjFactory::PType pTarget; + + ObjFactory TargetObj::create; + + + + + + + /******************************************************************* + * @test the basic object creation Factory behaviour: We declared + * a static field TargetObj::create to be a ObjFactory. So, + * by invoking this functor, we get a boost::shared_ptr + * wrapping a new TargetObj instance. From this we copy + * further shared-ptrs, invoke a member function and + * finally, when leaving the scope, our TargetObj + * will be destroyed automatically. + * @see lumiera::Factory + */ + class Factory_test : public Test + { + virtual void run(Arg arg) + { + uint num= isnil(arg)? 1 : lexical_cast(arg[1]); + + pTarget p1 (TargetObj::create (num)); + pTarget p2 (p1); + pTarget p3 = p2; + + cout << "now the smart-ptr has refcount=" << p1.use_count() << "\n" + << string (*p3) << "\n"; + } + }; + + + /** Register this test class... */ + LAUNCHER (Factory_test, "unit common"); + + + +}} // namespace lumiera::test diff --git a/wiki/renderengine.html b/wiki/renderengine.html index ff4258b84..20ef06d76 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -1232,7 +1232,7 @@ To make the intended use of the classes more clear, consider the following two e
A special kind (subclass) of [[Placement]]. As such it is always linked to a //Subject//, i.e. a MObject. In addition to the properties of a (unspecific) Placement, the ExplicitPlacement specifies a absolute time and track position for locating the Subject
 
-
+
We use Factories
 * for centralizing [[memory management|MemoryManagement]]
 * to support polymorphism (of course...)
@@ -1261,7 +1261,7 @@ For this reason I make Factory a Functor, so it can be incorporated as a member
       int wow_;
 
     public:
-      typedef lumiera::factory::RefcountPtr<Product> Factory;
+      typedef lumiera::factory::RefcntFactory<Product> Factory;
       static Factory create;
       
       Product() : wow_(42) {} ;
@@ -1282,7 +1282,8 @@ Some further details
 * thus, when Functor or any derived class issues a new XX(), our custom Allocator gains control
 * the Functor-behaviour relies on a custom {{{operator()}}} which can be overridden in derived classes to take various parameter lists.
 * additionally, such a Factory class derived from Functor can do specific magic and e.g. create some subclass
-* and, as the created smart-pointer is a template parameter, such a custom Functor can create all sorts of Proxies, wrappers and the like
+* and, as the created smart-pointer is a template template parameter, such a custom Functor can create all sorts of Proxies, wrappers and the like
+* a special case of this factory use is the [[Singleton]] factory, which is used a lot within the Proy-Layer code
 
@@ -1500,13 +1501,15 @@ Finally, this example shows an ''automation'' data set controlling some paramete * decide on SessionInterface and create [[Session datastructure layout|SessionDataMem]]
-
+
!Observations, Ideas, Proposals
 ''this page is a scrapbook for collecting ideas'' &mdash; please don't take anything noted here too literal. While writing code, I observe that I (ichthyo) follow certain informal guidelines, some of which I'd like to note down because they could evolve into general style guidelines for the proc layer code.
-* avoid doing anything non-local during the startup phase or shutdown phase of the application. consequently, allways prefer using an explicit lumiera::Singleton<T> over using an static instance directly, thus yielding better control when the ctor and dtor will be invoked.
-* write error handling code only if the error situation can be actually //handled// at this place. Otherwise, be prepared for exceptions just passing by and thus handle any resources by "resource acquisition is initialisation". Remember: error handling defeats decoupling and encapsulation
+* avoid doing anything non-local during the startup phase or shutdown phase of the application. consequently, always prefer using an explicit lumiera::Singleton<T> over using an static instance directly, thus yielding better control when the ctor and dtor will be invoked.
+* write error handling code only if the error situation can be actually //handled// at this place. Otherwise, be prepared for exceptions just passing by and thus handle any resources by "resource acquisition is initialisation" (RAII). Remember: error handling defeats decoupling and encapsulation
 * (almost) never {{{delete}}} an object directly, use {{{new}}} only when some smart pointer is at hand.
-* when user/client code is inteded to create objects, make the ctor protected and provide a factory member called {{{create}}} instead, returning a smart pointer
+* when user/client code is intended to create objects, make the ctor protected and provide a factory member called {{{create}}} instead, returning a smart pointer
+* similarly, when we need just one instance of a given service, make the ctor protected and provide a factory member called {{{instance}}}, to be implemented by the lumiera::[[Singleton]] factory.
+* whenever possible, prefer this (lazy initialised [[Singleton]]) approach and avoid static initialisation magic
 * avoid asuming anything that can't be enforced by types, interfaces or signatures; this means: be prepared for open possibilities
 * prefer {{{const}}} and initialisation code over assignment and active changes (inspired by functional programming)