diff --git a/SConstruct b/SConstruct index cc2f5c308..0c2271198 100644 --- a/SConstruct +++ b/SConstruct @@ -152,6 +152,10 @@ def configurePlatform(env): if conf.CheckCHeader('valgrind/valgrind.h'): conf.env.Append(CPPFLAGS = ' -DHAS_VALGRIND_VALGIND_H') + if not conf.CheckCXXHeader('tr1/memory'): + print 'We rely on the std::tr1 proposed standard extension for shared_ptr.' + Exit(1) + if not conf.CheckCXXHeader('boost/config.hpp'): print 'We need the C++ boost-lib.' Exit(1) @@ -188,6 +192,8 @@ def defineBuildTargets(env, artifacts): """ cinobj = ( srcSubtree(env,'backend') + srcSubtree(env,'proc') + + srcSubtree(env,'common') +# + srcSubtree(env,'lib') + env.Object('$SRCDIR/main.cpp') ) plugobj = srcSubtree(env,'plugin', isShared=True) diff --git a/src/common/factory.hpp b/src/common/factory.hpp new file mode 100644 index 000000000..b3f9faeb7 --- /dev/null +++ b/src/common/factory.hpp @@ -0,0 +1,114 @@ +/* + FACTORY.hpp - template for object/smart-pointer factories + + Copyright (C) CinelerraCV + 2007, Christian Thaeter + + 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 CINELERRA_FACTORY_H +#define CINELERRA_FACTORY_H + +#include + + + +namespace cinelerra + { + + namespace factory{ class VanillaAllocator; }//////////////////////////////////TODO + + /** + * Configurable template for creating Factory classes. + * These encapsulate the creating of new objects, indeed + * delegating the memory allocation to the backend layer. + * 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, + * but delegates the allocation to cinelerra's backend-layer. + * + */ + template + < + class T, // the product to be created + template class SMP = std::auto_ptr,// smart-pointer actually returned + class ALO = factory::VanillaAllocator // Allocator facility to be used //////////////TODO + > + class Factory : protected ALO + { + public: + /** Object creating facility. + * Intended to be over/written/ with a variant taking + * the appropriate number of parameters and using the + * (privately inherited) functions of the allocator. + * Note: non-virtual. + */ + SMP operator() (){ return SMP (new T ); }; + + private: + void operator= (const Factory&); // copy prohibited + }; + + + + /* -- some example and default instantiiations -- */ + + namespace factory + { + /** + * Example Allocator using just the normal C++ memory management. + * The intended use is for a Factory instance to iherit from this class. + * Specialized Allocators typically overload operator new and delete. + */ + class VanillaAllocator {}; + + /** + * Example Allocator using plain C memory management. + */ + class MallocAllocator + { + void* operator new (size_t siz) { return malloc (siz); }; + void operator delete (void* p) { if (p) free (p); }; + }; + + + using std::tr1::shared_ptr; + + /** a frequently used instantiation of the Factory, + * using the refcounting shared_ptr from Boost + * and for allocation just our default Allocator + */ + template + class RefcountPtr : public Factory + { + /** let the smart-Ptr use the custom operator delete, + * which may be defined in our Allocator baseclass. + */ + static void destroy (T* victim) { delete victim; }; + + public: + shared_ptr operator() () { return shared_ptr (new T, &destroy ); } + }; + + + + } // namespace factory + +} // namespace cinelerra +#endif diff --git a/src/common/factorytest.cpp b/src/common/factorytest.cpp new file mode 100644 index 000000000..6c11cb45b --- /dev/null +++ b/src/common/factorytest.cpp @@ -0,0 +1,48 @@ +/* + Factorytest - check basic workings of object/smart-pointer factory + + Copyright (C) CinelerraCV + 2007, Christian Thaeter + + 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 "common/factory.hpp" + +namespace cinelerra + { + + class Blubb + { + int uii ; + + public: + typedef factory::RefcountPtr Factory; + static Factory create; + + Blubb() : uii(42) {} ; + }; + + /** a static Factory instance + * for creating refcounting Ptrs to Blubb objects + */ + Blubb::Factory Blubb::create; + + std::tr1::shared_ptr huii = Blubb::create (); + std::tr1::shared_ptr pfuii = huii; + +} // namespace cinelerra diff --git a/uml/cinelerra3/128517 b/uml/cinelerra3/128517 index 8683426d4..7bb6667f7 100644 --- a/uml/cinelerra3/128517 +++ b/uml/cinelerra3/128517 @@ -1,6 +1,6 @@ -format 38 +format 40 "CommonLib" // CommonLib - revision 6 + revision 7 modified_by 5 "hiv" // class settings //class diagram settings @@ -8,7 +8,7 @@ format 38 //use case diagram settings package_name_in_tab default show_context default auto_label_position default draw_all_relations default shadow default //sequence diagram settings - show_full_operations_definition default write_horizontally default drawing_language default draw_all_relations default shadow default + show_full_operations_definition default write_horizontally default class_drawing_mode default drawing_language default draw_all_relations default shadow default //collaboration diagram settings show_full_operations_definition default show_hierarchical_rank default write_horizontally default drawing_language default package_name_in_tab default show_context default draw_all_relations default shadow default //object diagram settings @@ -34,7 +34,7 @@ format 38 //object diagram settings write_horizontally default package_name_in_tab default show_context default auto_label_position default draw_all_relations default shadow default //sequence diagram settings - show_full_operations_definition default write_horizontally default drawing_language default draw_all_relations default shadow default + show_full_operations_definition default write_horizontally default class_drawing_mode default drawing_language default draw_all_relations default shadow default //state diagram settings package_name_in_tab default show_context default auto_label_position default write_trans_label_horizontally default show_trans_definition default draw_all_relations default shadow default show_activities default region_horizontally default drawing_language default @@ -58,6 +58,23 @@ ${inlines} investigate posix.4 realtime timers, wrap these here" end + + class 135301 "Factory" + visibility public + nformals 1 + formal name "T" type "class" explicit_default_value "" + explicit_extends "" + cpp_decl "${comment}${template}class ${name}${inherit} + { +${members} }; +${inlines} +" + java_decl "" + idl_decl "" + explicit_switch_type "" + + comment "a template for generating functor-like Factory objects, used to encapsulate object creation and providing access via smart-pointers only." + end end classview 128138 "Posix Threads Abstraction" @@ -68,7 +85,7 @@ investigate posix.4 realtime timers, wrap these here" //object diagram settings write_horizontally default package_name_in_tab default show_context default auto_label_position default draw_all_relations default shadow default //sequence diagram settings - show_full_operations_definition default write_horizontally default drawing_language default draw_all_relations default shadow default + show_full_operations_definition default write_horizontally default class_drawing_mode default drawing_language default draw_all_relations default shadow default //state diagram settings package_name_in_tab default show_context default auto_label_position default write_trans_label_horizontally default show_trans_definition default draw_all_relations default shadow default show_activities default region_horizontally default drawing_language default @@ -148,7 +165,7 @@ ${inlines} //object diagram settings write_horizontally default package_name_in_tab default show_context default auto_label_position default draw_all_relations default shadow default //sequence diagram settings - show_full_operations_definition default write_horizontally default drawing_language default draw_all_relations default shadow default + show_full_operations_definition default write_horizontally default class_drawing_mode default drawing_language default draw_all_relations default shadow default //state diagram settings package_name_in_tab default show_context default auto_label_position default write_trans_label_horizontally default show_trans_definition default draw_all_relations default shadow default show_activities default region_horizontally default drawing_language default diff --git a/uml/cinelerra3/5.session b/uml/cinelerra3/5.session index 65a46ae7d..e8231ca4c 100644 --- a/uml/cinelerra3/5.session +++ b/uml/cinelerra3/5.session @@ -1,9 +1,9 @@ window_sizes 1104 756 270 824 557 120 show_stereotypes selected -package_ref 129 // cinelerra3 + package_ref 129 // cinelerra3 open -package_ref 129669 // proc + package_ref 129669 // proc end end diff --git a/wiki/renderengine.html b/wiki/renderengine.html index 246def996..7184bad39 100644 --- a/wiki/renderengine.html +++ b/wiki/renderengine.html @@ -761,7 +761,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...)
@@ -778,6 +778,41 @@ To make the intended use of the classes more clear, consider the following two e
 * how to specify the actual type needed?
 * how to implement the cases where a subtype needs to be selected (abstract factory pattern). Embody this into the Factory, pass it in as a Strategy or treat the Factory just as a simple service taking an explicit type-ID and providing the new object?
 
+!!chosen design
+My main goal is to have an easy-to-use interface for the implementer of individual classes using this factory mechanism. The intended use should mimic the standard use of operator new, and at the same time there should be a possibility to configure »real« Factory behaviour in.
+
+For this reason I make Factory a Functor, and for handling the concrete memory allocation, it inherits from an Allocator class. The users of this factory template typically either parametrize it with existing smart-pointer types and some Allocator instantiation, or they may chose to create a specialized Factory derived from this Factory template. After typically hiding this configuration behind a typedef, the user adds a static field to the class intended to use the Factory and initializes this field with the concrete Factory (this may pass internal ~IDs to the constructor of the Factory and from there on to the underlying Allocator).
+{{{
+#include "common/factory.hpp"
+
+  class Blubb
+    {
+      int uii ;
+
+    public:
+      typedef cinelerra::factory::RefcountPtr<Blubb> Factory;
+      static Factory create;
+      
+      Blubb() : uii(42) {} ;
+    };
+  
+  /** a static Factory instance 
+   *  for creating refcounting Ptrs to Blubb objects 
+   */
+  Blubb::Factory Blubb::create;  // <----note this is a constructor call
+}}}
+Now, the clients of {{{class Blubb}}} can create ref-counting pointers to Blubb-objects by doing a fully qualified {{{create()}}} functor call:
+{{{
+  std::tr1::shared_ptr<Blubb> huii = Blubb::create ();  // <----will invoke the default Blubb() ctor 
+  std::tr1::shared_ptr<Blubb> pfuii = huii;
+}}}
+Some further details
+* Functor inherits (protected) from Allocator, besides that there are no additional requirements.
+* typically, Allocator provides a overloaded {{{operator new(size_t)}}} etc.
+* 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.
+* then, 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