in reply to Re: Effective use of IPC::Semaphore to limit number of concurrent executions of a scxipt
in thread Effective use of IPC::Semaphore to limit number of concurrent executions of a scxipt

If I don't want the processes to block, then would the only changes I needed to make be in

resulting in the code below (rev. of previous code)? Are there any other obvious problems (that might lead to race conditions, for example) in the code below?

I actually don't want the extraneous ones to block, but to go ahead and exit, because other instances can pick up and process waiting data later-I just don't want to slam the machine with a huge number of processes doing heavy processing at once.

#!/usr/bin/perl -w use strict; use IPC::SysV qw(IPC_PRIVATE S_IRWXU IPC_CREAT SEM_UNDO ftok); use IPC::Semaphore; srand; my $sem = new IPC::Semaphore( ftok( $0, 0 ), 1, S_IRWXU | IPC_CREAT ); my $semval = $sem->getval(0); $semval = 0 unless ( defined($semval) ); exit(0) if ( $semval >= 10 ); $sem->op( 0, 1, SEM_UNDO ); # # Do work... or in this case, # print the value of $semval and sleep for a while # print $semval + 1, "\n"; sleep( int( rand(20) + 1 ) ); # # Decrement the semaphore value # $semval = $sem->getval(0); if ($semval) { $sem->op( 0, -1, SEM_UNDO ); } else { $sem->remove; } __END__ # # Sample test execution (in bash): # # index=500 # while [ $index -gt 0 ] # do # perl test.pl & # let "index=index-1" # done #
  • Comment on Re^2: Effective use of IPC::Semaphore to limit number of concurrent executions of a scxipt
  • Download Code

Replies are listed 'Best First'.
Re: Re^2: Effective use of IPC::Semaphore to limit number of concurrent executions of a scxipt
by ptkdb (Monk) on Oct 16, 2003 at 12:23 UTC
    You don't need to do a 'getval(0)' to check the value of the semaphore. If you set the flags to SEM_UNDO | IPC_NOWAIT, and check the return result and $!. If $! is EAGAIN then the semaphore value was 0 so no slots would be available and $sem->op() returned without altering the semaphore's value.
    use Errno qw/EAGAIN EINTR/ ; $result = $sem->op(0, -1, SEM_UNDO | IPC_NOWAIT) if( !$result && $! == EAGAIN ) { # semaphore was zero, no slots available print "BUSY, try later\n" ; exit(0) ; } die "op failed: $!" unless $result ; # op failed for some other reason ## ## lock acquired ##
    Blocking isn't really as bad as it sounds. The process will just wait until one of other instances finishes and then increments the semaphore to something greater than 0. How long that takes depends on how many others are competing to decrement the semaphore at the same time.

    If you want, you can add a time out using 'alarm'.

    alarm(5) ; # five seconds $success = semop $result = int $! ; # capture the value of errno alarm(0) ; # cancel alarm(if still active) if( !$sucess && $result == EINTR ) { # timed out }
Re: Re^2: Effective use of IPC::Semaphore to limit number of concurrent executions of a scxipt
by ptkdb (Monk) on Oct 16, 2003 at 15:03 UTC
  • line 17: op(0, -1, SEM_UNDO) in place of setval(0, ($semval+1))
  • line 31: op(0,  1, SEM_UNDO) in place of setval(0, ($semval-1))

    Semaphores DECREMENT to lock, and INCREMENT to unlock.