some cleanup and renaming
This commit is contained in:
parent
815f8569ce
commit
90dffdc9d2
7 changed files with 433 additions and 439 deletions
|
|
@ -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 T>
|
||||
class Wrapper<T, shared_ptr<T> >
|
||||
|
|
@ -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 T>
|
||||
class RefcountPtr : public Factory<T, Wrapper<T,shared_ptr<T> > >
|
||||
class RefcountFac : public Factory<T, Wrapper<T,shared_ptr<T> > >
|
||||
{
|
||||
public:
|
||||
typedef shared_ptr<T> 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<T, Wrapper<T> >
|
||||
class PImplFac : public Factory<T, Wrapper<T> >
|
||||
{
|
||||
public:
|
||||
typedef std::auto_ptr<T> PType;
|
||||
|
|
|
|||
|
|
@ -110,8 +110,8 @@ namespace mobject {
|
|||
|
||||
|
||||
// fabricating Objects wrapped into smart-ptrs
|
||||
lumiera::factory::RefcountPtr<Dummy<13> > oFac;
|
||||
lumiera::factory::RefcountPtr<Dummy<23> > pFac;
|
||||
lumiera::factory::RefcountFac<Dummy<13> > oFac;
|
||||
lumiera::factory::RefcountFac<Dummy<23> > pFac;
|
||||
|
||||
O o1, o2, o3;
|
||||
Q13 q1, q2, q3, q4, q5;
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
322
tests/lib/factory-special-test.cpp
Normal file
322
tests/lib/factory-special-test.cpp
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
/*
|
||||
Factory-Special(Test) - testing the more advanced features of factory
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
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 <boost/lexical_cast.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
|
||||
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<TargetO>
|
||||
{
|
||||
public:
|
||||
typedef shared_ptr<TargetO> 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<ParanoidObj>
|
||||
{
|
||||
public:
|
||||
typedef shared_ptr<ParanoidObj> 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<MallocO> FactoryM;
|
||||
typedef factory::PImplFac<TargetO,ImplObj> 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<uint>(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
|
||||
|
|
@ -1,326 +0,0 @@
|
|||
/*
|
||||
Factory-Special(Test) - testing the more advanced features of factory
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2008, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
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 <boost/lexical_cast.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <iostream>
|
||||
|
||||
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<TargetO>
|
||||
{
|
||||
public:
|
||||
typedef shared_ptr<TargetO> 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<ParanoidObj>
|
||||
{
|
||||
public:
|
||||
typedef shared_ptr<ParanoidObj> 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<MallocO> FactoryM;
|
||||
typedef factory::PImplPtr<TargetO,ImplObj> 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<uint>(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
|
||||
|
|
@ -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<TargetObj>
|
||||
{
|
||||
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<uint>(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<TargetObj>
|
||||
{
|
||||
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<uint>(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
|
||||
|
|
|
|||
|
|
@ -1232,7 +1232,7 @@ To make the intended use of the classes more clear, consider the following two e
|
|||
<pre>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
|
||||
</pre>
|
||||
</div>
|
||||
<div title="Factories" modifier="Ichthyostega" modified="200808110218" created="200708100401" tags="impl discuss excludeMissing" changecount="21">
|
||||
<div title="Factories" modifier="Ichthyostega" modified="200906060436" created="200708100401" tags="impl discuss excludeMissing" changecount="23">
|
||||
<pre>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
|
||||
</pre>
|
||||
</div>
|
||||
<div title="Fixture" modifier="Ichthyostega" modified="200712100439" created="200706220324" tags="def" changecount="4">
|
||||
|
|
@ -1500,13 +1501,15 @@ Finally, this example shows an ''automation'' data set controlling some paramete
|
|||
* decide on SessionInterface and create [[Session datastructure layout|SessionDataMem]]
|
||||
</pre>
|
||||
</div>
|
||||
<div title="ImplementationGuidelines" modifier="Ichthyostega" modified="200711210542" created="200711210531" tags="discuss draft" changecount="7">
|
||||
<div title="ImplementationGuidelines" modifier="Ichthyostega" modified="200906060443" created="200711210531" tags="discuss draft" changecount="12">
|
||||
<pre>!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)
|
||||
</pre>
|
||||
|
|
|
|||
Loading…
Reference in a new issue