76 lines
2.2 KiB
Nim
76 lines
2.2 KiB
Nim
# nim-raft
|
|
# Copyright (c) 2023 Status Research & Development GmbH
|
|
# Licensed under either of
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
|
# at your option.
|
|
# This file may not be copied, modified, or distributed except according to
|
|
# those terms.
|
|
|
|
import std/asyncdispatch
|
|
import std/locks
|
|
import ../raft/types
|
|
import uuids
|
|
|
|
export asyncdispatch
|
|
|
|
var
|
|
pollThr: Thread[void]
|
|
runningMtx: Lock
|
|
running: bool
|
|
|
|
proc RaftTimerCreateCustomImpl*(timerInterval: int, oneshot: bool, timerCallback: RaftTimerCallback): RaftTimer {.nimcall, gcsafe.} =
|
|
var
|
|
timer = RaftTimer(mtx: Lock(), canceled: false, expired: false, timeout: timerInterval, oneshot: oneshot)
|
|
|
|
initLock(timer.mtx)
|
|
|
|
addTimer(timer.timeout, timer.oneshot, proc (fd: AsyncFD): bool {.closure, gcsafe.} =
|
|
withLock(timer.mtx):
|
|
if not timer.canceled:
|
|
timerCallback(timer)
|
|
if timer.oneshot:
|
|
timer.expired = true
|
|
return true
|
|
else:
|
|
return false
|
|
else:
|
|
return true
|
|
)
|
|
timer
|
|
|
|
proc RaftTimerCancelCustomImpl*(timer: RaftTimer): bool {.nimcall, gcsafe, discardable.} =
|
|
withLock(timer.mtx):
|
|
if not timer.expired and not timer.canceled:
|
|
timer.canceled = true
|
|
else:
|
|
return false
|
|
|
|
proc RaftTimerPollThread() {.thread, nimcall, gcsafe.} =
|
|
while running:
|
|
try:
|
|
|
|
poll()
|
|
debugEcho activeDescriptors()
|
|
except ValueError as e:
|
|
debugEcho e.msg
|
|
# Add a 'dummy' timer if no other handles are present to prevent more
|
|
# ValueError exceptions this is a workaround for a asyncdyspatch bug
|
|
# see - https://github.com/nim-lang/Nim/issues/14564
|
|
addTimer(10000, false, proc (fd: AsyncFD): bool {.closure, gcsafe.} = false)
|
|
|
|
proc RaftTimerJoinPollThread*() {.nimcall, gcsafe.} =
|
|
joinThread(pollThr)
|
|
|
|
proc RaftTimerStartCustomImpl*(joinThread: bool = true) {.nimcall, gcsafe.} =
|
|
withLock(runningMtx):
|
|
running = true
|
|
createThread(pollThr, RaftTimerPollThread)
|
|
if joinThread:
|
|
RaftTimerJoinPollThread()
|
|
|
|
proc RaftTimerStopCustomImpl*(joinThread: bool = true) {.nimcall, gcsafe.} =
|
|
withLock(runningMtx):
|
|
running = false
|
|
if joinThread:
|
|
RaftTimerJoinPollThread() |