Thread-safety for the registry

This commit is contained in:
Zahary Karadjov 2019-03-25 00:46:17 +02:00
parent 3586140622
commit cb828352cc
1 changed files with 66 additions and 50 deletions

View File

@ -1,4 +1,4 @@
import macros, tables import locks, macros, tables
from options import LogLevel from options import LogLevel
type type
@ -16,31 +16,45 @@ type
topicStatesTable*: Table[string, ptr Topic] topicStatesTable*: Table[string, ptr Topic]
var var
gActiveLogLevel: LogLevel registryLock: Lock
gTotalEnabledTopics: int gActiveLogLevel {.guard: registryLock.}: LogLevel
gTotalRequiredTopics: int gTotalEnabledTopics {.guard: registryLock.}: int
gTopicStates = initTable[string, ptr Topic]() gTotalRequiredTopics {.guard: registryLock.}: int
gTopicStates {.guard: registryLock.} = initTable[string, ptr Topic]()
mainThreadId = getThreadId()
initLock(registryLock)
template lockRegistry(body: untyped) =
when compileOption("threads"):
withLock registryLock: body
else:
body
proc setLogLevel*(lvl: LogLevel) = proc setLogLevel*(lvl: LogLevel) =
lockRegistry:
gActiveLogLevel = lvl gActiveLogLevel = lvl
proc clearTopicsRegistry* = proc clearTopicsRegistry* =
lockRegistry:
gTotalEnabledTopics = 0 gTotalEnabledTopics = 0
gTotalRequiredTopics = 0 gTotalRequiredTopics = 0
for val in gTopicStates.values: for val in gTopicStates.values:
val.state = Normal val.state = Normal
iterator topicStates*: (string, TopicState) =
for name, topic in gTopicStates:
yield (name, topic.state)
proc registerTopic*(name: string, topic: ptr Topic): ptr Topic = proc registerTopic*(name: string, topic: ptr Topic): ptr Topic =
# As long as sequences are thread-local, modifying the `gTopicStates`
# sequence must be done only from the main thread:
doAssert getThreadId() == mainThreadId
lockRegistry:
gTopicStates[name] = topic gTopicStates[name] = topic
return topic return topic
proc setTopicState*(name: string, proc setTopicState*(name: string,
newState: TopicState, newState: TopicState,
logLevel = LogLevel.NONE): bool = logLevel = LogLevel.NONE): bool =
lockRegistry:
if not gTopicStates.hasKey(name): if not gTopicStates.hasKey(name):
return false return false
@ -63,6 +77,7 @@ proc setTopicState*(name: string,
proc topicsMatch*(logStmtLevel: LogLevel, proc topicsMatch*(logStmtLevel: LogLevel,
logStmtTopics: openarray[ptr Topic]): bool = logStmtTopics: openarray[ptr Topic]): bool =
lockRegistry:
var var
hasEnabledTopics = gTotalEnabledTopics > 0 hasEnabledTopics = gTotalEnabledTopics > 0
enabledTopicsMatch = false enabledTopicsMatch = false
@ -88,5 +103,6 @@ proc topicsMatch*(logStmtLevel: LogLevel,
return normalTopicsMatch return normalTopicsMatch
proc getTopicState*(topic: string): ptr Topic = proc getTopicState*(topic: string): ptr Topic =
lockRegistry:
return gTopicStates.getOrDefault(topic) return gTopicStates.getOrDefault(topic)