So I'm wondering in WHAT WAY is a queue safer than a shared variable?
Ostensibly, in no way. Given that a queue is just a shared array under the covers.
But, accessing shared variables requires locking. With Thread::Queue that locking is taken care of for you. It has been used many times by many people and thus proven correct.
There is certainly nothing stopping you from using a shared hash and performing the locking yourself. But then you have the responsibility to test that you're doing it correctly. Whilst not exactly rocket science, it is still possible to get it wrong.
From a practical stand point -- based upon the little you've said about it -- it seems that at some regular interval, your GUI (re-)draws the on-screen representation of the hash by iterating over its keys & values.
Assuming that's how you are doing things, there are several possibilities:
Simple. But what if the hash didn't change since the last time you did it. It becomes make-work.
When there is nothing changed you save the work.
But when something has changed you need to re-build from scratch for what might be a simple change. And you need to iterate the entire hash to do so.
Now when the worker sets the flag, you can compare the shared and local copies and only update the bit or bits that changed.
You still have to iterate the entire hash to find it. But now you also have to iterate the local copy. And you have to update the local copy.
And don't forget that each time you are iterating the hash in the GUI, you will have to lock it to prevent the worker from changing it whilst you are in the process of iterating it. And that means that the worker either has to stop doing what it is meant to be doing and wait for you to unlock the hash before it can record changes -- thus potentially missing something. Or it has to record changes that occur whilst the shared hash is locked, locally, so that it can remain responsive to whatever is causing those changes, and still update the hash properly once it becomes unlocked.
Now I have no idea how time critical your application is, so maybe none of that is a concern for you.
But imagine how much simpler it becomes if instead of the worker locking & updating a shared hash and then unlocking it again; and the GUI constantly locking the hash and iterating over it to discover what changed, if the worker simply told the GUI what changed when it changed. And the GUI does nothing until it receives that notification.
And the easy way to do that is a queue.
When something changes, instead of setting the key/value into the shared hash, it simply enqueues a message of the form: "key:value".
And when the GUI makes it regular check, it just checks if there is anything pending in the queue. If not, it does nothing. If there is, it pulls the message and either updates the screen directly or updates a local hash and then invokes a redraw.
No waiting; no locking (except under the covers of Thread::Queue); no iterating a hash to discover changes; no make-work. When something changes, you get told not just that something has changed, but what.
It takes far less time/cpu to push and pop a single value to a shared array than it does to iterate a shared hash looking for changes, so there is less contention also.
In reply to Re^9: bidirectional pipe freezing
by BrowserUk
in thread bidirectional pipe freezing
by chessgui
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |