aj7700 has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

I have a perl program "crit.pl" with crictical section code.

"crit.pl" can be invoked by mutiple threats simultaneously(handling race condition with flock).

Is there a way to achieve a queue in the processing? (i.e. The thread that calls "crit.pl" first gets executed first, 2nd execute 2nd, so on..)

Example: Call1 to crit.pl - running Call2 - waiting for lock Call3 - waiting for lock ..

In this case call2 should execute after call1 completes, followed by call3.

crit.pl flock :LOCK_EX //Critical section flock :LOCK_UN

Thank you

Replies are listed 'Best First'.
Re: Critical section FCFS
by neilwatson (Priest) on Jul 13, 2016 at 18:59 UTC

    Perhaps a queuing service instead. Input programs write to the queue and crit.pl reads the queue on its own time. Redis or RabbitMQ come to mind.

    Neil Watson
    watson-wilson.ca

      Neil, this would require a queuing application. Just wondering if there is another way which doesn't involve other applications. Thank you

        I think you misunderstood Neil.

        Your applications that call "crit.pl" would not need to be modified.

        Rather "crit.pl" would queue a request and wait for the response. Then a "critd.pl" would read a request from the queue, do whatever processing, send a response then read the next request.

        There are several modules on CPAN that can manage inter-process queues.

Re: Critical section FCFS
by oiskuu (Hermit) on Jul 14, 2016 at 21:31 UTC

    Well, okay. Your requirements have become reasonably clear, although the design choices lead to some doubts here. As usual, there are alternative ways to accomplish the task. I tried to keep this as simple as possible and not reinvent sendmail or somesuch.

    #! /usr/bin/perl use strict; use warnings; use File::Temp; use Fcntl qw( :flock ); myturn(); mywork(); exit(); sub diag { warn "$$: @_\n" } sub mywork { diag "WORKING... @ARGV"; sleep 1; } sub myturn { (my $wait, our $lk) = queueup("/tmp/foolock"); diag "waiting on lock"; flock($wait, LOCK_EX) or die; diag "obtained the lock!"; } sub queueup { my $lkfile = shift; my ($prev, $own); # release this once done with our unit work $own = File::Temp->new( UNLINK => 0 ); flock($own, LOCK_EX) or die; diag "create and lock $own"; # protect lockfile ops with another lock... open(my $op, "+>", "$lkfile.lk") or die; flock($op, LOCK_EX) or die; diag "take previous $lkfile"; open($prev, "+>", $lkfile) or die; diag "rename $own to $lkfile"; rename("$own", $lkfile) or die; #flock($op, LOCK_UN) or die; return ($prev, $own); }

    As you can see, a chain of per-process locks is used, but just two lockfiles are kept around on /tmp. All in all, I'm somewhat unsure about the robustness of this approach.

Re: Critical section FCFS
by Anonymous Monk on Jul 13, 2016 at 19:44 UTC

    What do you mean by "calls it first"? Programs run in parallel under multi-processor setups. The calls may be simultaneous.

    Do you have one threaded program that needs to serialize its accesses? Or is it multiple programs that need to cooperate? (In the first case, just lock a shared variable and that's it.)

      Crit.pl is one thread program. It may be called simultaneously, as you mentioned I need to serialize access.

      Example: Call1 to crit.pl - running Call2 - waiting for lock Call3 - waiting for lock ..

      In this case call2 should execute after call1 completes, followed by call3.

      Can you please explain more on how shared variable can be used for this?

        The FCFS stands for "first-come, first-served"? And you intend the script "crit.pl" to both queue up and serve the requests as well? Technically, your calls (processes) will then be executing at the same time, though only one can have the critical section.

Re: Critical section FCFS
by naren88 (Initiate) on Jul 15, 2016 at 17:50 UTC

    The module Thread::Semaphore is what you may be looking for!!