PDA

View Full Version : Dynamic creation of Singleton



remizero
2nd June 2016, 19:15
Hello everyone.

I have a Singleton (which must be done to ensure that only has a single instance of that object) class, in fact Singleton is a set of classes that inherit from the same abstract class base.

It is required that this set of Singleton classes are created dynamically, depending on the object to the request, these will be created, and if they already exist, assigned to that object if and when the active object.

To create this set of Singleton classes, I am working with the factory pattern design method implemented with QMetaObject and QMetaMethod on demand.

My problem is the following:

By using QMetaMethod :: Invoke (...), I requested an object to run the Singleton :: instance () method;

My question is: How can I do to run this method (Singleton :: instance ()), even if I do not have an instance of it?

Now, is there another way to create an object and ensure that there is only a single instance of it? Rather work with the Singleton pattern because I require no further verification and / or validation for use.

Additional, put them programming for dynamic creation of these classes Singleton:

.h Code


#include "ParseAbs.h"
#include "ParseCpp.h"
#include "ParseHtml.h"
#include "ParseJavascript.h"
#include "ParsePhp.h"
#include "ParseQt.h"
#include "ParseXml.h"

#include <QHash>
#include <QMetaMethod>
#include <QMetaObject>

class ParseFac {

public:
static ParseAbs *create ( const QString &ParseType, QTextDocument *parent );
};


.cpp Code


#include <QDebug>

typedef QHash<QString, QMetaObject> T_Parses;

T_Parses parsesTypesList () {

T_Parses hash;

hash [ "ParseCpp" ] = ParseCpp::staticMetaObject;
hash [ "ParseHtml" ] = ParseHtml::staticMetaObject;
hash [ "ParseJavascript" ] = ParseJavascript::staticMetaObject;
hash [ "ParsePhp" ] = ParsePhp::staticMetaObject;
hash [ "ParseQt" ] = ParseQt::staticMetaObject;
hash [ "ParseXml" ] = ParseXml::staticMetaObject;

return hash;
}

ParseAbs *ParseFac::create ( const QString &parseType , QTextDocument *parent ) {

T_Parses parsesType = parsesTypesList ();

ParseAbs *parseCreated = 0;

if ( parsesType.contains ( parseType ) ) {

const QMetaObject& metaObjectClass = parsesType [ parseType ];

// Here I try to get the method I want to run
//const QMetaMethod& metaMethodObjectClass = metaObjectClass.method ( metaObjectClass.indexOfMethod ( "getInstance" ) );
//metaMethodObjectClass.invoke ( "what kind of object place here?" );

// Here I try to create the object, but obviously I can not create
parseCreated = qobject_cast<ParseAbs *> ( metaObjectClass.newInstance ( Q_ARG ( QTextDocument*, parent ) ) );

if ( parseCreated == 0 ) {

qDebug () << "Error creating " << parseType;
abort ();
}
} else {

qDebug () << "Error creating " << parseType;
abort ();
}
return parseCreated;
}


The following lines of code are those that want to run, but not as assigning the respective class:


//const QMetaMethod& metaMethodObjectClass = metaObjectClass.method ( metaObjectClass.indexOfMethod ( "getInstance" ) );
//metaMethodObjectClass.invoke ( "what kind of object place here?" );


Thanks in advance for your answers.

anda_skoa
2nd June 2016, 22:32
Make the factory the singleton and let it create normal objects on demand when they don't exist yet.

Cheers,
_

remizero
3rd June 2016, 01:17
Anda_skoa Hi, thanks for responding so quickly.

This solution you offer me the thought too, but I have a problem with it, and then have to identify that or those created to allocate to other objects.

I have to create a multi editor tabs, and those singleton to create, I must assign dynamically to the current tab, so I find it very convenient to create them as singleton rather than as normal objects, it would have to inspect the object stack to verify if it exists, if it does not create it, and so every time you change tab, I think it's not a good idea to do so much unnecessary work that way also consumes resources.

Anyway, thank you very much for your contribution, I will continue investigating how to create these Singleton and when you have the answer I comment

anda_skoa
3rd June 2016, 08:40
I am not sure what you mean.

Checking if you have created an object before would be a simple lookup, assuming you store the created obejcts in an associative container such as a hash.

So first ParseFac::create() would check the hash with the existing objects and only continue with creation if it can't find an existing one.

Cheers,
_

remizero
5th June 2016, 16:51
Hello everyone again.

After investigating for several days, sadly it seems there is no way to invoke a static method without a previous instance of the class. It made me rethink the requested injunction.

First of all, when working with a Singleton, I'm guaranteeing a single instance of the object to create (for here going well so far).

On the other hand, the idea of ​​working with a factory Singletons, was simply to automate the creation of the same on demand, but this is where I presented the issue with the factory objects, for I have not got any way to invoke a static method without having a previous instance of the class.

But as every editor knows that objects analyzers have to create, then it was here that I decided not to work with factory objects and create objects analyzers "manually" because when recreate a new editor for the required language, this with only "create" again objects analyzers requiring not he is actually creating, because, if it were created (because there is already another editor for the same language) then just get the instance of the parser object Singleton and assigned to this new editor.

I hope this analysis will serve useful to someone else who has a similar problem.

PD: I terminated and solved this thread, but I can not locate where to place fixed or modify the title to identify it as solved

anda_skoa
5th June 2016, 21:21
First of all, when working with a Singleton, I'm guaranteeing a single instance of the object to create (for here going well so far).

Which of course would also be the case if the factory itself was a singleton.



On the other hand, the idea of ​​working with a factory Singletons, was simply to automate the creation of the same on demand, but this is where I presented the issue with the factory objects, for I have not got any way to invoke a static method without having a previous instance of the class.

A static member function can be stored as a function pointer, for example.

Cheers,
_

d_stranz
5th June 2016, 22:22
sadly it seems there is no way to invoke a static method without a previous instance of the class.

That's not true at all. Static methods do not require any class instance to invoke. You use the syntax:



result = MyClass::myStaticMethod();


A common way to implement a Singleton class is to use a static class method along with a static pointer:




// MyClass.h
class MyClass
{
private:
MyClass * pInstance;

MyClass();
~MyClass();

public:
static MyClass * instance()
{
if ( !pInstance )
pInstance = new MyClass();

return pInstance;
}

};

// MyClass.cpp;
MyClass::pInstance * instance = 0;

MyClass * pSingleton = MyClass::instance();


This leaves a dangling pInstance memory leak when the program exits, but you can implement code to clean that up if necessary.

remizero
6th June 2016, 01:31
Hi d_stranz.

I fully understand what you say, I know how to call a static method.

I am referring to the invocation of a static method without instance through QMetaObject :: InvokeMethod (), work with this class makes it impossible to invoke a static method without instance: s.

But thanks for your good intentions