Using Wt::Signal as a simple widget synchronization mechanism between sessions?
Added by Michele Perrone 14 days ago
Hi all,
I'm playing around and experimenting with some Wt concepts, and I was looking for an "easy" way to synchronize a slider across different sessions.
My idea was to:
- keep track of the slider value in a global variable
- have a global signal, to which the slider in each session connects to, and updates the slider value based on the received value
- when the slider value is changed in a session, the signal is emitted, which should be picked up by all other sessions Unfortunately this doesn't seem to work! Do you have any idea why? I'm attaching the source code. Many thanks in advance! :-)
Replies (3)
RE: Using Wt::Signal as a simple widget synchronization mechanism between sessions? - Added by Matthias Van Ceulebroeck 14 days ago
Hi Michele,
this is certainly possible, and you are close to a working example!
There is only a single thing missing here.
When a signal is listened to, there is no guarantee that the connected function is executed in the same thread as the UI thread, that manages all the W...
objects.
So there are two things you need to do.
- You need to make the client side of Wt aware that the server is allowed to "force-push" information to it with WApplciation::enableUpdates().
- The listening side (of the connection, meaning another
WApplication
instance) needs to ensure that the UI updates happen in the UI thread. You can do this by taking the WApplication::UpdateLock, performing ths UI changes, and then triggering the updates to the client side with WApplciation::triggerUpdate().
So, I would change:
public:
MyApplication(const Wt::WEnvironment& env)
: Wt::WApplication(env)
{
enableUpdates(true);
And also:
globalStateChanged.connect([this, slider](int state) {
Wt::WApplication::UpdateLock lock(this);
if (lock) {
slider->setValue(state);
triggerUpdate();
}
}
I believe that leads you to a working concept.
P.S. as the documentation of WApplciation::UpdateLock
indicates, you may wish to look at WServer::port().
Best,
Matthias
RE: Using Wt::Signal as a simple widget synchronization mechanism between sessions? - Added by Michele Perrone 10 days ago
Hello Matthias, thank you very much for your prompt reply!
I indeed forgot to take care the UpdateLock... I didn't think about it, because I wasn't starting any background thread on my own like I sometimes do.
Adding that does the trick :-)
I have a doubt about the thread-safety of Wt::Signal::emit() and Wt::Signal::connect(), though. I'm in a scenario where several threads can use both of these methods for a given signal at the same time:
- I have an std::thread running in the background, calling Wt::Signal::emit() whenever my state is updated
- then there are the Wt sessions using Wt::Signal::connect() to receive the signal and update their view
- and finally, the same Wt sessions also use Wt::Signal::emit() whenever the user changes something in the UI, so that the other sessions can update their view based on the new state
Do I need to set up some protection mechanism in order to avoid race conditions?
RE: Using Wt::Signal as a simple widget synchronization mechanism between sessions? - Added by Matthias Van Ceulebroeck 7 days ago
Hello Michele,
that will indeed be necessary. Since all threads can modify the value, its state ought to be consistent. You'll have to mutex the variable in this design.
Best,
Matthias