I've been wondering if something like Java's ThreadLocal (which I use a
massively in (Java) server-side code), could be defined in Nim.
I tried those two approaches, but neither is valid code. It seems to me it
isn't possible.
Attempt #1:
type
ThreadLocal*[T] = object
## Represents a thread-local, similar to ThreadLocals in Java.
initialised*: bool
## Is this thread local already initialised?
value*: T
## The thread local value.
InitThreadLocalProc*[T] = proc(): T {.nimcall, gcsafe.}
## Type of a proc that lazy initialises a ThreadLocal.
proc getValue*[T](init: InitThreadLocalProc[T]): var T =
## Returns the value of a thread-local.
var myThreadVar {.threadvar.}: ThreadLocal[T]
if not myThreadVar.initialised:
myThreadVar.value = init()
myThreadVar.initialised = true
return myThreadVar.value
proc Returns42(): int =
42
echo("TL: ",getValue(Returns42))
Attempt #2 (would be preferable to #1, because you are not limited to 1
ThreadLocal per type):
type
InitThreadLocalProc*[T] = proc(): T {.nimcall, gcsafe.}
## Type of a proc that lazy initialises a ThreadLocal.
ThreadLocal*[T] = object
## Represents a thread-local, similar to ThreadLocals in Java.
lazyInit: InitThreadLocalProc[T]
## The lazy initialisation proc.
initialised {.threadvar.}: bool
## Is this thread local already initialised?
value {.threadvar.}: T
## The thread local value.
proc initThreadLocal*[T](init: InitThreadLocalProc[T]): ThreadLocal[T] =
## Initialises a ThreadLocal.
result.lazyInit = init
proc getValue*[T](tl: ThreadLocal[T]): var T =
## Returns the value of a thread-local.
if not tl.initialised:
tl.value = tl.lazyInit()
tl.initialised = true
return tl.value
proc Returns42(): int =
42
var testThreadLocal = initThreadLocal[int](Returns42)
echo("TL: ",getValue(testThreadLocal))