diff --git a/src/lib/factory.hpp b/src/lib/factory.hpp deleted file mode 100644 index 28d37ad1a..000000000 --- a/src/lib/factory.hpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - FACTORY.hpp - template for object/smart-pointer factories - - 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. - -*/ - - -#ifndef LIB_FACTORY_H -#define LIB_FACTORY_H - -#include - - - -namespace lib { - namespace factory { - - /** - * Wrapping any object created by the Factory into some smart ptr class. - * 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 instantiated to either produce auto-ptrs or shared-ptrs. - */ - template - < class T, // the product to be created - class SMP =std::auto_ptr // smart-pointer actually returned - > - class Wrapper - { - protected: - SMP wrap (T* product) { return SMP (product); } - - public: - typedef SMP PType; - }; - - - /** - * 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 - * created object, which will manage the ownership. - * - * The provided default implementation uses just std::auto_ptr. - */ - template - < class T, // the product to be created - class WR = Wrapper // used for fabricating the wrapper - > - class Factory : public WR - { - public: - /** Object creating facility. - * Intended to be over/written/ with a variant taking - * the appropriate number of parameters and maybe - * using some special custom allocator. - * Note: non-virtual. - */ - typename WR::PType operator() () { return wrap (new T ); } - - }; - - - - - - /* -- some example and default instantiations -- */ - - using std::tr1::shared_ptr; - - /** - * a frequently used instantiation of the Wrapper, - * Utilising the refcounting tr1::shared_ptr. - */ - template - class Wrapper > - { - protected: - shared_ptr wrap (T* product) { return shared_ptr (product); } - - public: - typedef shared_ptr PType; - }; - - - /** - * Shortcut: commonly used (partial) instantiation of the Factory, - * generating refcounting shared_ptr wrapped Objects. Built upon - * the corresponding special instantiation of the Wrapper template. - */ - template - class RefcountFac : public Factory > > - { - public: - typedef shared_ptr PType; - }; - - - /** - * another convenience instantiation: auto_ptr-to-Impl-Factory. - * Creating an implementation subclass and wraps into auto_ptr. - * @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 PImplFac : public Factory > - { - public: - typedef std::auto_ptr PType; - - PType operator() (){ return wrap (static_cast (new TImpl)); }; - }; - - - - } // namespace factory - - /// @note Factory can be usable as-is (wraps into std::auto_ptr) - using factory::Factory; - - -} // namespace lib -#endif diff --git a/src/lib/multifact-arg.hpp b/src/lib/multifact-arg.hpp index 5422e1d08..5a04a7d69 100644 --- a/src/lib/multifact-arg.hpp +++ b/src/lib/multifact-arg.hpp @@ -20,7 +20,7 @@ */ -/** @file multifact.hpp +/** @file multifact-arg.hpp ** Extension allowing the MultiFact to pass arguments to the fabrication. ** This extension is implemented by template specialisations and thus kicks in ** when specifying a function \em signature as factory "product type". The resulting diff --git a/src/lib/multifact.hpp b/src/lib/multifact.hpp index b09ca8e2f..046cd6694 100644 --- a/src/lib/multifact.hpp +++ b/src/lib/multifact.hpp @@ -21,12 +21,13 @@ */ /** @file multifact.hpp - ** Building blocks to create a configurable factory, generating families of related objects. - ** Serving the "classical" factory situation: obtaining objects of various kinds, which - ** are related somehow (usually through an common interface). The creation of these - ** objects is non-trivial while number and exact parametrisation aren't known beforehand - ** and need to be figured out at runtime. Thus, a number of "fabrication lines" is set up, - ** to be selected on invocation through an ID (which may be symbolic, hashed or structural). + ** Framework for building a configurable factory, to generae families of related objects. + ** These building blocks are targeted towards the "classical" factory situation: obtaining + ** objects of various kinds, which are related somehow (usually through an common interface). + ** The creation of these objects might be non-trivial, while the number of flavours to be + ** produced and the exact parametrisation isn't known beforehand and needs to be figured out + ** at runtime. As a solution, thus a number of "fabrication lines" is set up, to be selected + ** on invocation through an ID (which may be symbolic, hashed or structural). ** ** Usually, the issue of object and storage management is closely related, while it is ** desirable to keep the object production logic clean of these rather technical concerns. @@ -38,7 +39,7 @@ ** function. ** ** \par Singleton generation - ** For the very common situation of needing various singleton objects, accessible by ID, + ** For the very common situation of building a family of singleton objects, accessible by ID, ** there is a convenience shortcut: The nested MultiFact::Singleton template can be instantiated ** within the context providing the objects (usually a static context). In itself a lib::Singleton ** factory, it automatically registers the singleton access function as "fabrication" function @@ -48,6 +49,7 @@ ** for the special case when the fabrication functions need additional invocation arguments. ** ** @see multifact-test.cpp + ** @see multifact-argument-test.cpp ** @see SingletonFactory ** @see lib::factory::Factory */ @@ -70,7 +72,7 @@ namespace lib { namespace factory { - /////////////////////////////////TICKET #470 : couldn't these wrappers be extracted into a separate header? + // Helpers to wrap the factory's product /** * Dummy "wrapper", diff --git a/src/proc/asset/media.hpp b/src/proc/asset/media.hpp index 3d3c0546c..73c5b3329 100644 --- a/src/proc/asset/media.hpp +++ b/src/proc/asset/media.hpp @@ -36,11 +36,12 @@ #define ASSET_MEDIA_H #include "proc/asset.hpp" -#include "lib/factory.hpp" #include "lib/time/timevalue.hpp" #include "proc/mobject/mobject.hpp" #include "proc/mobject/session/clip.hpp" +#include + namespace proc { @@ -138,7 +139,8 @@ namespace asset { /** * Factory specialised for creating Media Asset objects. */ - class MediaFactory : public lib::Factory + class MediaFactory + : boost::noncopyable { public: typedef P PType; diff --git a/src/proc/asset/meta.hpp b/src/proc/asset/meta.hpp index 8b6ffb7d1..24b56c81a 100644 --- a/src/proc/asset/meta.hpp +++ b/src/proc/asset/meta.hpp @@ -60,8 +60,8 @@ #include "proc/asset.hpp" #include "proc/asset/entry-id.hpp" -#include "lib/factory.hpp" +#include namespace proc { @@ -145,7 +145,8 @@ namespace asset { /** * Factory specialised for creating Metadata Asset objects. */ - class MetaFactory : public lib::Factory + class MetaFactory + : boost::noncopyable { public: typedef P PType; diff --git a/src/proc/asset/proc.hpp b/src/proc/asset/proc.hpp index 0f424aece..60486da19 100644 --- a/src/proc/asset/proc.hpp +++ b/src/proc/asset/proc.hpp @@ -36,9 +36,10 @@ #define ASSET_PROC_H #include "proc/asset.hpp" -#include "lib/factory.hpp" #include "proc/streamtype.hpp" +#include + namespace proc { @@ -113,7 +114,8 @@ namespace asset { /** * Factory specialised for creating Processor Asset objects. */ - class ProcFactory : public lib::Factory + class ProcFactory + : boost::noncopyable { public: typedef P PType; diff --git a/src/proc/asset/struct.hpp b/src/proc/asset/struct.hpp index 773ddf2c8..d9954526a 100644 --- a/src/proc/asset/struct.hpp +++ b/src/proc/asset/struct.hpp @@ -59,10 +59,9 @@ #include "proc/asset.hpp" #include "lib/query.hpp" -#include "lib/factory.hpp" -#include "lib/singleton.hpp" #include "lib/symbol.hpp" +#include #include #include @@ -134,7 +133,8 @@ namespace asset { /** * Factory specialised for creating Structural Asset objects. */ - class StructFactory : public lib::Factory + class StructFactory + : boost::noncopyable { scoped_ptr impl_; diff --git a/tests/40components.tests b/tests/40components.tests index 24a262f81..2d2aa4dc8 100644 --- a/tests/40components.tests +++ b/tests/40components.tests @@ -280,42 +280,6 @@ out: caught error::Logic: LUMIERA_ERROR_LOGIC:internal logic broken \(the big ba END -TEST "Factory_test" Factory_test 5 < string Dummy::name = str (typePatt % I); + template + inline P > + fabricate() + { + return P >(new Dummy); + } + @@ -109,22 +115,21 @@ namespace test { typedef DefsRegistry::Iter > Iter23; - // fabricating Objects wrapped into smart-ptrs - lib::factory::RefcountFac > oFac; - lib::factory::RefcountFac > pFac; - + // some test objects... Obj o1, o2, o3; Q13 q1, q2, q3, q4, q5; map ps; public: DefsRegistryImpl_test () - : o1 (oFac()), o2 (oFac()), o3 (oFac()), - q1 (garbage_query (1)), - q2 (garbage_query (2)), - q3 (garbage_query (3)), - q4 (garbage_query (4)), - q5 (garbage_query (5)) + : o1 (fabricate<13>()) + , o2 (fabricate<13>()) + , o3 (fabricate<13>()) + , q1 (garbage_query (1)) + , q2 (garbage_query (2)) + , q3 (garbage_query (3)) + , q4 (garbage_query (4)) + , q5 (garbage_query (5)) { } @@ -158,7 +163,7 @@ namespace test { ps.clear(); for (int i=0; i<100; ++i) { - Prd px (pFac()); + Prd px (fabricate<23>()); Q23 qx (garbage_query()); ps[qx] = px; reg_->put (px, qx); @@ -276,7 +281,7 @@ namespace test { CHECK (!reg_->forget (o1)); // failure, because it's already removed CHECK ( reg_->forget (o2)); - o3 = oFac(); // another object is another object (it's irrelevant...) + o3 = fabricate<13>(); // another object is another object (it's irrelevant...) i = reg_->candidates(q2); CHECK (! (*i)); // empty diff --git a/tests/lib/factory-special-test.cpp b/tests/lib/factory-special-test.cpp deleted file mode 100644 index eaa714422..000000000 --- a/tests/lib/factory-special-test.cpp +++ /dev/null @@ -1,322 +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 lib { -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; - CHECK (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 - } - - CHECK (0 == pX.use_count()); - - { - P p1 (placement_fac (cnt+1)); - P p2 (p1); - P p3 (p1); - P pX = p2; - - cout << msg % p2.use_count(); - - CHECK (raw == p1.get(), "explicit object placement at fixed buffer doesn't work."); - } - - CHECK (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; - - CHECK (0 == pX.use_count()); - { - P p1 (paranoid_fac (cnt)); - P p2 (p1); - P pX = p2; - - cout << msg % p2.use_count() - << string (*pX) << "\n"; - } - CHECK (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"; - - CHECK (!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 - - CHECK (!p1.get()); - } - }; - - - /** Register this test class... */ - LAUNCHER (Factory_special_test, "unit common"); - - - -}} // lib::test diff --git a/tests/lib/factorytest.cpp b/tests/lib/factorytest.cpp deleted file mode 100644 index dbf6dddb4..000000000 --- a/tests/lib/factorytest.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - Factory(Test) - unittest for the object creating 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 "testtargetobj.hpp" - -#include "lib/test/run.hpp" -#include "lib/factory.hpp" -#include "lib/util.hpp" - -#include -#include - -using boost::lexical_cast; -using util::isnil; -using std::string; -using std::cout; - - -namespace lib { -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 - { - 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 std::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) std::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 std::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 lib::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 lib::test diff --git a/tests/lib/multifact-argument-test.cpp b/tests/lib/multifact-argument-test.cpp index 5edd52e44..6c1760150 100644 --- a/tests/lib/multifact-argument-test.cpp +++ b/tests/lib/multifact-argument-test.cpp @@ -85,10 +85,11 @@ namespace test{ * @test define a MultiFact (factory with dynamic registration), * which accepts additional arguments and passes them * through to the registered factory function(s). - * @note we set up fabrication functions by binding such as to match - * the function signature declared in the factory; thereby one - * argument remains unclosed, which is the argument to be - * supplied on each factory invocation by the client code. + * @note we set up fabrication functions by binding the functions + * in such a way as to match the function signature declared + * in the factory; thereby one argument remains unclosed, + * which is the argument to be supplied on each + * factory invocation by the client code. * * @see lib::MultiFact * @see query-resolver.cpp