PDA

View Full Version : Make a QSharedPointer like class thread-safe with signal/slots



yayo56
9th August 2011, 22:02
Hi,

I create a class named SyncronizedPointer, it look like a QSharedPointer except that "->" operator make that all call become thread Safe here a simple example of use.



class Foo
{
void criticalMethod()
{
//All work done here is completely thred-safe
}
};

int main()
{

SyncronizedPointer<Foo> sp( new Foo() );

sp->criticalMethod();
/* This precedent line will automatically:
- Lock an mutex inside SyncronizedPointer object.
- Call the criticalMethod
- Unlock the mutex

With this system it's easy to make the Foo class thread safe, I can use copy of the
SyncronizedPointer object in multiple thread, I am sure that no more than one thread can
call a method inside Foo object at the same time.
*/

return (0);
/*
The Foo object will be automatically delete using a reference counting inside SyncronizedPointer.
*/
}



So my problem is when I am trying to use SyncronizedPointer with QObject like




class Foo : public QObject
{
Q_OBJECT

public:

void criticalMethod();

public slot:

void criticalSlot();
}

int main()
{
SyncronizedPointer<Foo> sp(new Foo());

/*
Here no problem I can send the sp var across thread, call to criticalMethod will stay
thread safe.
*/

QTimer timer;

/*
Now I want to connect the timer timeout signal to the criticalSlot
Note that call to this slot MUST be totaly thread safe
*/
QObject::connect(&timer, SIGNAL(timeout()), sp->data(), SLOT(criticalSlot()));

/*
The precedent line does not protect the access to the Foo class because Qt signal system
will directly call the slot without locking the Mutex inside the SyncronizedPointer
*/

return (0);
}



Is there a solution to make this work, for example by making Qt call the slot using the
SyncronizedPointer object ?


An easy way would be to put the mutex inside the Foo class and lock it inside both slot and method
but the code would be much less sexy :p


PS: Sorry if my English is not perfect.

soft0613
10th August 2011, 16:46
If I understand your problem you want your pointer to act like a decorator for your instance of QObject. No matter what's called on the object you want the code to go through the operator overloading of the pointer first to synchronize the call and then delegate the execution to the object.

Let me be honest, there's no such a thing in C++ (I'm talking about decorators).

But it doesn't mean it's not possible with Qt. The problem is that you connect the signal to your object, so the compiler has no idea about the SynchronizedPointer that's taking care of it.
What should be done is connecting the signal to the SynchronizedPointer instead, then delegate the execution to the encapsulated object's slot when the pointer receives the signal. You probably need to look deeper into Qt's meta objects and reflection documentation to come out with a generic solution but if that's not possible then you would need to write one pointer class for each type you want to decorate (not very exciting).

PS : If the sexy solution works try writing a generic Decorator class, that would be awesome.