Synchronizing between a local and remote GUI
-
Consider the following GUI:
when the user press the + button the value is incremented to 6.
However on another computer another user is running the same GUI.
The two GUIs have to stay in sync.
If one of the users press the + button the value should be updated for both GUIs.The remote GUI, the client, communicate with the local server via a simple protocol.
The communication takes the form of a cmd sent from the client and a response sent from the server. There are two commands:1. cmd:"GET_VALUE", response: "5" 2. cmd: "INCREMENT", response: "OK"
Unfortunately the client has to poll GET_VALUE to be notified, but the protocol albeit flawed can not be changed.
Also the response to the cmds have to be returned within a time limit (100 ms I think).How can I implement this in Qt, C++?
So far I have come up with the following classes (rough outline):
class Model { public: std::atomic<int> m_value; }; class Widget : public QWidget { public slots: void incrementClickedLocally(); // must update Model::m_value somehow void valueChangedFromModel(int value); // will update the QLineEdit }; // Reads synchronously from TCP/IP using WinSocket and works on the Model class RemoteHandler : public QThread { private: void run override(); };
I would like to use signals/slots to communicate across the threads.
However it seems that theRemoteHandler
can not use signal/slots to get theModel::m_value
since slots can not have return types?Further it would be convenient to emit a
valueChanged
signal from Model to notify Widget. However in order to do that Model must be a QObject.
It seems that when Model becomes a QObject there are many potential thread problems I have to look out for?
As it isModel
is threadsafe. I can therefore requestModel::m_value
directly from the non main thread inRemoteHandler
while the Widget may be accessing the same variable simultaneously from the main thread. -
@JonB : Thank you. I was just thinking the same thing. I think my reason was that the client may hammer the server with GET_VALUE messages. The server also runs OpenGL in the main thread. I was worried that if the messages from the client was processed in the main thread the OpenGL visualization would not be smooth. Not sure if this is the case though. I should probably test this,
@andyP said in Synchronizing between a local and remote GUI:
I think my reason was that the client may hammer the server with GET_VALUE messages
It won't. How many/frequently messages do you imagine a UI executes, e.g. in response to a user action pressing a button. It's minuscule compared to e.g. the speed of TCP/IP messages....
std::atomic<>
,QAtomicInt
, and all your questions about polling, flags etc.: You won't be needing any of this stuff once you realise threads are not the way to go..... -
Consider the following GUI:
when the user press the + button the value is incremented to 6.
However on another computer another user is running the same GUI.
The two GUIs have to stay in sync.
If one of the users press the + button the value should be updated for both GUIs.The remote GUI, the client, communicate with the local server via a simple protocol.
The communication takes the form of a cmd sent from the client and a response sent from the server. There are two commands:1. cmd:"GET_VALUE", response: "5" 2. cmd: "INCREMENT", response: "OK"
Unfortunately the client has to poll GET_VALUE to be notified, but the protocol albeit flawed can not be changed.
Also the response to the cmds have to be returned within a time limit (100 ms I think).How can I implement this in Qt, C++?
So far I have come up with the following classes (rough outline):
class Model { public: std::atomic<int> m_value; }; class Widget : public QWidget { public slots: void incrementClickedLocally(); // must update Model::m_value somehow void valueChangedFromModel(int value); // will update the QLineEdit }; // Reads synchronously from TCP/IP using WinSocket and works on the Model class RemoteHandler : public QThread { private: void run override(); };
I would like to use signals/slots to communicate across the threads.
However it seems that theRemoteHandler
can not use signal/slots to get theModel::m_value
since slots can not have return types?Further it would be convenient to emit a
valueChanged
signal from Model to notify Widget. However in order to do that Model must be a QObject.
It seems that when Model becomes a QObject there are many potential thread problems I have to look out for?
As it isModel
is threadsafe. I can therefore requestModel::m_value
directly from the non main thread inRemoteHandler
while the Widget may be accessing the same variable simultaneously from the main thread. -
Consider the following GUI:
when the user press the + button the value is incremented to 6.
However on another computer another user is running the same GUI.
The two GUIs have to stay in sync.
If one of the users press the + button the value should be updated for both GUIs.The remote GUI, the client, communicate with the local server via a simple protocol.
The communication takes the form of a cmd sent from the client and a response sent from the server. There are two commands:1. cmd:"GET_VALUE", response: "5" 2. cmd: "INCREMENT", response: "OK"
Unfortunately the client has to poll GET_VALUE to be notified, but the protocol albeit flawed can not be changed.
Also the response to the cmds have to be returned within a time limit (100 ms I think).How can I implement this in Qt, C++?
So far I have come up with the following classes (rough outline):
class Model { public: std::atomic<int> m_value; }; class Widget : public QWidget { public slots: void incrementClickedLocally(); // must update Model::m_value somehow void valueChangedFromModel(int value); // will update the QLineEdit }; // Reads synchronously from TCP/IP using WinSocket and works on the Model class RemoteHandler : public QThread { private: void run override(); };
I would like to use signals/slots to communicate across the threads.
However it seems that theRemoteHandler
can not use signal/slots to get theModel::m_value
since slots can not have return types?Further it would be convenient to emit a
valueChanged
signal from Model to notify Widget. However in order to do that Model must be a QObject.
It seems that when Model becomes a QObject there are many potential thread problems I have to look out for?
As it isModel
is threadsafe. I can therefore requestModel::m_value
directly from the non main thread inRemoteHandler
while the Widget may be accessing the same variable simultaneously from the main thread.@andyP said in Synchronizing between a local and remote GUI:
However it seems that the RemoteHandler can not use signal/slots to get the Model::m_value since slots can not have return types?
Why do you need a return type for this? Send a signal (request) to the model to get the current value... In your model you add some slot like
onValueRequested
and in there you send the value back to your request-"starter" (-> 2-way connection).
Unless there's a better way, but I dont know much about your app design or structure. -
@andyP
Why do you have any threads at all? Without would simplify the task a lot. Qt TCP socket handling is designed to be asynchronous.@JonB : Thank you. I was just thinking the same thing. I think my reason was that the client may hammer the server with GET_VALUE messages. The server also runs OpenGL in the main thread. I was worried that if the messages from the client was processed in the main thread the OpenGL visualization would not be smooth. Not sure if this is the case though. I should probably test this,
-
@andyP said in Synchronizing between a local and remote GUI:
However it seems that the RemoteHandler can not use signal/slots to get the Model::m_value since slots can not have return types?
Why do you need a return type for this? Send a signal (request) to the model to get the current value... In your model you add some slot like
onValueRequested
and in there you send the value back to your request-"starter" (-> 2-way connection).
Unless there's a better way, but I dont know much about your app design or structure.@Pl45m4 : Thank you. But how do I send the value back to RemoteHandler? From what I understand it is adviced against subclasses of QThread having slots? I guess I could introduce a
std::atomic<bool> m_answerReady
andstd::atomic<int> m_value
variable in theRemoteHandler
class. After the RemoteHandler had sent a requestValue signal it would go into a poll loop where it would be checking them_answerReady
flag until it changes. That may work. -
@Pl45m4 : Thank you. But how do I send the value back to RemoteHandler? From what I understand it is adviced against subclasses of QThread having slots? I guess I could introduce a
std::atomic<bool> m_answerReady
andstd::atomic<int> m_value
variable in theRemoteHandler
class. After the RemoteHandler had sent a requestValue signal it would go into a poll loop where it would be checking them_answerReady
flag until it changes. That may work. -
@JonB : Thank you. I was just thinking the same thing. I think my reason was that the client may hammer the server with GET_VALUE messages. The server also runs OpenGL in the main thread. I was worried that if the messages from the client was processed in the main thread the OpenGL visualization would not be smooth. Not sure if this is the case though. I should probably test this,
@andyP said in Synchronizing between a local and remote GUI:
I think my reason was that the client may hammer the server with GET_VALUE messages
It won't. How many/frequently messages do you imagine a UI executes, e.g. in response to a user action pressing a button. It's minuscule compared to e.g. the speed of TCP/IP messages....
std::atomic<>
,QAtomicInt
, and all your questions about polling, flags etc.: You won't be needing any of this stuff once you realise threads are not the way to go..... -
Consider the following GUI:
when the user press the + button the value is incremented to 6.
However on another computer another user is running the same GUI.
The two GUIs have to stay in sync.
If one of the users press the + button the value should be updated for both GUIs.The remote GUI, the client, communicate with the local server via a simple protocol.
The communication takes the form of a cmd sent from the client and a response sent from the server. There are two commands:1. cmd:"GET_VALUE", response: "5" 2. cmd: "INCREMENT", response: "OK"
Unfortunately the client has to poll GET_VALUE to be notified, but the protocol albeit flawed can not be changed.
Also the response to the cmds have to be returned within a time limit (100 ms I think).How can I implement this in Qt, C++?
So far I have come up with the following classes (rough outline):
class Model { public: std::atomic<int> m_value; }; class Widget : public QWidget { public slots: void incrementClickedLocally(); // must update Model::m_value somehow void valueChangedFromModel(int value); // will update the QLineEdit }; // Reads synchronously from TCP/IP using WinSocket and works on the Model class RemoteHandler : public QThread { private: void run override(); };
I would like to use signals/slots to communicate across the threads.
However it seems that theRemoteHandler
can not use signal/slots to get theModel::m_value
since slots can not have return types?Further it would be convenient to emit a
valueChanged
signal from Model to notify Widget. However in order to do that Model must be a QObject.
It seems that when Model becomes a QObject there are many potential thread problems I have to look out for?
As it isModel
is threadsafe. I can therefore requestModel::m_value
directly from the non main thread inRemoteHandler
while the Widget may be accessing the same variable simultaneously from the main thread. -
@andyP said in Synchronizing between a local and remote GUI:
I think my reason was that the client may hammer the server with GET_VALUE messages
It won't. How many/frequently messages do you imagine a UI executes, e.g. in response to a user action pressing a button. It's minuscule compared to e.g. the speed of TCP/IP messages....
std::atomic<>
,QAtomicInt
, and all your questions about polling, flags etc.: You won't be needing any of this stuff once you realise threads are not the way to go.....