Atomic intrinsics v0.1.0
MemoryOrder
pub enum MemoryOrder: uint8 {
Relaxed = 0,
Acquire = 1,
Release = 2,
AcquireRelease = 3,
SequentiallyConsistent = 4
}
Which other memory operations may be reordered across an atomic one.
The weakest ordering that makes a program correct is also the fastest, and a stronger one is never wrong. When in
doubt, SequentiallyConsistent gives every thread one agreed order of all such operations.
Cases
| Name | Value | Description |
|---|---|---|
Relaxed | 0 | No ordering: the operation itself is atomic, and nothing around it is held back. Right for counters whose value no other memory depends on. |
Acquire | 1 | Later operations of this thread are not moved before this load, so whatever a releasing thread wrote before its release is visible after this acquire. For loads and the read half of read-modify-write operations. |
Release | 2 | Earlier operations of this thread are not moved after this store, so they are visible to a thread that acquires what it stores. For stores and the write half of read-modify-write operations. |
AcquireRelease | 3 | Both Acquire and Release, for a read-modify-write operation that does both. |
SequentiallyConsistent | 4 | AcquireRelease, and also a single order of every sequentially consistent operation that all threads agree on. |
AtomicLoad<T>
pub func AtomicLoad<T>(address: *T, order: MemoryOrder) -> T
Reads the value at address atomically.
order must be Relaxed, Acquire or SequentiallyConsistent, written at the call. address must be aligned to
the size of T and point at memory every thread that touches it reaches only through atomic operations. Runs in
constant time and allocates nothing.
Type parameters
| Name | Description |
|---|---|
T | an integer of 8 to 64 bits, bool, or a pointer |
Parameters
| Name | Type | Description |
|---|---|---|
address | *T | the value to read |
order | MemoryOrder | which other operations may move across this one |
Returns: the value read
AtomicStore<T>
pub func AtomicStore<T>(
address: *var T,
value: T,
order: MemoryOrder
)
Writes value to address atomically.
order must be Relaxed, Release or SequentiallyConsistent, written at the call. address must be aligned to
the size of T. Runs in constant time and allocates nothing.
Type parameters
| Name | Description |
|---|---|
T | an integer of 8 to 64 bits, bool, or a pointer |
Parameters
| Name | Type | Description |
|---|---|---|
address | *var T | where to write |
value | T | what to write |
order | MemoryOrder | which other operations may move across this one |
AtomicExchange<T>
pub func AtomicExchange<T>(
address: *var T,
value: T,
order: MemoryOrder
) -> T
Writes value to address and returns what was there, as one atomic step.
Any ordering is allowed. address must be aligned to the size of T. Runs in constant time and allocates nothing.
Type parameters
| Name | Description |
|---|---|
T | an integer of 8 to 64 bits, bool, or a pointer |
Parameters
| Name | Type | Description |
|---|---|---|
address | *var T | where to write |
value | T | what to write |
order | MemoryOrder | which other operations may move across this one |
Returns: the value that was replaced
AtomicCompareExchange<T>
pub func AtomicCompareExchange<T>(
address: *var T,
expected: T,
desired: T,
success: MemoryOrder,
failure: MemoryOrder
) -> T
Writes desired to address if it holds expected, and returns what it held, as one atomic step.
The write happened exactly when the returned value equals expected. success orders the operation when it writes,
and failure when it only reads; failure may not be Release or AcquireRelease, nor acquire more than
success does. address must be aligned to the size of T. Never fails spuriously. Runs in constant time apart
from contention and allocates nothing.
Type parameters
| Name | Description |
|---|---|
T | an integer of 8 to 64 bits, bool, or a pointer |
Parameters
| Name | Type | Description |
|---|---|---|
address | *var T | the value to compare and replace |
expected | T | the value address must hold for the write to happen |
desired | T | the value to write |
success | MemoryOrder | the ordering when the write happens |
failure | MemoryOrder | the ordering when it does not |
Returns: the value address held before the operation
AtomicFetchAdd<T>
pub func AtomicFetchAdd<T>(
address: *var T,
value: T,
order: MemoryOrder
) -> T
Adds value to the integer at address and returns what was there, as one atomic step.
The sum wraps on overflow, as two's complement arithmetic does. Any ordering is allowed. Runs in constant time apart
from contention and allocates nothing.
Type parameters
| Name | Description |
|---|---|
T | an integer of 8 to 64 bits |
Parameters
| Name | Type | Description |
|---|---|---|
address | *var T | the integer to add to |
value | T | what to add |
order | MemoryOrder | which other operations may move across this one |
Returns: the value before the addition
AtomicFetchSub<T>
pub func AtomicFetchSub<T>(
address: *var T,
value: T,
order: MemoryOrder
) -> T
Subtracts value from the integer at address and returns what was there, as one atomic step.
The difference wraps on overflow. Any ordering is allowed. Runs in constant time apart from contention and
allocates nothing.
Type parameters
| Name | Description |
|---|---|
T | an integer of 8 to 64 bits |
Parameters
| Name | Type | Description |
|---|---|---|
address | *var T | the integer to subtract from |
value | T | what to subtract |
order | MemoryOrder | which other operations may move across this one |
Returns: the value before the subtraction
AtomicFetchAnd<T>
pub func AtomicFetchAnd<T>(
address: *var T,
value: T,
order: MemoryOrder
) -> T
Combines the value at address with value by bitwise and, and returns what was there, as one atomic step.
Any ordering is allowed. Runs in constant time apart from contention and allocates nothing.
Type parameters
| Name | Description |
|---|---|
T | an integer of 8 to 64 bits, or bool |
Parameters
| Name | Type | Description |
|---|---|---|
address | *var T | the value to combine |
value | T | the bits to keep |
order | MemoryOrder | which other operations may move across this one |
Returns: the value before the operation
AtomicFetchOr<T>
pub func AtomicFetchOr<T>(
address: *var T,
value: T,
order: MemoryOrder
) -> T
Combines the value at address with value by bitwise or, and returns what was there, as one atomic step.
Any ordering is allowed. Runs in constant time apart from contention and allocates nothing.
Type parameters
| Name | Description |
|---|---|
T | an integer of 8 to 64 bits, or bool |
Parameters
| Name | Type | Description |
|---|---|---|
address | *var T | the value to combine |
value | T | the bits to set |
order | MemoryOrder | which other operations may move across this one |
Returns: the value before the operation
AtomicFetchXor<T>
pub func AtomicFetchXor<T>(
address: *var T,
value: T,
order: MemoryOrder
) -> T
Combines the value at address with value by bitwise exclusive or, and returns what was there, as one atomic
step.
Any ordering is allowed. Runs in constant time apart from contention and allocates nothing.
Type parameters
| Name | Description |
|---|---|
T | an integer of 8 to 64 bits, or bool |
Parameters
| Name | Type | Description |
|---|---|---|
address | *var T | the value to combine |
value | T | the bits to flip |
order | MemoryOrder | which other operations may move across this one |
Returns: the value before the operation
Fence
pub func Fence(order: MemoryOrder)
Orders this thread's memory operations without touching memory.
order must not be Relaxed, which would order nothing. An Acquire fence keeps later operations after earlier
loads, a Release fence keeps earlier operations before later stores, and SequentiallyConsistent does both and
takes part in the single order of sequentially consistent operations. Runs in constant time and allocates nothing.
Parameters
| Name | Type | Description |
|---|---|---|
order | MemoryOrder | what the fence holds back |
SpinHint
pub func SpinHint()
Tells the processor that the thread is waiting in a loop for another thread. It saves power and lets a sibling hardware thread run, and has no effect on memory. A loop that waits long should sleep instead. Runs in constant time and allocates nothing.
Integer arithmetic
Checked, wrapping and saturating arithmetic at every integer width, the limits of an integer type, and the uint64 intrinsics allocation sizes are computed with.
Bit operations
Counting, rotating, reversing and testing the bits of an integer of any width, and a right shift that brings in zeros whatever the sign.