nuclear

  Source   Edit

  1. 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.

Types

Nuclear[T] = distinct ptr T
  Source   Edit

Procs

proc `!+`[T](x: nuclear T; y: int): pointer {.inline.}
Internal leaked procedure   Source   Edit
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](x, y: nuclear T): bool {.inline.}
  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 isNil[T](x: nuclear T): bool {.inline.}
Alias for ptr T isNil procedure.   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
proc nucleate[T](x: typedesc[T]; size: int = 1): nuclear T {.inline.}
Nuclear version of std lib createShared

Example:

var x = nucleate int
x[] = 5
doAssert cast[ptr int](x)[] == 5
  Source   Edit

Templates

template `.`[T](x: nuclear T; field: untyped): untyped
Allows field access to nuclear pointers of object types. The access of those fields will also be nuclear in that they enforce atomic operations of a relaxed order.   Source   Edit
template cptr[T](x: nuclear T): ptr T
Alias for casting back to ptr   Source   Edit
template nuclear(x: typed): untyped
This is a short hand for emulating the type declaration of ptrs and refs

Example:

doAssert $(nuclear int) == $(Nuclear[int])
  Source   Edit