module: threads-internal Synopsis: The implementation of the classes Author: Tony Mann Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND //// define open abstract class () end class; define sealed inline method make (class == , #rest keys, #key, #all-keys) => (lock :: ) apply(make, , keys); end method; define inline function lock-wait-result (lock :: , prim-res :: ) => (res :: ) select (prim-res) $success => #t; $timeout => #f; otherwise => lock-wait-result-error(lock, prim-res); end select; end; define method lock-wait-result-error (lock :: , prim-res :: ) => (res :: ) select (prim-res) $success => #t; $timeout => #f; $pre-locked => error(make(, lock: lock)); otherwise => error(make(, synchronization: lock)); end select; end method; define inline function lock-release-result (lock :: , prim-res :: ) => () unless (prim-res == $success) lock-release-result-error(lock, prim-res); end unless; end; define method lock-release-result-error (lock :: , prim-res :: ) => () select (prim-res) $unlocked => error(make(, lock: lock)); $count-exceeded => error(make(, lock: lock)); otherwise => error(make(, synchronization: lock)); end select; end method; //// define constant $semaphore-maximum-count-limit = 1000000; define open abstract primary class (, ) constant slot initial-count :: , init-value: 0, init-keyword: initial-count:; constant slot maximum-count :: , init-value: $semaphore-maximum-count-limit, init-keyword: maximum-count:; end class; define sealed class () end class; define sealed domain make (singleton()); define sealed domain initialize (); define sealed inline method make (class == , #rest keys, #key, #all-keys) => (lock :: ) apply(make, , keys); end method; define method initialize (lock :: , #key) => () drain-finalization-queue(); next-method(); let res = primitive-make-semaphore(lock, lock.synchronization-name, lock.initial-count, lock.maximum-count); check-synchronization-creation(lock, res); finalize-when-unreachable(lock); end method; define inline sealed method release (lock :: , #key) => () let res = primitive-release-semaphore(lock); lock-release-result(lock, res); end method; define inline sealed method wait-for (lock :: , #key timeout) => (success?) let res = if (timeout) primitive-wait-for-semaphore-timed(lock, timeout.millisecs) else primitive-wait-for-semaphore(lock) end if; lock-wait-result(lock, res); end method; define sealed method finalize (lock :: ) => () let res = primitive-destroy-semaphore(lock); check-synchronization-finalization(lock, res); end method; //// define open abstract class () end class; define sealed inline method make (class == , #rest keys, #key, #all-keys) => (lock :: ) apply(make, , keys); end method; define open generic owned? (lock :: ) => (owned? :: ); //// define open abstract primary class (, ) end class; define sealed class () end class; define sealed domain make (singleton()); define sealed domain initialize (); define sealed inline method make (class == , #rest keys, #key, #all-keys) => (lock :: ) apply(make, , keys); end method; define method initialize (lock :: , #key) => () drain-finalization-queue(); next-method(); let res = primitive-make-recursive-lock(lock, lock.synchronization-name); check-synchronization-creation(lock, res); finalize-when-unreachable(lock); end method; define inline sealed method release (lock :: , #key) => () let res = primitive-release-recursive-lock(lock); lock-release-result(lock, res); end method; define inline sealed method wait-for (lock :: , #key timeout) => (success?) let res = if (timeout) primitive-wait-for-recursive-lock-timed(lock, timeout.millisecs) else primitive-wait-for-recursive-lock(lock) end if; lock-wait-result(lock, res); end method; define sealed method owned? (lock :: ) => (owned? :: ) primitive-owned-recursive-lock(lock) == $true; end method; define sealed method finalize (lock :: ) => () let res = primitive-destroy-recursive-lock(lock); check-synchronization-finalization(lock, res); end method; //// define open abstract primary class (, ) end class; define sealed class () end class; define sealed domain make (singleton()); define sealed domain initialize (); // make-simple-lock is a fast mechanism for allocating s // which may be used early in the bootstrap of the Dylan library. define function make-simple-lock () => (result :: ) let instance :: = system-allocate-simple-instance(, fill: #f); initialize-simple-lock(instance, #f); instance end; define function initialize-simple-lock (lock :: , name) => () drain-finalization-queue(); let res = primitive-make-simple-lock(lock, name); check-synchronization-creation(lock, res); finalize-when-unreachable(lock); end; define sealed inline method make (class == , #rest keys, #key, #all-keys) => (lock :: ) apply(make, , keys); end method; define method initialize (lock :: , #key) => () next-method(); initialize-simple-lock(lock, lock.synchronization-name); end method; define inline sealed method release (lock :: , #key) => () let res = primitive-release-simple-lock(lock); lock-release-result(lock, res); end method; define inline sealed method wait-for (lock :: , #key timeout) => (success?) let res = if (timeout) primitive-wait-for-simple-lock-timed(lock, timeout.millisecs) else primitive-wait-for-simple-lock(lock) end if; lock-wait-result(lock, res); end method; define sealed method owned? (lock :: ) => (owned? :: ) primitive-owned-simple-lock(lock) == $true; end method; define sealed method finalize (lock :: ) => () let res = primitive-destroy-simple-lock(lock); check-synchronization-finalization(lock, res); end method; //// //// The class of multiple-reader single-writer locks // The internal state of a is either : // a , indicating the thread which owns the lock in write mode // or // an , indicating the number of times the lock has been claimed // in read mode. // When unlocked, the state will be 0 // // The lock class is implemented as a monitored data structure. // A is released whenever there is a possibility // of a state transition from read mode to write mode (i.e. // whenever the lock moves into the unlocked state) define constant = type-union(, ); define open abstract primary class () constant slot internal-monitor = make(, lock: make()); slot rw-lock-state :: = 0; end class; define sealed class () end class; define sealed domain make (singleton()); define sealed domain initialize (); define sealed inline method make (class == , #rest keys, #key, #all-keys) => (lock :: ) apply(make, , keys); end method; define sealed method release (lock :: , #key) => () let monitor = lock.internal-monitor; let inner-lock = monitor.associated-lock; let res = with-lock (inner-lock) let state = lock.rw-lock-state; if (state.locked-for-writing?) lock.rw-lock-state := 0; release-all(monitor); #t elseif (state.locked-for-reading?) let new-state = state - 1; lock.rw-lock-state := new-state; if (new-state == 0) release-all(monitor); end if; #t; else #f; end if; end with-lock; unless (res) lock-release-result-error(lock, $unlocked); end unless; end method; define sealed method wait-for (lock :: , #key timeout, mode = #"read") => (success?) if (mode == #"read" | mode == #"write") let monitor = lock.internal-monitor; let inner-lock = monitor.associated-lock; block (exit) with-lock (inner-lock) if (mode == #"write") until (lock.lock-is-free?) unless (wait-for(monitor, timeout: timeout)) exit(#f); end unless; end until; lock.rw-lock-state := current-thread(); else // mode == #"read" until (lock.lock-is-free-for-reading?) unless (wait-for(monitor, timeout: timeout)) exit(#f); end unless; end until; lock.rw-lock-state := lock.rw-lock-state + 1; end if; #t end with-lock; end block; else error("Unknown mode for waiting for lock: %=", mode); end if; end method; define sealed method owned? (lock :: ) => (owned? :: ) lock.rw-lock-state.locked-for-writing?; end method; define sealed method owned-for-reading? (lock :: ) => (owned? :: ) lock.rw-lock-state.locked-for-reading?; end method; define inline method locked-for-writing? (state :: ) => (locked? :: ) state == current-thread(); end method; define inline method locked-for-reading? (state :: ) => (locked? :: ) instance?(state, ) & (state > 0); end method; define inline method lock-is-free? (rw-lock :: ) => (free? :: ) rw-lock.rw-lock-state == 0; end method; define inline method lock-is-free-for-reading? (rw-lock :: ) => (free? :: ) instance?(rw-lock.rw-lock-state, ) end method;