5.2 Atomic Fixnums
(require rebellion/concurrency/atomic/fixnum) | |
package: rebellion |
An atomic fixnum is a thread-safe, future-safe, kill-safe, break-safe, and lock-free mutable object containing a single fixnum. The most basic operation on an atomic fixnum is a compare and set, which attempts to set the atomic fixnum to a new value if and only if its current value is equal to some specific value. When Racket is compiled with support for futures, this operation is implemented with a single hardware instruction.
All other operations on atomic fixnums are implemented in terms of atomic compare and set with a retry loop. For example, atomic-fixnum-add! gets the current value of the atomic fixnum, adds it with an input number, then attempts to set the value to the computed result if and only if the atomic fixnum’s current value at the time of the compare-and-set is equal to its value at the time the result was computed. If that isn’t the case due to contention with competing threads or futures, then atomic-fixnum-add! retries the operation again. This is a form of Optimistic Concurrency Control (OCC).
procedure
(atomic-fixnum? v) → boolean?
v : any/c
procedure
(make-atomic-fixnum initial-value [ #:name name]) → atomic-fixnum? initial-value : fixnum? name : (or/c interned-symbol? #f) = #f
5.2.1 Basic Atomic Fixnum Operations
procedure
(atomic-fixnum-get num) → fixnum?
num : atomic-fixnum?
> (define num (make-atomic-fixnum 42)) > (atomic-fixnum-get num) 42
procedure
(atomic-fixnum-set! num replacement) → void?
num : atomic-fixnum? replacement : fixnum?
> (define num (make-atomic-fixnum 0)) > (atomic-fixnum-set! num 5) > (atomic-fixnum-get num) 5
procedure
(atomic-fixnum-add! num amount) → void?
num : atomic-fixnum? amount : fixnum?
This operation is not guaranteed to terminate. The operation may be retried if num is concurrently mutated, and there are no limits on how many times it may be retried.
> (define num (make-atomic-fixnum 3)) > (atomic-fixnum-add! num 6) > (atomic-fixnum-get num) 9
procedure
(atomic-fixnum-update! num updater) → void?
num : atomic-fixnum? updater : (-> fixnum? fixnum?)
This operation is not guaranteed to terminate. The operation may be retried if num is concurrently mutated, and there are no limits on how many times it may be retried.
Because the update may be retried, updater should be safe to apply multiple times. Beware that any side effects in updater may be executed more than once.
> (define num (make-atomic-fixnum 5)) > (atomic-fixnum-update! num sqr) > (atomic-fixnum-get num) 25
5.2.2 Conditional Atomic Fixnum Operations
procedure
(atomic-fixnum-compare-and-set! num expected replacement) → boolean? num : atomic-fixnum? expected : fixnum? replacement : fixnum?
> (define num (make-atomic-fixnum 0)) > (atomic-fixnum-compare-and-set! num 1 42) #f
> (atomic-fixnum-get num) 0
> (atomic-fixnum-compare-and-set! num 0 42) #t
> (atomic-fixnum-get num) 42
procedure
(atomic-fixnum-compare-and-exchange! num expected replacement) → fixnum? num : atomic-fixnum? expected : fixnum? replacement : fixnum?
This operation is not guaranteed to terminate. The operation may be retried if num is concurrently mutated, and there are no limits on how many times it may be retried.
> (define num (make-atomic-fixnum 0)) > (atomic-fixnum-compare-and-exchange! num 1 42) 0
> (atomic-fixnum-get num) 0
> (atomic-fixnum-compare-and-exchange! num 0 42) 0
> (atomic-fixnum-get num) 42
procedure
(atomic-fixnum-compare-and-add! num expected amount) → boolean? num : atomic-fixnum? expected : fixnum? amount : fixnum?
This operation is not guaranteed to terminate. The operation may be retried if num is concurrently mutated, and there are no limits on how many times it may be retried.
> (define num (make-atomic-fixnum 3)) > (atomic-fixnum-compare-and-add! num 2 6) #f
> (atomic-fixnum-get num) 3
> (atomic-fixnum-compare-and-add! num 3 6) #t
> (atomic-fixnum-get num) 9
5.2.3 Compound Atomic Fixnum Operations
procedure
(atomic-fixnum-get-then-set! num replacement) → fixnum? num : atomic-fixnum? replacement : fixnum?
This operation is not guaranteed to terminate. The operation may be retried if num is concurrently mutated, and there are no limits on how many times it may be retried.
> (define num (make-atomic-fixnum 5)) > (atomic-fixnum-get-then-set! num 10) 5
> (atomic-fixnum-get num) 10
procedure
(atomic-fixnum-get-then-add! num amount) → fixnum?
num : atomic-fixnum? amount : fixnum?
This operation is not guaranteed to terminate. The operation may be retried if num is concurrently mutated, and there are no limits on how many times it may be retried.
> (define num (make-atomic-fixnum 3)) > (atomic-fixnum-get-then-add! num 6) 3
> (atomic-fixnum-get num) 9
procedure
(atomic-fixnum-add-then-get! num amount) → fixnum?
num : atomic-fixnum? amount : fixnum?
This operation is not guaranteed to terminate. The operation may be retried if num is concurrently mutated, and there are no limits on how many times it may be retried.
> (define num (make-atomic-fixnum 3)) > (atomic-fixnum-add-then-get! num 6) 9
procedure
(atomic-fixnum-get-then-update! num updater) → fixnum? num : atomic-fixnum? updater : (-> fixnum? fixnum?)
This operation is not guaranteed to terminate. The operation may be retried if num is concurrently mutated, and there are no limits on how many times it may be retried.
Because the update may be retried, updater should be safe to apply multiple times. Beware that any side effects in updater may be executed more than once.
> (define num (make-atomic-fixnum 5)) > (atomic-fixnum-get-then-update! num sqr) 5
> (atomic-fixnum-get num) 25
procedure
(atomic-fixnum-update-then-get! num updater) → fixnum? num : atomic-fixnum? updater : (-> fixnum? fixnum?)
This operation is not guaranteed to terminate. The operation may be retried if num is concurrently mutated, and there are no limits on how many times it may be retried.
Because the update may be retried, updater should be safe to apply multiple times. Beware that any side effects in updater may be executed more than once.
> (define num (make-atomic-fixnum 5)) > (atomic-fixnum-update-then-get! num sqr) 25