- my $filename=shift;
- my ($timeout)=(shift (@_) or $Timeout);
-
- unless (-l &masterlockfile($filename) and not $iAmMaster) {
- # bevorstehenden Schreibzugriff anmelden
- &simple_lock ($filename,$timeout) or return 0;
-
- my $i;
- for ($i=0 ; $i<=$timeout ; $i++) {
- # Referenzdatei sperren
- &simple_lock (&reffile($filename),$timeout) or (return &simple_unlock($filename,$timeout) and 0);
-
- # Referenzzaehler = 0 ? => okay
- return 1 if (&get_ref ($filename) == 0);
-
- # Referenzdatei wieder freigeben
- &simple_unlock (&reffile($filename),$timeout) or (return &simple_unlock($filename,$timeout) and 0);
- sleep(1);}
-
- &simple_unlock ($filename);}
+ my $filename = shift;
+ my $timeout = shift || $Timeout;
+ my $rest = ($LOCKED{$filename} and $LOCKED{$filename} == 1) ? 1 : 0;
+
+ unless (-l masterlockfile($filename) and not $iAmMaster) {
+ # announce the write lock
+ # and wait $timeout seconds for
+ # references == 0 (no shared locks set)
+ #
+ simple_lock ($filename,$timeout) or return 0;
+ for (1..$timeout) {
+
+ # lock reference counter
+ # or fail
+ #
+ unless (simple_lock (&reffile($filename),$timeout)) {
+ simple_unlock($filename,$timeout);
+ return 0;
+ }
+
+ # ready if we have no shared locks
+ #
+ if (get_ref ($filename) == $rest) {
+ $LOCKED{$filename} = 2 | ($rest ? 1 : 0);
+ return 1;
+ };
+
+ # release reference counter
+ # shared locks get the chance to be removed
+ #
+ unless (simple_unlock (&reffile($filename),$timeout)) {
+ simple_unlock($filename,$timeout);
+ return 0;
+ }
+ sleep(1);
+ }
+
+ # write lock failed
+ # remove the announcement
+ #
+ simple_unlock ($filename);
+ }