good chemistry is complicated,
and a little bit messy -LW
Re^5: How can I force thread switching?by BrowserUk (Pope)
|on Sep 30, 2013 at 10:44 UTC||Need Help??|
The actual code was simplified to caricature so that problems and bugs could occur rapidly.
Sorry. I should have said confusing to me rather than "confused". It was obviously artifacts of the reduction process that was leaving me in the dark as to the wider picture of your code.
The confused code may be a reference to my fiddling with is_running and is_joinable. This a (feeble?) attempt to protect against programming errors in the workers.... Since this is my first multi-thread Perl script, there may be a much better way to do it. Have you any suggestion?
The simplest approach to dealing with thread proc errors is to wrap them in block eval. Instead of:
The retry loop is optional, but demonstrates the possibility. Adding that, plus a random divide-by-zero error in the actual thread proc:
And you get:
Thus errors are trapped and diagnosed at source and recovery can be attempted without having to try and detect and divine reasoning remotely.
Concerning the logxxx, these are thread-safe (I hope) subs to write to the common screen.
A couple of thoughts:
Your latest code shows you passed a reference to the queue as a thread argument. What is the advantage/difference compared to a :shared variable? What is the efficiency impact?
From an efficiency point of view, whether explicitly shared (via: my $Q :shared = ... ), or implicitly cloned via closure:
or implicitly shared via argument passing as I showed, it makes little or no difference. In all three cases we are manipulating a reference to an explictly shared array (within the Q module), and the runtime effect is pretty much the same.
The main advantages of using the implicitly shared reference via argument passing is the same as preferring to pass arguments to subroutines rather than have them access global variables. Ie. scoping; action at a distance; visibility etc.
The advantages of my self-limiting queue implementation over your externally-limited implementation are:
The upshot is that I've never used Thread::Semaphore; I had to install it to run your code, and I will be uninstalling it immediately. Not because it is badly implemented -- from a cursory glance it looks just fine -- but because there is nothing it can do for me that I cannot do better with the underlying locking mechanism applied directly to the shared resource to be controlled.
But if I use it, then I will have to use two separate locking mechanisms to control that single resource -- the use of threads::shared::lock() is unavoidable. And applying two locking mechanisms to a single resource is always a recipe for slow code at best; and dead/livelocks and priority inversions all too frequently.
I highly recommend that you drop your use of Thread::Semaphore and adopt my threads::Q implementation. The latter is now very well tested and proven and simplifies your use-case beyond measure.
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.