473,320 Members | 1,861 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Object factory and Intel compiler

Hi all

I have code for an object factory, heavily based on an article by Jim Hyslop
(although I've made minor modifications). The factory was working fine using
g++, but since switching to the Intel compiler it has stopped working. I
think the singleton pattern static instance thing may be at the root of the
problem, but I'm not sure. I had to add calls to instance() in regCreateFn,
which gets the behaviour more in line with what I was expecting during
static initialization (the objects all register with the same registry). I
have tried playing with the MS compatibility options of the Intel compiler,
with no success.

The problem occurs when I make a call to manufacture a given object: a
totally different instance of the factory and registry are used (I have
checked this by printing out pointers).

A typical call to the manufacture method would be:

shared_ptr<CAngle3D> newB = boost::shared_polymorphic_cast<CAngle3D>
(objectFactory<CBase>::instance().manufacture("CAn gle3D"));

This fails, since the objectFactory<CBase>::instance() returns a valid
factory, but one with no items in the map of create functions (i.e. it is a
different one to that used when registering the create functions in the
static initalizers).

In this example, the first section of the header for CAngle3D is as follows:
class CAngle3D : public CBase
{
public:
// Tell the Object Factory about this class
//FACTORY_DECLARE_CLASS(CAngle3D
static registerInFactory<CBase, CAngle3D> regClass;

and the following is placed into the cpp for CAngle3D:
// Register class with Object Factory
//FACTORY_REGISTER_CLASS(CAngle3D)
registerInFactory<CBase, CAngle3D> CAngle3D::regClass("CAngle3D");

The complete CFactory.h listing is pasted at the end of this email. You will
notice that there is a large amount of debugging info being output.

The output of my program, when it starts up, is as follows: (Notice
especially the memory addresses, that change when the program tries to
manufacture a CAngle3D object)

$ ./TestMathCore
Constructor: objectFactory for class CBase
Registering create function for "CAngle3D"
Registry size = 1(0046FBD0)
Registering clone function for "CAngle3D"
registerInFactory: "CAngle3D"
Constructor: objectFactory for class CBase
Registering create function for "CFrequency"
Registry size = 2(0046FBD0)
Registering clone function for "CFrequency"
registerInFactory: "CFrequency"
Constructor: objectFactory for class CBase
Registering create function for "CList"
Registry size = 3(0046FBD0)
Registering clone function for "CList"
registerInFactory: "CList"
Constructor: objectFactory for class CBase
Registering create function for "CSortableList"
Registry size = 4(0046FBD0)
Registering clone function for "CSortableList"
registerInFactory: "CSortableList"
Constructor: objectFactory for class CBase
Registering create function for "CCollection"
Registry size = 5(0046FBD0)
Registering clone function for "CCollection"
registerInFactory: "CCollection"
Constructor: objectFactory for class CBase
Registering create function for "CAngle"
Registry size = 6(0046FBD0)
Registering clone function for "CAngle"
registerInFactory: "CAngle"
Min resolution = 1, Max resolution = 1000000
Timer setting successful.
The system clock interval is 10 ms.
Adjustment disabled = 1
MathCore Test App
-----------------

CAngle3D
Constructor: objectFactory for class CBase
Registry size = 0(0046FB04)
Contents of Object Factory warehouse:

Trying to manufacture "CAngle3D"
Object Factory 0046FB04: 0 items
objectFactory: Don't know how to manufacture that object type.
Ensure that FACTORY_REGISTER_CLASS is used.

I would *really* appreciate some help! Sorry for the hugely long post . . .

Ryan
// CFactory.h
// object abstract factory template.
// Copyright 2001, Jim Hyslop.
// This file may be freely used, modified and distributed, provided that
// the accompanying copyright notice remains intact.
//
// The object abstract factory template is an implementation of the
// Abstract Class Factory pattern, as a template (see "Design Patterns:
// Elements of Reusable Object-Oriented Software", E. Gamma, R. Helm,
// R. Johnson, J. Vlissides, Addison Wesley [1995] )
//
// To use the template, you need to provide a base class and (optionally)
// a key class. The base class must provide a unique identifier
//
// The key class must be able to be used as a key in a std::map, i.e. it
must
// - implement copy and assignment semantics
// - provide bool operator< () const;
// Default is std::string.
//
// Steps to using the factory:
// 1 - Create the base class and its derivatives
// 2 - Register each class in the factory by instantiating a
// registerInFactory<> template class - do this in one file only (the
// class implementation file is the perfect place for this)
// 3 - create the object by calling create() and passing it the same
// value used when you instantiated the registerInFactory object.
// For example:
// base header:
// class Base { /* whatever (don't forget the virtual dtor! */ };
//
// base implementation:
// registerInFactory<Base, Base, std::string> registerBase("Base");
//
// derived header:
// class Derived : public Base { /* whatever */ };
//
// derived implementation:
// registerInFactory<Base, Derived, std::string> registerDer("Derived");
//
// code that instantiates the classes:
// std::auto_ptr<Base> newBase =
objectFactory<Base>::instance().create("Base");
// std::auto_ptr<Base> newDerived =
objectFactory<Base>::instance().create("Derived");
//
// New derivatives can be added without affecting the existing code.

#ifndef FACTORY_HEADER_DEFINED
#define FACTORY_HEADER_DEFINED

#include <boost/shared_ptr.hpp>

using boost::shared_ptr;

//#pragma warning(disable: 4275)
//#pragma warning(disable: 4786)

// Macro to simplify registration with the Object Factory and creation of a
Clone function
// To be used in the class declaration in the header file (.h) for the new
class
#define FACTORY_DECLARE_CLASS(_cNewClass) \
static registerInFactory<CBase,_cNewClass>regClass;\
virtual shared_ptr<CBase>Clone()\
{return shared_ptr<CBase>(new _cNewClass(*this));}

// Macro to simplify implementation of the registration function
// To be used in the class implementation (.cpp) file for the new class
#define FACTORY_REGISTER_CLASS(_cNewClass) \
registerInFactory<CBase, _cNewClass> _cNewClass::regClass(#_cNewClass);

// The abstract factory itself.
// Implemented using the Singleton pattern

template <class manufacturedObj>
class objectFactory
{
public:
// a BASE_CREATE_FN is a function that takes no parameters
// and returns a pointer to a manufactuedObj. Note that
// we use no parameters, but you could add them
// easily enough to allow overloaded ctors, e.g.:
typedef manufacturedObj* (*BASE_CREATE_FN)();

typedef manufacturedObj* (*BASE_CLONE_FN)(manufacturedObj*);

int iTest;
// FN_REGISTRY is the registry of all the BASE_CREATE_FN
// pointers registered. Functions are registered using the
// regCreateFn member function (see below).
typedef map<string, BASE_CREATE_FN> FN_REGISTRY;
FN_REGISTRY registry;

typedef map<string, BASE_CLONE_FN> FN_CLONE_REGISTRY;
FN_CLONE_REGISTRY CloneRegistry;

// Singleton implementation - private ctor & copying, with
// no implementation on the copying.
objectFactory();
objectFactory(const objectFactory&); // Not implemented
objectFactory &operator=(const objectFactory&); // Not implemented
public:
// Singleton access.
static objectFactory &instance();

// Method to register the class ID key, and a pointer to
// the function that creates the class.
void regCreateFn(const string & strClassID, BASE_CREATE_FN);

// Method to register the class ID key, and a pointer to
// the function that clones
void regCloneFn(const string & strClassID, BASE_CLONE_FN);

// Create a new class of the type specified by className.
// manufacturedObj* manufacture(const std::string & className) const;
shared_ptr<manufacturedObj> manufacture(const std::string & className)
const;

shared_ptr<manufacturedObj> clone(shared_ptr<manufacturedObj> pToClone)
const;

// Create a new class of the type specified by className.
shared_ptr<manufacturedObj> assemble(list<string> &is,
list<string>::const_iterator& i) const;
};

////////////////////////////////////////////////////////////////////////
// Implementation details.

template <class manufacturedObj>
objectFactory<manufacturedObj>::objectFactory()
{
cout << "Constructor: objectFactory for " << typeid(manufacturedObj).name()
<< endl;
}

template <class manufacturedObj>
objectFactory<manufacturedObj> & objectFactory<manufacturedObj>::instance()
{
// Note that this is not thread-safe!
static objectFactory theInstance;
return theInstance;
}

// Register the creation function. This simply associates the classIDKey
// with the function used to create the class. The return value is a dummy
// value, which is used to allow static initialization of the registry.
// See example implementations in base.cpp and derived.cpp
template <class manufacturedObj>
void objectFactory<manufacturedObj>::regCreateFn(const string & strClassID,
BASE_CREATE_FN func)
{
cout << "Registering create function for \"" << strClassID << "\"" << endl;
instance().registry[strClassID] = func;
cout << "Registry size = " << instance().registry.size() << "(" <<
&(instance().registry) << ")" << endl;
}

template <class manufacturedObj>
void objectFactory<manufacturedObj>::regCloneFn(const string & strClassID,
BASE_CLONE_FN func)
{
cout << "Registering clone function for \"" << strClassID << "\"" << endl;
instance().CloneRegistry[strClassID]=func;
}

template <class manufacturedObj>
shared_ptr<manufacturedObj>
objectFactory<manufacturedObj>::manufacture(const std::string & className)
const
{
cout << "Registry size = " << instance().registry.size() << "(" <<
&(instance().registry) << ")" << endl;
shared_ptr<manufacturedObj> manufactured;
cout << "Contents of Object Factory warehouse:" << endl;
typename FN_REGISTRY::const_iterator regIter = instance().registry.begin();
while (regIter != instance().registry.end())
cout << regIter->first << endl;
cout << endl;

typename FN_REGISTRY::const_iterator regEntry =
instance().registry.find(className);
cout << "Trying to manufacture \"" << className << "\"" << endl;
cout << "Object Factory " << &(instance().registry) << ": " <<
instance().registry.size() << " items" << endl;
if (regEntry != instance().registry.end())
manufactured.reset((*regEntry).second());
else
cout << "objectFactory: Don't know how to manufacture that object
type.\nEnsure that FACTORY_REGISTER_CLASS is used." << endl;
return manufactured;
}

// Clone an object using the class name of the cloned object
template <class manufacturedObj>
shared_ptr<manufacturedObj>
objectFactory<manufacturedObj>::clone(shared_ptr<m anufacturedObj> pToClone)
const
{
cout << "clone(shared_ptr<manufacturedObj> pToClone) const" << endl;
shared_ptr<manufacturedObj> manufactured;
typename FN_CLONE_REGISTRY::const_iterator
regEntry=CloneRegistry.find(pToClone->ClassName());
if (regEntry != CloneRegistry.end())
manufactured =
shared_ptr<manufacturedObj>((*regEntry).second(pTo Clone.get()));
else
cout << "objectFactory: Don't know how to clone that object type.\nEnsure
that FACTORY_REGISTER_CLASS is used." << endl;
return manufactured;
}

// Assemble a new manufacturedObj using the list of string tokens and
iterator supplied
template <class manufacturedObj>
shared_ptr<manufacturedObj>
objectFactory<manufacturedObj>::assemble(list<std: :string> &is,
list<string>::const_iterator& i) const
{
cout << "assemble" << endl;
string strObjType, strObjName;
list<string>::const_iterator start = i;
while ((i != is.end()) && ((*i).find("XSIL") == string::npos)) i++;
// Read back the object name, if it is present
while ((i != is.end()) && ((*i).find("Type") == string::npos)) i++;
while ((i != is.end()) && ((*i).find("=") == string::npos)) i++;
i++; strObjType = *i;
shared_ptr<manufacturedObj> ret;
typename FN_REGISTRY::const_iterator regEntry=registry.find(strObjType);
if (regEntry != registry.end())
ret.reset((*regEntry).second());
i = start;
ret->XML_Read(is, i);
return ret;
}

// ************************************************** **********
// Helper template to make registration painless and simple
// ************************************************** **********
template <class ancestorType,
class manufacturedObj>
class registerInFactory
{
public:
static ancestorType* createInstance()
{
cout << "createInstance()" << endl;
return (ancestorType*)(new manufacturedObj);
}
static ancestorType* cloneInstance(ancestorType * pObjToClone)
{
cout << "cloneInstance(ancestorType * pObjToClone)" << endl;
manufacturedObj * pDerivedToClone = new manufacturedObj;
*pDerivedToClone = *((manufacturedObj*)pObjToClone);
// pDerivedToClone = (manufacturedObj*) pObjToClone;
// cout << "Cloning " << pObjToClone->GetID() << endl;
// return (ancestorType*)(new
manufacturedObj(*((manufacturedObj*)pObjToClone))) ;
return (ancestorType*)pDerivedToClone;
}
registerInFactory(const string id)
{
m_strClassName.assign(id);
objectFactory<ancestorType>::instance().regCreateF n(m_strClassName,
createInstance);
objectFactory<ancestorType>::instance().regCloneFn (m_strClassName,
cloneInstance);
cout << "registerInFactory: \"" << m_strClassName << "\"" << endl;
}
protected:
string m_strClassName;
};

#endif
Jul 22 '05 #1
2 2946
Ryan Mitchley wrote:
Hi all

I have code for an object factory, heavily based on an article by Jim Hyslop
(although I've made minor modifications). The factory was working fine using
g++, but since switching to the Intel compiler it has stopped working. I
think the singleton pattern static instance thing may be at the root of the
problem, but I'm not sure. I had to add calls to instance() in regCreateFn,
which gets the behaviour more in line with what I was expecting during
static initialization (the objects all register with the same registry). I
have tried playing with the MS compatibility options of the Intel compiler,
with no success.


I have no idea, but creating singleton instances of factory registries
is a tricky thing to do when messing with DLL's and template instances
all around.

May I suggest an alternative ? I released the Austria C++ library a few
weeks ago that does implement a generic factory mechanism and it does
deal with DLL/DSO hell. I have not tested it with the intel compiler.

This is an example taken from the Austria test case.
class Interface
{

public:

virtual const char * Thingy() = 0;
virtual const char * Thingy1() = 0;
virtual const char * Thingy2() = 0;

bool * mark_del;

Interface()
: mark_del( 0 )
{
}

virtual ~Interface()
{
if ( mark_del )
{
* mark_del = true;
}
}

void MarkPtr( bool * i_mark_del )
{
mark_del = i_mark_del;
}

virtual int ContructParamCount() = 0;

};
class Implementor
: public Interface
{

public:

virtual const char * Thingy()
{
return m_str;
}

virtual const char * Thingy1()
{
return m_str2;
}

virtual const char * Thingy2()
{
return m_str3;
}

Implementor( const char * str, const char * str2, const char * str3 )
: m_str( str ),
m_str2( str2 ),
m_str3( str3 ),
contruction_parameter_count( 3 )
{
}

Implementor( const char * str, const char * str2 )
: m_str( str ),
m_str2( str2 ),
contruction_parameter_count( 2 )
{
}

Implementor( const char * str )
: m_str( str ),
contruction_parameter_count( 1 )
{
}

Implementor()
: m_str( "Empty" ),
contruction_parameter_count( 0 )
{
}

virtual int ContructParamCount()
{
return contruction_parameter_count;
}

int contruction_parameter_count;

const char * m_str;
const char * m_str2;
const char * m_str3;
};
AT_MakeFactory1P( "ImplementorKEY", Implementor, Interface, DKy, const
char * );
AT_MakeFactory2P( "ImplementorKEY", Implementor, Interface, DKy, const
char *, const char * );
AT_MakeFactory3P( "ImplementorKEY", Implementor, Interface, DKy, const
char *, const char *, const char * );

AT_MakeFactory0P( "ImplementorKEY", Implementor, Interface, DKy );
http://austria.sourceforge.net
http://austria.sourceforge.net/dox/h...8h-source.html

The build system may not work for you, however the Austria build is
fairly easy to configure.
Jul 22 '05 #2
Ryan Mitchley wrote:
Hi all

I have code for an object factory, heavily based on an article by Jim
Hyslop (although I've made minor modifications). The factory was
working fine using g++, but since switching to the Intel compiler it
has stopped working. I think the singleton pattern static instance
thing may be at the root of the problem,


This could be a platform dependent problem. Can give more details?

=> What's the OS?
=> are the factories registered/used in a dll/dso?
=> if so, how do link to the dll/dso? Directly, through an import
library or do you use something like LoadLibrary/dlopen?
=> What version did the g++ compiler have that used to work and what
version of Intel's compiler are you trying to use now?

Marco


Jul 22 '05 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
by: Medi Montaseri | last post by:
Hi, Given a collection of similar but not exact entities (or products) Toyota, Ford, Buick, etc; I am contemplating using the Abstraction pattern to provide a common interface to these products....
8
by: Alex Vinokur | last post by:
=========== Windows 2000 Intel C++ 8.0 =========== ------ foo.cpp ------ int main () { for (int i = 0; i < 10; i++); for (int i = 0; i < 10; i++);
5
by: Lars Schouw | last post by:
I have downloaded the newest boos release. I am havng problems building boost using the intel C++ 8.0 compiler. It looks as if bjam can't fine the icl.exe compiler executable itself. This file is...
1
by: Gregg Altschul | last post by:
I have a Shared Object which its sole purpose is to create objects of a certain type and return a pointer to the object to the user. Therefore, the user becomes the owner of this object and is...
6
by: BBM | last post by:
I have an object that has a fairly complex construction sequence, so I have written a dedicated "factory" class that invokes the constructor of my object class (which does nothing but instantiate...
11
by: Kevin Prichard | last post by:
Hi all, I've recently been following the object-oriented techiques discussed here and have been testing them for use in a web application. There is problem that I'd like to discuss with you...
2
by: Faheem Mitha | last post by:
Hi, The following bit of code compiles fine with gcc 3.3 or later, but has problems with the Intel C++ compiler version 9.1, which produces the following error message. Is this a compiler...
1
by: orel | last post by:
Please, As i tried hundreds different implementation to make it work and actually didn't succeed, can someone here help me to understand and use the implementation of the Object Factory design...
16
by: Alex | last post by:
Hello, I'm trying to use a (remote) COM object from a PHP script (4.4, server has apache2 win32). The basics seem to work : I instantiate the COM object ($o = new COM"..."), then I use two of...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.