|
| 1 | +=begin pod |
| 2 | +
|
| 3 | +=TITLE class Semaphore |
| 4 | +
|
| 5 | +=SUBTITLE Control access to shared resources by multiple processes |
| 6 | +
|
| 7 | + class Semaphore { } |
| 8 | +
|
| 9 | +Protect your shared code, data or device access using semaphores. An example is |
| 10 | +a printer manager managing a pool of printers without the need of storing print |
| 11 | +jobs when all printers are occupied. The next job is just blocked until a |
| 12 | +printer becomes available. |
| 13 | +
|
| 14 | + class print-manager { |
| 15 | + has Array $!printers; |
| 16 | + has Semaphore $!print-control; |
| 17 | +
|
| 18 | + method BUILD ( Int:D :$nbr-printers ) { |
| 19 | + for ^$nbr-printers -> $pc { |
| 20 | + $!printers[$pc] = { :name{"printer-$pc"}, ... }; |
| 21 | + } |
| 22 | +
|
| 23 | + $!print-control .= new($nbr-printers); |
| 24 | + } |
| 25 | +
|
| 26 | + method print ( $print-job ) { |
| 27 | + $!print-control.acquire; |
| 28 | +
|
| 29 | + find-available-printer-and-print-it($job); |
| 30 | +
|
| 31 | + $!print-control.release; |
| 32 | + } |
| 33 | + } |
| 34 | +
|
| 35 | +Another example is a protection around code updating sensitive data. In such a |
| 36 | +case the semaphore is typically initialized to 1. |
| 37 | +
|
| 38 | +It is important to have a release on every exit of your program! While this is |
| 39 | +obvious, it is easy to fall in traps such as trowing an exception caused by some |
| 40 | +event. When the program dies there is no problem. When the exception is caught |
| 41 | +your program might eventualy come back to the acquire method and will hang |
| 42 | +indefinitely. |
| 43 | +
|
| 44 | +=head1 Methods |
| 45 | +
|
| 46 | +=head2 method new |
| 47 | +
|
| 48 | + method new ( int $permits ) |
| 49 | +
|
| 50 | +Initialize the semaphore with the number of permitted accesses. E.g. when set to |
| 51 | +2, program threads can pass the acquire method twice until it blocks on the |
| 52 | +third time acquire is called. |
| 53 | +
|
| 54 | +=head2 method acquire |
| 55 | +
|
| 56 | + method acquire() |
| 57 | +
|
| 58 | +Acquire access. When other threads have called the method before and the the |
| 59 | +number of permits are used up, the process blocks until threads passed before |
| 60 | +releases the semaphore. |
| 61 | +
|
| 62 | +=head2 method try_acquire |
| 63 | +
|
| 64 | + method try_acquire() returns Bool |
| 65 | +
|
| 66 | +Same as acquire but will not block. Instead it returns True if access is |
| 67 | +permitted or False otherwise. |
| 68 | +
|
| 69 | +=head2 method release |
| 70 | +
|
| 71 | + method release() |
| 72 | +
|
| 73 | +Release the semaphore raising the number of permissions. Any blocked thread will |
| 74 | +get access after that. |
| 75 | +
|
| 76 | +=end pod |
0 commit comments