- Copyright 2021 Shayan Habibi
Nuclear Pointers
This library emulates the behaviour of volatile pointers without using volatiles (where possible); the behaviour of volatile pointers is emulated using atomic stores and loads with a relaxed memory order.
Volatiles are used if the object store/load is larger than 8 bytes. Ideally, nuclear should be used to atomically alter the objects fields with a field operator.
Procs
proc `<-`[T](x, y: nuclear T) {.inline.}
-
Load the value in y atomically and store it in x atomically. In the case that the object type T is larger than 8 bytes and exceeds atomic assurances, we use volatile operations.
Example:
var x = nucleate int var y = nucleate int x[] = 5 y[] = 7 x <- y y[] = 8 doAssert x[] == 7 doAssert y[] == 8
Source Edit proc `[]`[T](nptr: nuclear T): T {.inline.}
-
Dereference the pointer atomically; only if T is less than 8 bytes In the case that the object type T is larger than 8 bytes and exceeds atomic assurances, we use volatile operations.
Example:
type Obj = object field1: int field2: int var x = nucleate Obj x[] = Obj(field1: 5, field2: 8) doAssert x[] == Obj(field1: 5, field2: 8) denucleate x
Source Edit proc `[]=`[T](x: nuclear T; y: T) {.inline.}
-
Assign value y to the region pointed by the nuclear pointer atomically. In the case that the object type T is larger than 8 bytes and exceeds atomic assurances, we use volatile operations.
Example:
var x = nucleate int x[] = 5 doAssert x[] == 5 denucleate x
Source Edit proc denucleate[T](x: nuclear T) {.inline.}
-
Nuclear version of std lib freeShared
Example:
var x: nuclear int = nucleate int denucleate x
Source Edit proc nuclearAddr[T](x: var T): nuclear T {.inline.}
-
Replicates the addr function, except it will return a nuclear T instead of a std ptr T
Example:
var y: int = 5 var x = nuclearAddr y doAssert x[] == 5 doAssert y == 5
Source Edit