I've written a simple console application using windows sockets to work as a proxy between a server and a client. I decided to make a graphical interface for watching all the in/outgoing packets real time (like a very simple wireshark).
The connection between the server and the client runs on a different thread than the message loop. When the server/client sends a packet, I would like that to be displayed (for example added to a simple text control) immediately.
But since I can not access the forms from other thread than the thread where the message loop is I dont know how to handle this.
I've found several solutions in:
- Managed c++
- C++/CLI
- C#,
but not any without using .NET platform. (I really new to this GUI topic so I am not even sure you can use windows forms without .NET)
Maybe QT + C++ could handle this problem, but any other solution than that? If not is it possible to write a wrapper in C# / Java for the native C++ code?
There must be many applications written in C/C++ which using a GUI, what is the general way to do that?
You are absolutely correct that you cannot access a window in a different thread. The proper way to handle this to post a message using the ::PostMessage Win32 API command (or, if you are using a wrapper library around Win32, whatever function in that wrapper that eventually calls PostMessage). Here's a useful link from Microsoft regarding message queues:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644928(v=vs.85).aspx
There is an alternative one, free and open-source, called Nana C++ Library (http://stdex.sourceforge.net), a pure C++ GUI library.
By using Nana library, the multithreading issue can be fixed easily. There is an article on the multithreading in GUI, it would be a choice for your hobby project.
A quick and dirty Win32 solution would involve a critical section, a text buffer, and a timer in the UI thread.
Define a few globals...
CRITICAL_SECTION bufferLock; // critical section (to be initialized somewhere)
char dataBuffer[65536]; // contains the data that will be sent to the form
int newdata = 0; // how much data we got (this variable must be atomic, int is ok)
char uiDataBuffer[65536]; // data available to the form
int overflow = 0; // just in case...
UI thread timer
void onTimer ()
{
if (overflow)
{
// handle this
}
else
if (newdata) // new data to display
{
// take the lock, copy the data and release the lock quickly
EnterCriticalSection(&bufferLock);
int dataread = newdata;
memcpy(uiDataBuffer, dataBuffer, dataread);
newdata = 0;
LeaveCriticalSection(&bufferLock);
// TODO: append the text in uiDataBuffer[] to your text control
}
}
To be called from the worker thread:
void sendData (char* data, int size)
{
EnterCriticalSection (&bufferLock);
if(size+newdata > 65536)
overflow = 1;
else
{
memcpy(dataBuffer+newdata, data, size);
newdata += size;
}
LeaveCriticalSection (&bufferLock);
}
Code untested. Buffer size and timer frequency are to be adjusted.
It is possible to avoid polling the buffer with the timer by using PostMessage() (with a custom message) to signal the UI that new data is available.
If performance is an issue, data exchange between a producer and a consumer thread can also be performed very efficiently with a lock-free FIFO queue.
PostMessage() alone is not a solution to exchange data between threads.
Related
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.
I have an old legecy ATL/MFC application with two threads, the main Window-Thread and a Render-Thread. My problem is I have random, access-violation errors related to a CSimpleString; i.e. access violation, 0xdddddddd etc...
I have deduced the problem is the two threads accessing the same string at the same time, one trying to use it to render (the MFC main Window-Thread) and one trying to update the string (the Render-Thread).
From the MFC side; the class is
class CDisplay : public CStatic
{
public:
CString m_strDisplay;
...
void SetDisplay(CString str, int nMode = -1);
...
}
There is no paint override and the text is basically rendered via CStatic.
Now, the SetDisplay method is what is called from the Render-Thread; and it prodominent code is:
if (m_strDisplay != str)
{
m_strDisplay = str;
SetWindowText(str + " ");
}
My problem here, is that I need a critical section; but I don't know how to get the MFC side to adhere to it.
Anyone have some wisdom in making MFC thread-safe and avoiding these problems?
Make GUI updates (SetWindowText) in the MFC main thread only. In the render thread, set a variable (protected by critical section) and/or send a message, and then perform the actual GUI element manipulation in the MFC main thread.
I using Indy with C++ Builder XE3. It's perfect system but i have some problems. IdTCPServer works really good but when i have some connections on him and i want to stop server then my application freezed. I try to tell how i do it step by step:
1) Starting application (and server listening)
2) wait for new connections (or simulate it, no difference)
3) when we have 10-15 connections - then try to stop server listening.
4) when code came to IdTCPServer1->Active = false - application will be frozen
i made little video. Maybe it explain situation much better. http://www.youtube.com/watch?v=BNgTxYbLx8g
And here my code:
OnConnect:
EnterCriticalSection(&CritLock);
++ActiveConnections;
SetActiveConnections(ActiveConnections);
LeaveCriticalSection(&CritLock);
OnDisconnect:
EnterCriticalSection(&CritLock);
--ActiveConnections;
SetActiveConnections(ActiveConnections);
LeaveCriticalSection(&CritLock);
StopServer Code:
void TForm1::StopServer()
{
TList *list = IdTCPServer1->Contexts->LockList();
try
{
for(int i = 0; i < list->Count; ++i)
{
TIdContext *AContext = reinterpret_cast<TIdContext*>(list->Items[i]);
try
{
if (AContext->Connection->Connected())
{
AContext->Connection->IOHandler->InputBuffer->Clear();
AContext->Connection->IOHandler->WriteBufferCancel();
AContext->Connection->IOHandler->WriteBufferClear();
AContext->Connection->IOHandler->WriteBufferClose();
AContext->Connection->IOHandler->CloseGracefully();
AContext->Connection->Disconnect();
}
}
catch (const Exception &e)
{
}
}
}
__finally
{
IdTCPServer1->Contexts->UnlockList();
}
IdTCPServer1->Contexts->Clear();
//IdTCPServer1->StopListening();
IdTCPServer1->Active = false;
}
Thanks for advise!
You need to get rid of all your StopServer() code except for the very last line. When TIdTCPServer is deactivated, it performs all necessary cleanups for you. DO NOT DO IT YOURSELF (especially since you are doing it wrong anyway).
void TForm1::StopServer()
{
IdTCPServer1->Active = false;
}
Now, with just that code, if your app is still freezing, then that means you are deadlocking the main thread. That happens if you call StopServer() in the context of the main thread and one of two things are happening in your server code:
one of your TIdTCPServer event handlers performs a synchronized operation to the main thread (either via TIdSync or TThread::Synchronize()).
one of your TIdTCPServer event handlers swallows Indy exceptions and does not allow TIdTCPServer to terminate one or more client threads correctly when needed.
Internally, the TIdTCPServer::Active property setter closes all active sockets and waits for their respective threads to fully terminate, blocking the calling thread until the property setter exits. If yoou are deactivating the server in the main thread and one of the server threads performs a sync that the main thread cannot process, or otherwise does not terminate correctly when it should be, that will block the server deactivation from exiting and thus deadlock the main thread.
So make sure that:
you are not performing sync operations to the main thread while the server is being deactivated by the main thread. If you must sync, then deactivate the server in a worker thread instead so the main thread is not blocked anymore.
your event handlers are not swallowing any Indy EIdException-derived exceptions in try/catch blocks. If you catch such an exception, re-throw it when you are finshed using it. Let TIdTCPServer handle any Indy exceptions so it can perform internal cleanups as needed.
Lastly, on a side note, you do not need to keep track of connections manually. TIdTCPServer already does that for you in the Contexts property. If you need to know how many clients are currently connected at any moment, simply Lock() the Contexts list, read its Count property (or do anything else you need to do with the clients), and then Unlock() the list.
I have two threads (the applications main thread and another one). I am using OpenGL to draw some stuff and I am using the OpenGL keyboard and mouse callbacks. OpenGL blocks when I call glutMainLoop() and since I have to do some calculations in the background, I created another thread. Now, the OpenGL callbacks shall send some data (e.g. x, y position of the mouse/key which has been pressed) to the other thread which has a critical section. While the critical section is running no messages should be accepted, but rather than dropping these messages, I want to process them after the critical section. The class of the non-OpenGL looks something like this:
void run()
{
for (;;) {
int currentTime = now();
if (now() - previousTime > WAIT_INTERVAL) {
previousTime = currentTime;
tick();
}
}
}
void tick() {
// critical section begins
processor->step()
// critical section ends
}
void receiveMessage(void *data) {
processor->changeSomeData(data);
}
So, if receiveMessage() is called from the OpenGL thread and processor->step() is running, the call to changeSomeData() should be postponed because it would mess up the whole calculation.
I want to use the following classes to synchronize the threads:
Mutex.h:
#ifndef MUTEX_H
#define MUTEX_H
#include <Windows.h>
class Mutex;
#include "Lock.h"
class Mutex
{
public:
Mutex();
~Mutex();
private:
void acquire();
void release();
CRITICAL_SECTION criticalSection;
friend class Lock;
};
#endif
Mutex.cpp:
#include "Mutex.h"
Mutex::Mutex()
{
InitializeCriticalSection(&this->criticalSection);
}
Mutex::~Mutex()
{
DeleteCriticalSection(&this->criticalSection);
}
void Mutex::acquire()
{
EnterCriticalSection(&this->criticalSection);
}
void Mutex::release()
{
LeaveCriticalSection(&this->criticalSection);
}
Lock.h:
#ifndef LOCK_H
#define LOCK_H
class Lock;
#include "Mutex.h"
class Lock
{
public:
Lock(Mutex& mutex);
~Lock();
private:
Mutex &mutex;
};
#endif
Lock.cpp
#include "Lock.h"
Lock::Lock(Mutex& mutex) : mutex(mutex)
{
this->mutex.acquire();
}
Lock::~Lock ()
{
this->mutex.release();
}
EDIT:
Here is the whole project: http://upload.visusnet.de/uploads/BlobbyWarriors-rev30.zip (~180 MB)
EDIT 2:
And here is the SVN repo: https://projects.fse.uni-due.de/svn/alexander-mueller-bloby-warriors/trunk/
Oh... No, no, no. Threads are NOT what you should use here. Seriously. Thread are NOT your solution in this particular case. Let's roll back a bit...
You're using GLUT at the moment and you say you need threads to "avoid locking on glutMainLoop(). And you don't want locking because you want to do some calculations in the meantime.
Stop now and ask yourself - are you sure that those operations need to be done asynchronically (as a whole) from OpenGL rendering? If so, you may stop reading this post and look at the other ones, but I sincerely believe that it may not be the case for a +- typical real-time OpenGL application.
So... A typical OpenGL app looks like this:
handle events
tick calculations
redraw screen
Most GL window libraries let you implement that as your own main loop, GLUT kind of obfuscates that with its "callbacks", but the idea is the same.
You can still introduce parallelism in your application, but it should start and stop at step 2, so it's still sequential on main-loop level: "calculate a frame of calculations, THEN render this frame". This approach is likely to save you a lot of trouble.
Protip: Change your library. GLUT is outdated and not maintained anymore. Switching to GLFW (or SDL) for window creation wouldn't take much effort in terms of code and - contrary to GLUT - you define your main loop yourself, which seems to be what you want to achieve here. (Plus they tend to be more convenient for input & window event handling, etc.)
Some typical pseudocode with constant-timestep real-time physics without interfering with rendering (assuming that you want to run physics more often than rendering, in general):
var accum = 0
const PHYSICS_TIMESTEP = 20
while (runMainLoop) {
var dt = getTimeFromLastFrame
accum += dt
while (accum > PHYSICS_TIMESTEP) {
accum -= PHYSICS_TIMESTEP
tickPhysicsSimulation(PHYSICS_TIMESTEP)
}
tickAnyOtherLogic(dt)
render()
}
A possible extension from that is to use the value of accum as an additional "extrapolation" value only for rendering, which would allow for visually smooth the graphical representation while simulating physics more seldomly (with bigger DT), possibly more seldomly than once per rendering frame.
In the main thread: lock a mutex, add a struct/object containing the necessary info to a FIFO data structure of some sort, unlock the mutex, then (optionally) wake up the background thread (via a signal or a condition variable or writing a byte to a socket or however)
In the background thread: (optionally) block until awoken by the main thread, then lock the mutex, pop the first item from the head of the FIFO, unlock the mutex, process the item, repeat.
Critical sections and mutexes are bad. They should only be used by library designers, and usually not even then (because for reusable code, it's often worth the extra effort to gain the extra scalability of lock-free).
Instead, you should use a threadsafe queue. Windows offers lots:
thread message queue (PostMessage)
mailslots
message-mode pipes
datagram sockets
SList API
are just a few of your options.
All of these are highly optimized and much easier to use than designing your own queue.
I wouldn't recommend using GLUT anymore - it's terribly outdated and very restrictive. But if you're set on using it, you might want to look into glutIdleFunc. GLUT will continuously invoke this callback when it's idle - you can use this to perform background processing in the main thread.
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.