chickadee » posix-semaphore

Outdated egg!

This is an egg for CHICKEN 4, the unsupported old release. You're almost certainly looking for the CHICKEN 5 version of this egg, if it exists.

If it does not exist, there may be equivalent functionality provided by another egg; have a look at the egg index. Otherwise, please consider porting this egg to the current version of CHICKEN.

posix-semaphore

Where to Find

For now, it's available at: https://github.com/dleslie/posix-semaphore-egg

Constants

Open Flags

o/accmodeconstant
o/rdonlyconstant
o/wronlyconstant
o/rdwrconstant
o/creatconstant
o/nocttyconstant
o/truncconstant
o/appendconstant
o/nonblockconstant
o/ndelayconstant
o/syncconstant
o/fsyncconstant
o/asyncconstant

Valid mode_t Flags

s/isuidconstant
s/isgidconstant
s/irusrconstant
s/iwusrconstant
s/ixusrconstant
s/irwxuconstant
s/irgrpconstant
s/iwgrpconstant
s/ixgrpconstant
s/irwxgconstant
s/irothconstant
s/iwothconstant
s/ixothconstant
s/irwxoconstant

Core Functions

make-semprocedure

Allocates memory for a semaphore.

free-sem semaphoreprocedure

Frees memory allocated for a semaphore.

sem-init semaphore shared? valueprocedure

Initializes a semaphore. If `shared?` is true then the semaphore will be shared with processes which are not its children, and so must reside in a POSIX shared memory range. `value` is an integer.

sem-destroy semaphoreprocedure

Destroys an un-named semaphore.

sem-failed? semaphoreprocedure

Returns true if `semaphore` is a pointer to the special failed semaphore, indicating that `sem-open` failed to operate as desired.

sem-open name open-flagsprocedure

Given a string `name` and an integer mask of `open-flags`, attempts to open a semaphore using the given flags. Returns a semaphore, or false if the operation failed.

sem-open/mode name open-flags mode_t valueprocedure

Given a string `name` and an integer mask of `open-flags`, attempts to open a semaphore using the given flags. If `open-flags` is o/creat, then it will attempt to allocate a new semaphore with the given `mode_t` and a particular integer value. Returns a semaphore, or false if the operation failed.

sem-close semaphoreprocedure

Given a semaphore, attempts to close the semaphore. Returns true if successful, false otherwise.

Unlinks a semaphore by the given name. Returns true if successful, false otherwise.

sem-wait semaphoreprocedure

Attempts to decrement a semaphore. It will block until doing so is possible.

sem-trywait semaphoreprocedure

Attempts to decrement a semaphore. It will not block if it is not possible to do so, and will return true if the semaphore was decremented and false otherwise.

sem-timedwait semaphore seconds nano-secondsprocedure

Attempts to decrement a semaphore. It will block for a maximum of `seconds + nanoseconds`, and will return true if the semaphore was decremented and false otherwise.

sem-post semaphoreprocedure

Increments a semaphore.

sem-getvalue semaphoreprocedure

Gets the value of the semaphore. This command is non-blocking and non-deterministic.

Utility Procedures

create-sem name value #!key (open-flags o/creat) (mode 644)procedure

Uses sem-open/mode to open or create a new semaphore, defaulting to creating. If doing so failed then it will unlink the name and return false. If doing so succeeded then it sets a finalizer that closes and unlinks the semaphore, and returns the new semaphore.

with-sem/try semaphore #!rest bodyprocedure

Macro that uses dynamic-wind to ensure that the semaphore is properly posted regardless of the outcome of `body ...`.

with-sem/try semaphore body-success body-failprocedure

Macro that uses dynamic-wind to ensure that the semaphore is properly posted regardless of the outcome of `body-success` and `body-fail`. `body-success` is called if the semaphore could be decremented, otherwise `body-fail` is called.

with-sem/timed semaphore seconds nano-seconds body-success body-failprocedure

Macro that uses dynamic-wind to ensure that the semaphore is properly posted regardless of the outcome of `body-success` and `body-fail`. `body-success` is called if the semaphore was able to be decremented in `seconds + nano-seconds`, otherwise `body-fail` is called.

Example

(use posix-semaphore)

;; Just in case some other proc has 'test-semaphore', I've tacked on a random number.
;; This shouldn't ever be necessary, or you could use the pid instead.
;; But for testing it came in handy.
(define name (format "test-semaphore-~S" (random 100000)))

;; create-sem handles the name linking and sem-failed? check, as well as setting a finalizer to clean up the semaphore.
(define mutex (create-sem name 1))
(when (not mutex)
      (display "Failed to open semaphore\n")
      (exit))

;; Using sem-getvalue is sort of dangerous. It gets the value of the semaphore at the time it is called, but you cannot expect that value to be consistent.
;; If you have a semaphore with an initial value greater than 1 then even calling sem-getvalue after a successful sem-post cannot assure a consistent value.
(display (format "Semaphore value before post is: ~S\n" (sem-getvalue mutex)))

;; with-sem and its alternates use dynamic-wind to ensure that the semaphore is posted even if the body breaks during operation.
;; Think of it as lock(){..} in C#, or a lock object in C++
(with-sem mutex
          (display (format "Semaphore value after wait is: ~S\n" (sem-getvalue mutex))))

(display (format "Semaphore value after post is: ~S\n" (sem-getvalue mutex)))

Author

Dan Leslie (dan@ironoxide.ca)

License

Copyright 2013 Daniel J. Leslie. All rights reserved.

The contact email address for Daniel J. Leslie is dan@ironoxide.ca

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of
     conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list
     of conditions and the following disclaimer in the documentation and/or other materials
     provided with the distribution.

THIS SOFTWARE IS PROVIDED BY DANIEL J. LESLIE AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DANIEL J. LESLIE OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of Daniel J. Leslie.

Contents »