Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

cog (4665)

Journal of cog (4665)

Monday September 13, 2004
11:28 AM

Lock

[ #20855 ]
In order to lock a variable, this is what I did (kind of):

sub lock {
    if ( $_[0] ) {
        return 0
    }
    else {
        $_[0] += $$;
        if ( $_[0] == $$ ) {
            return $$;
        }
        else {
            $_[0] -= $$;
            return 0;
        }
    }
}

sub unlock { $_[0] = 0 }

And you can use it with something such as

if ( lock( $dbfile->{lock} ) ) {
    # I locked the database and now it's mine
}
else {
    # somebody got there first...
}

Now... should I put this into a module? :-| And, considering I would (if not for anyone else, at least I'd be using it...), what should I call it? :-|

Lock::Mechanism ?

Lock::Variable ?

:-|

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • I'm not clear that += is atomic. Have you verified that?
    --
    • Randal L. Schwartz
    • Stonehenge
    • By atomic, you mean the operation concludes in one single step, right?

      I haven't verified it, no, but... does it matter? :-| After all, if the result isn't the expected one, changes are undone...

      OK, I just looked under perlop... and I couldn't find anything stating that += is not atomic... :-|
      • Very few things are atomic. By that, I mean there's no way that someone else can get "in the middle" of the operation. But normally, += is implement by "fetching the value, adding the number, then storing the value". That's three steps. You lose, if you lose the CPU between two of those steps.

        So, it looks good on paper, but will definitely fail in real life. You really need something like flock(), which is atomic (or uses atomic steps at the bottom on which to build).

        --
        • Randal L. Schwartz
        • Stonehenge
  • the sub unlock must be $_[0] -= $$

    If not, you could have $_[0] as a negative value, if a different thread unlocks a var while the else part of lock() is running (atfer the +=, before the if)

    You must of course ensure that += is atomic, as randal pointed out.

    What's your problem with IPC::Semaphore or Thread::Semaphore?

    --
    life is short
    • Actually, the unlock sub is kind of a "force unlock". Hence, the direct attribution to zero :-)

      My problem with IPC::Semaphore and Thread::Semaphore is that I didn't think of searching for Semaphore, only for Lock O:-)

      But anyway, I don't think the complexity of IPC::Semaphore (not that there's many of it) is needed for such a simple case as the one I've got. I only need to lock one variable in a file, to ensure that the same process doesn't run twice (or more) at the same time. (hum... maybe Semaphore::Sim
      • I really can't recommend that code :).

        There are so many dependencies to make it work right: does += flushes the dbfile after the update? is it atomic (locks, read old value, sums with $$, writes new value, unlocks)?

        I think you are better off with Fcntl lock stuff...

        --
        life is short
        • does += flushes the dbfile after the update?

          At least in my case, it does.

          is it atomic?

          it doesn't lock and read old value and sums... it simply sums $$ and checks if the resulting value is indeed $$ or not; if not, then something else changed that variable meanwhile... which means we should decrement the variable with $$ again and leave it as it was... It's not an atomic thing... it tries to do it, and then it checks out whether it succeeded or not... and it really doesn't matter if it didn't, because tha
          • Nope, you can easily have no process take care of the job and leave the value at a non-zero negative number. Two processes can both find a zero start, and both increment. Since += is not atomic, that can leave the lock set to PID1, PID2, or (PID1+PID2). (The first two happen if the processes both start the increment by reading the current value before the other process has written it back - the one that writes it back second "wins".) In the first two cases, as long as the wrong process decides it has fai
  • OK, I now understand what you were all talking about :-)

    Thanks for your patience, as I really wasn't getting it :-) Now it makes sense :-)

    It's going to be a very particular case, the one that fails, but I'm still going to implement a way to prevent it somehow :-)

    Thanks :-)