47 lines
1.9 KiB
Nim
47 lines
1.9 KiB
Nim
|
# Nimbus - Types, data structures and shared utilities used in network sync
|
||
|
#
|
||
|
# Copyright (c) 2018-2021 Status Research & Development GmbH
|
||
|
# Licensed under either of
|
||
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
||
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
||
|
# http://opensource.org/licenses/MIT)
|
||
|
# at your option. This file may not be copied, modified, or
|
||
|
# distributed except according to those terms.
|
||
|
|
||
|
import
|
||
|
chronos
|
||
|
|
||
|
{.push raises: [Defect].}
|
||
|
|
||
|
# Use `safeSetTimer` consistently, with a `ref T` argument if including one.
|
||
|
type
|
||
|
SafeCallbackFunc*[T] = proc (objectRef: ref T) {.gcsafe, raises: [Defect].}
|
||
|
SafeCallbackFuncVoid* = proc () {.gcsafe, raises: [Defect].}
|
||
|
|
||
|
proc safeSetTimer*[T](at: Moment, cb: SafeCallbackFunc[T],
|
||
|
objectRef: ref T = nil): TimerCallback =
|
||
|
## Like `setTimer` but takes a typed `ref T` argument, which is passed to the
|
||
|
## callback function correctly typed. Stores the `ref` in a closure to avoid
|
||
|
## garbage collection memory corruption issues that occur when the `setTimer`
|
||
|
## pointer argument is used.
|
||
|
proc chronosTimerSafeCb(udata: pointer) = cb(objectRef)
|
||
|
return setTimer(at, chronosTimerSafeCb)
|
||
|
|
||
|
proc safeSetTimer*[T](at: Moment, cb: SafeCallbackFuncVoid): TimerCallback =
|
||
|
## Like `setTimer` but takes no pointer argument. The callback function
|
||
|
## takes no arguments.
|
||
|
proc chronosTimerSafeCb(udata: pointer) = cb()
|
||
|
return setTimer(at, chronosTimerSafeCb)
|
||
|
|
||
|
proc setTimer*(at: Moment, cb: CallbackFunc, udata: pointer): TimerCallback
|
||
|
{.error: "Do not use setTimer with a `pointer` type argument".}
|
||
|
## `setTimer` with a non-nil pointer argument is dangerous because
|
||
|
## the pointed-to object is often freed or garbage collected before the
|
||
|
## timer callback runs. Call `setTimer` with a `ref` argument instead.
|
||
|
|
||
|
proc setTimer*(at: Moment, cb: CallbackFunc): TimerCallback =
|
||
|
chronos.setTimer(at, cb, nil)
|
||
|
|
||
|
# End
|