multithreading - How to send signal from Singleton thread to another thread (Not singleton) -
i'm facing problem while creating singleton class it's own thread sends signal thread not singleton class.
consumer.h
class consumer : public qthread { q_object public: explicit consumer(qobject *parent = 0); consumer(worker *worker); signals: void tomessage(const bool& keepcycle); public slots: void getmessage(const qstring& str); private: int m_counter; };
consumer.cpp
consumer::consumer(qobject *parent) : qthread(parent) { m_counter = 0; connect(worker::instance(), signal(sendmessage(qstring)), this, slot(getmessage(qstring))); connect(this, signal(tomessage(bool)), worker::instance(), slot(frommessage(bool))); } // get's message singleton thread if counter > 5 sends signal terminate cycle in singleton thread void consumer::getmessage(const qstring &str) { m_counter++; if(m_counter <= 5) { qdebug() << "got message " << m_counter << ": " << str << "\n"; return; } else { emit tomessage(false); } }
singleton done follows (suspect it's not thread-safe):
template <class t> class singleton { public: static t* instance() { if(!m_instance) m_instance = new t; assert(m_instance != null); return m_instance; } protected: singleton(); ~singleton(); private: singleton(singleton const&); singleton& operator=(singleton const&); static t* m_instance; }; template <class t> t* singleton<t>::m_instance = null;
and worker singleton class
class worker : public qthread { q_object public: explicit worker(qobject *parent = 0); void run(); signals: void sendmessage(const qstring& str); public slots: void frommessage(const bool& keepcycle); private: volatile bool m_keepcycle; }; typedef singleton<worker> worker;
worker.cpp
worker::worker(qobject *parent) : qthread(parent) { m_keepcycle = true; } void worker::run() { while(true) { if(m_keepcycle) { qstring str = "what's up?"; elworker::instance()->sendmessage(str); } else { qdebug() << "keep alive" << false; break; } } qdebug() << "value of keepcycle" << m_keepcycle; } void worker::frommessage(const bool &keepcycle) { m_keepcycle = keepcycle; qdebug() << "\nmessage from: " << keepcycle << "\n"; }
the main.cpp
consumer consumer; elworker::instance()->start(); consumer.start();
can me create thread-safe singleton , send signals between threads?
first of all, highly recommended separate worker it's thread:
class object : public qobject { ... public slots: void onstarted(); // if needed void onfinished(); // if needed ... }; ... mobject = qsharedpointer < object >(new object); mthread = new qthread(this); mobject->movetothread(mthread); connect(mthread, signal(started()), mobject, slot(onstarted())); // if needed connect(mthread, signal(finished()), mobject, slot(onfinished())); // if needed mthread->start();
second of all, there lot of ways of creating singleton. favourite this:
object * obj(qobject *parent = 0) { static object *mobj = new object(parent); return mobj; } ... obj(this); // creating obj()->dostuff(); // using
now, thread-safety. sending signals thread-safe, unless you're sending pointers or non-constant references. which, according code, not. so, should fine.
update
actually, didn't how created thread-safe singleton above , i'm sending signal worker consumer not thread itself? – hiken
- static values inside of function created , initialized once, first time call
obj
functionmobj
created , returned , each other time call it, createdmobj
returned. also, didn't say, it's thread-safe, said - way better, template one, because:- it simplier
- requires less code
- works
qobject
without problems
- yes, should send signals worker class, not thread one. qt's has example (the first one, not second one): http://doc.qt.io/qt-5/qthread.html#details. thing
qthread
should used - controlling thread's flow. there situations, when need deriveqthread
, rewriteqthread::run
, case isn't 1 of them.
Comments
Post a Comment