[sf-perl] threads, threads::shared, and multiple locked variables

David Christensen dpchrist at holgerdanske.com
Thu Jul 9 17:08:18 PDT 2020

On 2020-07-09 14:40, yary wrote:

> On Wed, Jul 8, 2020 at 7:45 PM David Christensen wrote:

>> I have been experimenting with concurrent programming with Perl, 
>> threads, and threads::shared.  I have successfully used a shared 
>> variable, lock(), cond_wait(), and cond_broadcast() to ensure 
>> thread-safe access to one shared resource.
>> I would now like to ensure thread-safe access to multiple shared 
>> resources.  Specifically, if a thread desires access to any one of 
>> several shared resources, how can it block, wake up when one
>> resource is available (and locked), and determine which resource to
>> access?

> How about code with # what goes here? comments
> I'm a little fuzzy on what the question is. It sounds a little like 
> the old-school "select" call that takes a bit vector representing
> file handles, which paused and then filled 3 other bit vectors saying
> which handles were ready to read, write, or had an exception-is that
> what the question is-using "threads" mechanisms to signal which of
> several things are ready?
> perldoc -f select shows what I remember as similar: my ($nfound,
> $timeleft) = select(my $rout = $rin, my $wout = $win, my $eout =
> $ein, $timeout);

Yes, that's the idea -- except that I am working with shared variables 
[1], rather than file handles.

> ...my go-to in these situations is to `use MCE;` and figure out
> which of its many idioms applies...

MCE [2] appears to provide a framework for creating multiple identical 
workers and partitioning work among them (?).

My question is more related to first principles of concurrent programming.

I am attempting to create a general-purpose Perl library for flow-based 
programming (FBP) [3], whereby multiple independent "processes" send 
data "items" to each other via communication "connections" and work 
together as a overall program.

FBP's are easily represented by directed graphs -- "processes" are nodes 
(boxes) and "connections" are edges (arrows).  For example, here is a 
FBP to read a file (src), compress the contents, tee the compressed 
stream into two streams, write the first duplicate stream to a file 
(dst.gz), checksum the second duplicate stream, and write the checksum 
to a file (dst.gz,md5):

                        +-----+ -> write(dst.gz)
read(src)-> compress-> | tee |
                        +-----+ -> checksum -> write(dst.gz.md5)

I use 'threads' to create and manage one thread for each process and I 
use 'threads::shared' to create and manage one array for each 
connection.  These modules work for simple programs like the above with 
processes that have single inputs and single or multiple outputs, but, 
in general, FBP's will include processes with multiple inputs:

... proc1 -> +------+
              | func | ...
... proc2 -> +------+

So, I need a mechanism for a thread to go to sleep on multiple shared 
variables, wake up when one of those variables signals, and then know 
which variable woke it up.

I am starting to believe that my question is really a feature request 
for threads::shared (and/or Perl?).

I am open to alternative approaches, but the goal is a general-purpose 
FBP library.

(As a work-around, I am implementing a polling solution with a 
configurable sleep delay.)

(Perhaps I could build a work-around using file handles and 'select', 
but file handles are scarce resources and a large FBP could consume many.)


[1] https://perldoc.perl.org/threads/shared.html

[2] https://metacpan.org/pod/distribution/MCE/lib/MCE.pod

[3] https://en.wikipedia.org/wiki/Flow-based_programming

More information about the SanFrancisco-pm mailing list