ATL COM: Access Event Methods From Other Thread - c++

I'm implementing a COM interface to an existing VS2010 C++ MFC-application. Most parts of the COM interface interaction works great, but I am confused of how to trigger COM events from another thread that the one where the COM interface is running / defined. The application is multi-threaded with one main thread running the COM interface and handling GUI changes (thread 1) and one thread to receive incoming messages from a C-library (thread 2).
For certain messages received in thread 2 I want to notify the COM clients by sending a COM event. I have read many threads (Firing COM Event From Another Thread is one of them) and CoMarshalInterThreadInterfaceInStream / CoGetInterfaceAndReleaseStream is mentioned. Using Google I can't seem to find any usage of these methods that makes any sense to me; I just don't understand how to implement these functions and if they really will help me.
Relevant code parts:
TestCOM.idl: (the interface definition)
interface ITestCOM: IDispatch
{
[id(1), helpstring("method Test")] HRESULT Test();
};
dispinterface _ITestCOMEvents
{
properties:
methods:
[id(1), helpstring("event ExecutionOver")] HRESULT TestEvent();
};
coclass TestAppCOM
{
[default] interface ITestCOM;
[default, source] dispinterface _ITestCOMEvents;
};
ITestCOMEvents_CP.h (VS generated class for Connection Points / events)
template<class T>
class CProxy_ITestCOMEvents :
public ATL::IConnectionPointImpl<T, &__uuidof(_ITestCOMEvents)>
{
public:
HRESULT Fire_TestEvent()
{
HRESULT hr = S_OK;
T * pThis = static_cast<T *>(this);
int cConnections = m_vec.GetSize();
for (int iConnection = 0; iConnection < cConnections; iConnection++)
{
pThis->Lock();
CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
pThis->Unlock();
...
TestCOM.h (class implementing the methods and CProxy_ITestCOMEvents class)
class ATL_NO_VTABLE CTestCOM :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CTestCOM, &CLSID_TestCOM>,
public IConnectionPointContainerImpl<CTestCOM>,
public CProxy_ITestCOMEvents<CTestCOM>,
public IDispatchImpl<IMecAppCOM, &IID_ITestCOM, &LIBID_TestLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
static CTestCOM * p_CTestCOM;
CTestCOM()
{
p_CTestCOM = this;
}
Incoming.CPP (a class running on thread 2 that should trigger an event in the following case statement)
case INCOMING_EVENT_1:
// Trigger Fire_TestEvent in thread 1
// CTestCOM::p_CTestCOM->Fire_TestEvent(); trigger event on thread 2
In the code above you can find my current workaround for this problem which is to create a pointer object p_CTestCOM that will allow any class running on thread 1 to trigger the COM events. Thread 2 can access that object but it would trigger it in thread 2, which wouldn't work. To solve this all methods defined in Incoming.CPP could post a message (using PostMessage()) to thread 1 which would use p_CTestCOM to access and send the COM event. This would work, but I am sure there must be a better (and safer) solution that more accurately follows the COM design principles.
I someone could shed some light I would be most grateful!

Roman R. provides some good options but there is a better alternative, IMO: you can marshal the listeners to the thread which fires the event. As advising the listeners is typically done inside IConnectionPointImpl class in an ATL project, you 'just' need to modify the default IConnectionPointImpl to do the marshalling for you (e.g. via GIT which is simpler that marshaling API).
The big advantage is that the rest of the code remains almost the same as before, so no message passing or synchronization is needed - only the generated *CP.h file needs to be updated.
The implementation is discussed in Microsoft knowledge base article KB280512 which seems to be removed now, but there is an improved implementation by PJ Naughter which you can use to replace the default implementation.
Here's the version that I use, based on the missing KB article.
The usage is simple, just rename the class in the generated CP.h file and modify m_vec.GetAt parts, as described in the gist I have linked.

The important thing to start with is the threading model of your COM object. It is is MTA, then you might want to simply initialize your worker thread respectively with COM, with CoInitializeEx(NULL, COINIT_MULTITHREADED) and fire events right from there.
If the object is STA, which is most likely the case, and what might be necessary e.g. to well integrate the object with some environments, then you need to fire events from the main thread, and to get there from the worker thread you need to use some synchronization. For example, on your worker thread you discover a need to fire an event. You code might set a flag or an internal synchronization object (such as event) so that main thread code would eventually notice it and proceed with raising an external event from there.
Another common solution for STA COM object is to create in advance a hidden/message-only window so that a worker thread could post a message on it. The message will be dispatched to the window's procedure on window creation thread, that is on STA thread and the message handler would be a safe place to fire COM event from.
Alternatively you can create an internal COM object and marshal it into worker thread to create a proxy/stub pair, and have your call from worker thread automatically converted into call of your method on main thread through marhsaling. This is workable but inferior to window messaging in almost every way: your interface/object needs to be suitable for proxy/stub pair creation, COM call is blocking while with a windows message you always have a choice between SendMessage and PostMessage, and it is the latter you wlil want to prefer to avoid deadlocks in interthread communication.

Related

create `wxThread` to call backend function for every `EVT_TREELIST_ITEM_EXPANDED` event

I have following classes:
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_TREELIST_ITEM_CHECKED(wxID_ANY, MyFrame::OnItemChecked)
EVT_TREELIST_ITEM_EXPANDED(wxID_ANY, MyFrame::OnItemExpand)
END_EVENT_TABLE()
class MyThread: public wxThread
{
public:
MyThread(MyFrame *frame, wxTreeListItem &item);
virtual void *Entry();
SeleSyncFrame *m_frame;
wxTreeListItem item;
};
class MyFrame
{
friend class MyThread;
private:
wxTreeListCtrl* m_treelist;
public:
void OnItemExpand(wxTreeListEvent& event);
};
I have to update m_treelist on every EVT_TREELIST_ITEM_EXPANDED event. For that I am calling OnItemExpand().
void MyFrame::OnItemExpand(wxTreeListEvent& event)
{
wxTreeListItem item = event.GetItem();
MyThread *thread = new MyThread(this, item);
if (thread->Create() != wxTHREAD_NO_ERROR)
{
dbg.Error(__FUNCTION__, "Can't create thread!");
}
thread->Run();
}
constructor of MyThread class:
MyThread::MyThread(MyFrame *frame, wxTreeListItem &item) : wxThread()
{
m_frame = frame;
this->item = item;
}
Entry function of MyThread:
wxThread::ExitCode MyThread::Entry()
{
wxTreeListItem root = m_frame->m_treelist->GetRootItem();
m_frame->m_treelist->CheckItem(root, wxCHK_CHECKED);
//This back-end fun is time consuming
Calltobackend(string resp);
// I have to convert this string resp into xml and append all items of xml as children for 'item'.
(m_frame->m_treelist)->AppendItem(item, "child");
m_frame->m_treelist->CheckItem(item, wxCHK_CHECKED);
m_frame->m_treelist->UpdateItemParentStateRecursively(m_frame->m_treelist->GetFirstChild(item));
return NULL;
}
I want to create thread for every browse request and update corresponding item with its children. Is my approach is not correct? How should I achieve this? I was thinking of one more approach where I will use thread only to send request to backend and I will send response to Main thread using OnWorkerEvent. But I have to update item which is expanded with response returned by backend. How will that OnWorkerEvent will know which item from tree it has to update with children returned by response?
As VZ said, updating GUI from a different thread is a can of worms. Don't do it.
For your issue. Let's say you have to update a control (in your case, items of a treelist) with values that come from a long task.
The idea is simple:
On your user event handler (like OnItemExpand) just create and run
the thread. Don't wait for it, make it "detached".
In the thread code, just before it ends, post a message to the main thread by wxQueueEvent(). The value you need may be part of this message. Or
you can also write an accesible var, better using wxMutex; and use
the message to inform the main thread that that var is updated.
Write a new function (e.g. a MyFrame::OnMyThreadEnds) than handles the message and/or var. Here is where you update the GUI.
See http://docs.wxwidgets.org/trunk/classwx_thread.html
You can only use GUI objects from one (usually main) thread of your application, so your approach simply can't work. It's also not clear at all why would you go to the trouble of creating a thread just for doing this, it's not like there are any time-consuming operations being done in the thread here.
The standard way to use threads in GUI applications is to perform any long-running tasks in background worker threads and post events to the main thread to perform the GUI updates. You should structure your application like this unless you have really good reasons not to do it.
In more details, the traditional way to do it is for the worker thread to post wxThreadEvents to the main thread, containing the information that the main thread needs to perform the action. Notice that wxThreadEvent has SetPayload() method which allows you to pass any kind of data between threads, so you just need to call it in the worker and then use GetPayload() in the main thread to extract the information and process it.
However since wxWidgets 3.0 you have another way to do it with CallAfter(), which is especially convenient if you use C++11 (and you really should). This allows you to write the code you want to execute in the scope of the thread function, but it will actually get executed in the context of the main thread. So you could do this:
wxThread::ExitCode MyThread::Entry()
{
wxGetApp().CallAfter([this] {
wxTreeListItem root = m_frame->m_treelist->GetRootItem();
m_frame->m_treelist->CheckItem(root, wxCHK_CHECKED);
});
...
}
and it would actually work because the code inside the lambda would be run in the main thread. This is extremely convenient and you should do it like this, but just make sure you actually understand what does this do and that it still uses the same underlying mechanism of posting events to do its magic.

Is creating a separate thread for a logger ok?

I'm writing a multithreaded application in Qt (several threads with their own event loops). When logging I want the logger to include a thread id (they have meaningful names) into the log. Qt default logger seems incapable of doing this.
So I have three options:
every thread does logging by itself (this involves mutexes, so is probably the worst approach, but I'm not sure)
There's a dedicated logger thread and other threads directly post events into it (probably faster, than 3.)
Same as 2. but the message is dispatched through the signal/slot system (in fact, this will result in posting an event as well).
Which one is better and what are best practices doing it in general?
Some things to clarify after questions in comments:
QThread has a standard method postEvent(), that is thread-safe.
So the question becomes, does the logger thread need to do enough work per event to justify the cost of marshaling the event's data across some sort of queue
That is the essence of the question. I know that the best answer is "Measure!", but currently the app is in an early development stage, there's not much what to measure. Also it's always good to choose the right design from the beginning.
In my case threads are probably a good idea: it's a media player, so there's GUI thread, playback thread, DB/Media library thread, network thread pool... The whole Zoo of threads in other words.
These are general remarks since I have no experience with Qt. With respect to the cost of queuing, in general: I/O usually lets other run time costs pale, so it should not matter.
Properties of a dedicated logging thread:
Good: Minimal impact on runtime behavior of the program.
Good: Guaranteed single log messages (not intermixed output from several threads).
Bad: Significant implementation effort.
Bad: The time of initiating and actually performing the logging are decoupled (that is the whole point!). You may see logging output not where you expect it.
Bad: a terminating program may swallow the last and most important log messages (Andreas' point), so you may want to add a synchronous log function (this is an extreme of the point above).
The (dis)advantages of logging from each thread directly are the inverse of the above. No two threads can log at the same time (either because functions like printf() implicitly lock a FILE, or because you synchronize the log function explicitly); this makes all threads which want to log block until the current thread is done. If logging is done for debugging purposes one may want to log unbuffered (so that the data is not lost in the event of a subsequent crash), which exacerbates the run time impact.
How bad that is depends on the nature of the application as well as the logging mechanism and amount of data.
I have implemented logging mechanisms for Qt applications in a nice clean way using the Qt Event mechanism.
In a Qt application there is a single instance of QApplication representing the application.
You can create your own events by inheriting from QEvent, and post them and handle them using the QApplication object for the application.
So for example you might have your log event class
MyLogEvent : public QEvent
{
public:
MyLogEvent(QString threadId, QString logMessage) : QEvent(QEvent::User)
{ /* Store the ThreadID and log message, with accessor functions */};
}
And you can post events from any Qt thread using
MyLogEvent *event = new MyLogEvent(QString("Thread 1"), QString("Something Happened"));
QApplication::postEvent(mainWindow, event);
The handler could be a main window object (if you want to log to a window), or a dedicated object if you want to e.g. log to a file.
In the object handling the events, override QObject::event to handle the log messages
bool MainWindow::event(QEvent *e)
{
if(e->type()==QEvent::User)
{
// This is a log event
MyLogEvent *logEvent = static_cast<MyLogEvent *>(e);
ui.textEdit->appendPlainText(logEvent->logMessage())
return true;
}
return QMainWindow::event(e);
}
I don't quite understand why every thread doing logging by itself would need to use an explicit mutex.
If you're logging to a disk file, then every thread can be logging to its own file. You can name the files with a common prefix:
QFile * logFile(QObject * parent = nullptr) {
auto baseName = QStringLiteral("MyApplication-");
auto threadName = QThread::currentThread()->objectName();
if (threadName.isEmpty())
return new QTemporaryFile(baseName);
else
return new QFile(baseName + threadName);
}
The operating system is serializing access via its filesystem mutex(es).
If you're logging to a database that supports concurrent access, such as sqlite with proper concurrency options selected, the database driver will take care of serializing access.
If you're logging to a common thread, then the event queue has a mutex that you automatically serialize with when you postEvent.
You're right that using the signal-slot mechanism doesn't buy you much over using events directly. In fact, it's guaranteed to perform more memory allocations, so you should prefer posting an event yourself, ideally an event that uses a QVarLengthArray<char> of a size that fits "most" of the log messages. Then, allocating such an event is done with a single malloc call:
// logger.h
struct MyLogEvent : QEvent {
constexpr static QEvent::Type theType() { return (QEvent::Type)(QEvent::User + 1); }
QVarLengthArray<char, 128> message;
MyLogEvent(const char * msg) : QEvent(theType()) {
message.append(msg, strlen(msg));
}
};
class Logger : public QObject {
...
public:
static void log(const char * msg) {
QCoreApplication::postEvent(instance(), new MyLogEvent(msg));
}
static Logger * instance(); // singleton, must be a thread safe method
};
// logger.cpp
...
Q_GLOBAL_STATIC(Logger, loggerInstance);
Logger * Logger::instance() {
// Thread-safe since QGlobalStatic is.
return loggerInstance;
}
Had you used a QByteArray or a QString, the expression new MyLogEvent would have performed at least two allocations.

Event system similar to C# (.NET?)

In C# (at least using .NET, but I think it's general), you can create events like this: Understanding events and event handlers in C#.
Is there a similar mechanism for C++?
PS: I've never liked signal/slot system, so please don't suggest it, since I'm already using it and would love to switch to something else.
The event mechanism in C# is really just a formal, language implemented version of the Observer Pattern. This pattern can be implemented in any language, including C++. There are many examples of implementations in C++.
The largest and most common implementation is probably Boost.Signals and Boost.Signals2, though you explicitly mentioned not liking the signal/slot style implementations.
Event.h can be downloaded from the link bellow, it provides a .NET like Event implemented in C++: http://www.codeproject.com/Tips/1069718/Sharp-Tools-A-NET-like-Event-in-Cplusplus
An example of its usage:
#include "Event.h" // This lib consists of only one file, just copy it and include it in your code.
// an example of an application-level component which perform part of the business logic
class Cashier
{
public:
Sharp::Event<void> ShiftStarted; // an event that pass no argument when raised
Sharp::Event<int> MoneyPaid; // will be raised whenever the cashier receives money
void Start(); // called on startup, perform business logic and eventually calls ProcessPayment()
private:
// somewhere along the logic of this class
void ProcessPayment(int amount)
{
// after some processing
MoneyPaid(amount); // this how we raise the event
}
};
// Another application-level component
class Accountant
{
public:
void OnMoneyPaid(int& amount);
};
// The main class that decide on the events flow (who handles which events)
// it is also the owner of the application-level components
class Program
{
// the utility level components(if any)
//(commented)DataStore databaseConnection;
// the application-level components
Cashier cashier1;
Accountant accountant1;
//(commented)AttendanceManager attMan(&databaseConnection) // an example of injecting a utility object
public:
Program()
{
// connect the events of the application-level components to their handlers
cashier1.MoneyPaid += Sharp::EventHandler::Bind( &Accountant::OnMoneyPaid, &accountant1);
}
~Program()
{
// it is recommended to always connect the event handlers in the constructor
// and disconnect in the destructor
cashier1.MoneyPaid -= Sharp::EventHandler::Bind( &Accountant::OnMoneyPaid, &accountant1);
}
void Start()
{
// start business logic, maybe tell all cashiers to start their shift
cashier1.Start();
}
};
void main()
{
Program theProgram;
theProgram.Start();
// as you can see the Cashier and the Accountant know nothing about each other
// You can even remove the Accountant class without affecting the system
// You can add new components (ex: AttendanceManager) without affecting the system
// all you need to change is the part where you connect/disconnect the events
}
If boost is not an option, I implemented events in c++ here. The semantics is almost the same as in .NET . It's a compact implementation but uses quite advanced C++ features: a modern C++11 compiler is required.

How to write simple background thread in CWorkerThread

I'm trying to asynchronously run function in my add-on for Internet Explorer (I'm writing BHO in VC++). As suggested here I'm trying to use CWorkerThread.
I've been trying to figure it out for hours but still have no idea how to do it. I don't have much experience in ATL. The lack of a good documentations or tutorials on Internet is killing me.
I'm creating class by Add->Class and choosing ATL Simple Object (that's how you add classed to ATL project right?). But how to implement this IWorkerThreadClient? I thought that choosing Add->Implement Interface in Class View would be good but there is no IWorkerThreadClient on the list.
I think I don't know ATL or COM enaugh but can't find good resource for learning this (esspessialy newest ATL7).
I even tried winapi CreateThread approach but it isn't working. I'm passing this class pointer to run static method but something is corrupting with memory later. Nevertheless if It had worked I still would rather use something else than CreateThread.
Right now I have something like this. In OnDocumentComplete there's RemoveImages(sptmlDoc) and I just want to run it asynchronously.
EDIT: What I did with CreateThread:
I tried running RemoveImages function (from here) asynchronously. I created static function in my class with signature like here. RemoveImages has parameter so I copied it to a member of a class:
if (htmlDoc2 != NULL)
{
m_tmpHtmlDocument2 = htmlDoc2;
m_hThread = CreateThread( NULL, 0, MyThreadFunction, this, 0, &m_threadId);
}
and MyThreadFunction:
static DWORD WINAPI MyThreadFunction( LPVOID lpParam )
{
CHelloWorldBHO* myClass = (CHelloWorldBHO*)lpParam;
myClass->RemoveImages(myClass->m_tmpHtmlDocument2);
return 0;
}
I get "Unhandled exception at 0x60c0da05 in iexplore.exe: 0xC0000005: Access violation reading location 0x000001b8." here in the bold line:
void CHelloWorldBHO::DontDisplayElement(CComPtr htmlElement)
{
CComPtr style;
HRESULT hr = htmlElement->get_style(&style);
if (hr == S_OK && style != NULL)
{
static const CComBSTR strNone(L"none");
style->put_display(strNone);
}
}
Your performing a naughty by trying to use a COM handle allocated in 1 thread in another. BHO environment is STA (Single Threaded Apartment) so you should be marshalling the m_tmpHtmlDocument2 object for use in your thread.
Experiance has shown that in some cases IE may let you get away with passing the Browser com object from 1 thread to another and then getting the document and elements afterwards may work. This is entirely unreliable.
Depending on IE 6/7/8 you will have different target threads to execute your actions on, thinking at the levels of per security level/frame/tab/window. basically any time IE creates a new 'Site'
Also to prevent your app from holding the pages active even after navigation away from the page, in FireFox you would use an nsWeakPointer<> , I've never found the equivelant in IE.
Suggestion: Perhaps instead of marshalling com to another thread because your interaction with the page is slow, trying to improve the way you interact with the page and improve performance in process might be a better aim.
Here is an outline using the CThreadPool which will queue up requests, and then execute them when the pool has space.
I use pvWorkerParam to tie the threads back to the site.
I have different types of ActionRequests, you could of course simplify and just pass null for the request.
Note: This doesn't resolve marshalling issues you already have
class ActionRequest{
DontDisplayElement();// define your do stuff in here
};
class ScriptWorker
{
public:
ScriptWorker(void);
virtual ~ScriptWorker(void);
public:
BOOL Initialize(void* pvWorkerParam);
void Execute(ActionRequest *request, void* pvWorkerParam, OVERLAPPED* pOverlapped){
try{
std::auto_ptr<ActionRequest> cleanupRequest(request);
request.DontDisplayElement();
} catch(...) {}
}
void Terminate(void* pvWorkerParam);
private:
boolean m_bCoUninit;
};
Site{
CThreadPool<ScriptWorker> m_scriptWorkerThread;
Site() {
void *pvWorkerParam = this;// or whatever you want to have passed to every script worker and execute in the pool.
m_scriptWorkerThread.Initialize( pvWorkerParam, 1 );
}
OnDocumentComplete() {
m_scriptWorkerThread.QueueRequest( new ActionRequest() );
}
}
and sptmlDoc - is it an IHTMLDocumet* ?
IWorkerThreadClient - never heard of it
"I even tried winapi CreateThread approach but it isn't working. I'm passing this class pointer to run static method but something is corrupting with memomory later"
Keeping it simple is the best design pattern of them all. So stick with CreateThread unless you have good reasons not to. Now, my guess is that the crash occurs because of sptmlDoc being passed to the thread for later processing. The thing is such pointers are only valid from the BeforeNavigate event until DocumentComplete event. Try to do that processing on the spot (inside your event handler) and see if it stil crashes. Some code posting would help too

Threading issues in C++

I have asked this problem on many popular forums but no concrete response. My applciation uses serial communication to interface with external systems each having its own interface protocol. The data that is received from the systems is displayed on a GUI made in Qt 4.2.1.
Structure of application is such that
When app begins we have a login page
with a choice of four modules. This
is implemented as a maindisplay
class. Each of the four modules is a
separate class in itself. The concerned module here is of action class which is responsible of gathering and displaying data from various systems.
User authentication gets him/her
into the action screen. The
constructor of the action screen
class executes and apart from
mundane initialisation it starts the
individual systems threads which are
implemented as singleton.
Each system protocol is implemented as a singleton thread of the form:
class SensorProtocol:public QThread {
static SensorProtocol* s_instance;
SensorProtocol(){}
SensorProtocol(const SensorProtocol&);
operator=(const SensorProtocol&);
public:
static SensorProtocol* getInstance();
//miscellaneous system related data to be used for
// data acquisition and processing
};
In implementation file *.cpp:
SensorProtocol* SensorProtocol::s_instance=0;
SensorProtocol* SensorProtocol::getInstance()
{
//DOUBLE CHECKED LOCKING PATTERN I have used singletons
// without this overrated pattern also but just fyi
if(!s_instance)
{
mutex.lock();
if(!s_instance)
s_instance=new SensorProtocol();
mutex.unlock();
}
}
Structure of run function
while(!mStop)
{
mutex.lock()
while(!WaitCondition.wait(&mutex,5)
{
if(mStop)
return;
}
//code to read from port when data becomes available
// and process it and store in variables
mutex.unlock();
}
In the action screen class I have define an InputSignalHandler using sigaction and saio. This is a function pointer which is activated as soon as data arrives on any of the serial ports.
It is a global function (we cannot change it as it is specific to Linux) which is just used to compare the file descriptors of the serial port where data has arrived and the fd's of the sensor systems, if a match is found WaitCondition.wakeOne is invoked on that thread and it comes out the wait and reads and processes the data.
In the action screen class the individual threads are started as SensorProtocol::getInstance()->start().
Each system's protocol has a frame rate at which it sends data. Based on this fact, in actions screen we set up update timers to time out at refresh rate of protocols. When these timers time out the UpdateSensorProtocol() function of operation screen is called
connect(&timer, SIGNAL(timeout), this,SLOT(UpdateSensorProtocol()));
This grabs an instance of sensor singleton as
SensorProtocol* pSingleton=SensorProtocol::getInstance();
if(pSingleton->mUpdate)
{
//update data on action screen GUI
pSingleton->mUpdate=false; //NOTE : this variable is set to
// true in the singleton thread
// while one frame is processed completely
}
For all uses of singleton instance SensorProtocol::getInstance() is used. Given the above scenario, One of my protocols is hanging no matter what changes I do.
The hang occurs in the while displaying data using UpdateSensorProtocol() If I comment ShowSensorData() function in the UpdateSensorProtocol() it works fine. But otherwise it hangs and the GUI freezes. Any suggestions!
Also, Since the main thread grabs the running instance of singleton, is it really multithreading because we are essentially changing mUpdate in singleton itself albeit from action screen.
I am confused in this.
Also, Can somebody suggest an alternate design as to what I am doing now.
Thanks In Advance
First off all don't make the Systems singletons. Use some kind of Context Encapsulation
for the different system.
If you ignoe this advice and still want to create "singletons" threads at least use QApplication::instance(); as the parent of the thread and put QThread::wait() in the singleton destructors otherwise your program will crash at the program exit.
if(!s_instance){
QMutexLocker lock(&mutex);
if(!s_instance)
s_instance=new SensorProtocol( QApplication::instance());
}
But this isn't going to solve your problem ...
Qt is event driven so try to exployed this very nice event-driven architecture and create a eventloop for each system thread. Then you can create "SystemProtocols" that live in another threads and you can create timers, send events between threads, ... without using low level synchronization objects.
Have a look at the blog entry from Bradley T. Hughes Treading without the headache
Code is not compiled but should give you a good idea where to start ...
class GuiComponent : public QWidget {
//...
signals:
void start(int); // button triggerd signal
void stop(); // button triggerd singal
public slots:
// don't forget to register DataPackage at the metacompiler
// qRegisterMetaType<DataPackage>();
void dataFromProtocol( DataPackage ){
// update the gui the the new data
}
};
class ProtocolSystem : public QObject {
//...
int timerId;
signals:
void dataReady(DataPackage);
public slots:
void stop() {
killTimer(timerId);
}
void start( int interval ) {
timerId = startTimer();
}
protected:
void timerEvent(QTimerEvent * event) {
//code to read from port when data becomes available
// and process it and store in dataPackage
emit dataReady(dataPackage);
}
};
int main( int argc, char ** argv ) {
QApplication app( argc, argv );
// construct the system and glue them together
ProtocolSystem protocolSystem;
GuiComponent gui;
gui.connect(&protocolSystem, SIGNAL(dataReady(DataPackage)), SLOT(dataFromProtocol(DataPackage)));
protocolSystem.connect(&gui, SIGNAL(start(int)), SLOT(start(int)));
protocolSystem.connect(&gui, SIGNAL(stop()), SLOT(stop()));
// move communication to its thread
QThread protocolThread;
protocolSystem.moveToThread(&protocolThread);
protocolThread.start();
// repeat this for other systems ...
// start the application
gui.show();
app.exec();
// stop eventloop to before closing the application
protocolThread.quit();
protocolThread.wait();
return 0;
}
Now you have total independent systems, gui and protocols don't now each other and don't even know that the program is multithreaded. You can unit test all systems independently in a single threaded environement and just glue them together in the real application and if you need to, divided them between different threads.
That is the program architecture that I would use for this problem. Mutlithreading without a single low level synchronization element. No race conditions, no locks, ...
Problems:
Use RAII to lock/unlock your mutexes. They are currently not exception safe.
while(!mStop)
{
mutex.lock()
while(!WaitCondition.wait(&mutex,5))
{
if(mStop)
{
// PROBLEM 1: You mutex is still locked here.
// So returning here will leave the mutex locked forever.
return;
}
// PROBLEM 2: If you leave here via an exception.
// This will not fire, and again you will the mutex locked forever.
mutex.unlock();
// Problem 3: You are using the WaitCondition() incorrectly.
// You unlock the mutex here. The next thing that happens is a call
// WaitCondition.wait() where the mutex MUST be locked
}
// PROBLEM 4
// You are using the WaitCondition() incorrectly.
// On exit the mutex is always locked. So nwo the mutex is locked.
What your code should look like:
while(!mStop)
{
MutextLocker lock(mutex); // RAII lock and unlock mutex.
while(!WaitCondition.wait(&mutex,5))
{
if(mStop)
{
return;
}
//code to read from port when data becomes available
// and process it and store in variables
}
By using RAII it solves all the problems I spotted above.
On a side note.
Your double checked locking will not work correctly.
By using the static function variable suggested by 'Anders Karlsson' you solve the problem because g++ guarantees that static function variables will only be initialized once. In addition this method guaranteed that the singelton will be correctly destroyed (via destructor). Currently unless you are doing some fancy stuff via onexit() you will be leaking memory.
See here for lots of details about better implementation of singleton.
C++ Singleton design pattern
See here why your double checked locking does not work.
What are all the common undefined behaviours that a C++ programmer should know about?
I would start by using RAII (Resource Acquisition Is Initialization) to improve the safety of your locking code. You have code that look like this:
mutex.lock();
...logic...
mutex.unlock();
Wrap the mutex code inside a class where the mutex gets acquired in the ctor and released in the dtor. Now your code looks like this:
MyMutex mutex;
...logic...
The major improvement is that if any exceptions throw in the logic part, your mutex still gets released.
Also, don't let any exceptions leak out of your threads! Catch them even if you don't know how to handle them other than logging it somewhere.
I can't be completely sure what the problem is since I have no clue what the ShowSensorData() function (method?) is doing, but there are some multithreading issues with the code that you have included.
mUpdate should be protected by a mutex if it is accessed by more than one thread.
The run() method looks like it will lock the mutex and never release it if mStop is true.
You should consider using RAII practices to grab and release the mutex. I don't know if you are using Qt mutexes or not but you should look into using QMutexLocker to lock and unlock your mutexes.
I would consider changing your SensorProtocol class to use the condition variable and a flag or some sort of event (not sure what Qt has to offer here) to handle the update inside of a method associated with the object instance. Something like:
/*static*/ void
SensorProtocol::updateSensorProtocol() {
SensorProtocol *inst = SensorProtocol::getInstance();
inst->update();
}
Then make sure that the update() method grabs the mutex before reading or writing any of the members that are shared between the reader and display.
A more complete approach would be to separate your UI display, the sensors, and their linkage using a Model-View-Controller architecture. Refactoring the solution into an MVC architecture would probably simplify things quite a bit. Not to mention that it makes applications like this a lot less error-prone. Take a look at the QAbstractItemView and QAbstractItemDelegate classes for an idea on how this can be implemented. From what I remember, there is a tutorial about implementing MVC using Qt somewhere... it's been quite a few years since I have played with Qt though.
your getInstance method could maybe be written like this as well to avoid having the s_instance var:
SensorProtocol& getInstance()
{
static SensorProtocol instance;
return instance;
}
The double checked locking pattern is broken in C++. This is well documented all over the internet. I don't know what your problem is but clearly you will need to resolve this in your code.
Take a look at QextSerialPort:
QextSerialPort is a cross-platform
serial port class. This class
encapsulates a serial port on both
POSIX and Windows systems.
QextSerialPort inherits from QIODevice and makes serial port communications integrate more smoothly with the rest of the Qt API.
Also, you could use a message passing scheme for communications between the I/O and GUI threads instead of shared memory. This is often much less error prone. You can use the QApplication::postEvent function to send custom QEvent messages to a QObject to be processed in the GUI thread with the QObject::customeEvent handler. It will take care of synchronization for you and alleviate your deadlock problems..
Here is a quick and dirty example:
class IODataEvent : public QEvent
{
public:
IODataEvent() : QEvent(QEvent::User) {}
// put all of your data here
};
class IOThread : public QThread
{
public:
IOThread(QObject * parent) : QThread(parent) {}
void run()
{
for (;;) {
// do blocking I/O and protocol parsing
IODataEvent *event = new IODataEvent;
// put all of your data for the GUI into the event
qApp->postEvent(parent(), event);
// QApplication will take ownership of the event
}
}
};
class GUIObject : public QObject
{
public:
GUIObject() : QObject(), thread(new IOThread(this)) { thread->start() }
protected:
void customEvent(QEvent *event)
{
if (QEvent::User == event->type) {
IODataEvent *data = (IODataEvent *) event;
// get data and update GUI here
event->accept();
} else {
event->ignore();
}
// the event loop will release the IODataEvent memory automatically
}
private:
IOThread *thread;
};
Also, Qt 4 supports queing signals and slots across threads.
Have three sepearate threads for send, receive and display.
Raise an event whenever data is received and handle that within the display thread.
Edit in response to comment 1
I'll admit that I know nothing of qt but from what you've said it would still appear that you can create your serial port object which in turn starts up two worker threads (by use of a start method) for the input and output buffer control.
If the serial port class has a "Connect to port" method to gain use of the serial port; an "Open port" method which starts up your worker threads and opens the port; a "Close port" method to shutdown the send and receive threads and a property for setting the "On Data Received" event handler then you should be all set.
The class shouldn't need to be a singleton as you'll find that most operating systems wont allow more than one process to control a serial port at any one time, instead you'll get an exception (which you need to handle) when you try and connect if it is already in use. The worker threads ensure that the port is held under you're control.