diff options
Diffstat (limited to 'lib')
-rwxr-xr-x | lib/core/typeinfo.nim | 16 | ||||
-rw-r--r-- | lib/pure/actors.nim | 45 | ||||
-rwxr-xr-x | lib/pure/parsecfg.nim | 1 | ||||
-rwxr-xr-x | lib/system/threads.nim | 8 |
4 files changed, 39 insertions, 31 deletions
diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim index 32042695d..b5e9e1a0f 100755 --- a/lib/core/typeinfo.nim +++ b/lib/core/typeinfo.nim @@ -104,13 +104,17 @@ proc toAny*[T](x: var T): TAny {.inline.} = proc kind*(x: TAny): TAnyKind {.inline.} = ## get the type kind result = TAnyKind(ord(x.rawType.kind)) + +proc size*(x: TAny): int {.inline.} = + ## returns the size of `x`'s type. + result = x.rawType.size proc baseTypeKind*(x: TAny): TAnyKind {.inline.} = ## get the base type's kind; ``akNone`` is returned if `x` has no base type. if x.rawType.base != nil: result = TAnyKind(ord(x.rawType.base.kind)) -proc baseTypeSize*(x: TAny): int = +proc baseTypeSize*(x: TAny): int {.inline.} = ## returns the size of `x`'s basetype. if x.rawType.base != nil: result = x.rawType.base.size @@ -339,8 +343,8 @@ proc getInt64*(x: TAny): int64 = proc getBiggestInt*(x: TAny): biggestInt = ## retrieve the integer value out of `x`. `x` needs to represent - ## some integer, a bool, a char or an enum. The value might be - ## sign-extended to ``biggestInt``. + ## some integer, a bool, a char, an enum or a small enough bit set. + ## The value might be sign-extended to ``biggestInt``. var t = skipRange(x.rawtype) case t.kind of tyInt: result = biggestInt(cast[ptr int](x.value)[]) @@ -350,7 +354,7 @@ proc getBiggestInt*(x: TAny): biggestInt = of tyInt64: result = biggestInt(cast[ptr int64](x.value)[]) of tyBool: result = biggestInt(cast[ptr bool](x.value)[]) of tyChar: result = biggestInt(cast[ptr char](x.value)[]) - of tyEnum: + of tyEnum, tySet: case t.size of 1: result = ze64(cast[ptr int8](x.value)[]) of 2: result = ze64(cast[ptr int16](x.value)[]) @@ -361,7 +365,7 @@ proc getBiggestInt*(x: TAny): biggestInt = proc setBiggestInt*(x: TAny, y: biggestInt) = ## sets the integer value of `x`. `x` needs to represent - ## some integer, a bool, a char or an enum. + ## some integer, a bool, a char, an enum or a small enough bit set. var t = skipRange(x.rawtype) case t.kind of tyInt: cast[ptr int](x.value)[] = int(y) @@ -371,7 +375,7 @@ proc setBiggestInt*(x: TAny, y: biggestInt) = of tyInt64: cast[ptr int64](x.value)[] = int64(y) of tyBool: cast[ptr bool](x.value)[] = y != 0 of tyChar: cast[ptr char](x.value)[] = chr(y.int) - of tyEnum: + of tyEnum, tySet: case t.size of 1: cast[ptr int8](x.value)[] = toU8(y.int) of 2: cast[ptr int16](x.value)[] = toU16(y.int) diff --git a/lib/pure/actors.nim b/lib/pure/actors.nim index 285e3241d..4576cb602 100644 --- a/lib/pure/actors.nim +++ b/lib/pure/actors.nim @@ -30,7 +30,7 @@ proc spawn*[TIn, TOut](action: proc( self: PActor[TIn, TOut]){.thread.}): PActor[TIn, TOut] = ## creates an actor; that is a thread with an inbox. The caller MUST call ## ``join`` because that also frees the associated resources with the actor. - result = allocShared0(sizeof(result[])) + result = cast[PActor[TIn, TOut]](allocShared0(sizeof(result[]))) open(result.i) createThread(result.t, action, result) @@ -52,8 +52,8 @@ proc recv*[TIn, TOut](a: PActor[TIn, TOut]): TTask[TIn, TOut] = ## receives a task from `a`'s inbox. result = recv(a.i) -proc send*[TIn, TOut, X, Y](sender: PActor[X, Z], - receiver: PActor[TIn, TOut], msg: TIn) = +proc send*[TIn, TOut, X, Y](receiver: PActor[TIn, TOut], msg: TIn, + sender: PActor[X, Y]) = ## sends a message to `a`'s inbox. var t: TTask[TIn, TOut] t.receiver = addr(sender.i) @@ -99,9 +99,9 @@ proc poolWorker[TIn, TOut](self: PActor[TIn, TOut]) {.thread.} = var m = self.recv if m.shutDown: break when TOut is void: - action(m.data) + m.action(m.data) else: - self.repy(action(m.data)) + self.repy(m.action(m.data)) proc createActorPool*[TIn, TOut](a: var TActorPool[TIn, TOut], poolSize = 4) = ## creates an actor pool. @@ -109,21 +109,20 @@ proc createActorPool*[TIn, TOut](a: var TActorPool[TIn, TOut], poolSize = 4) = when TOut isnot void: open(a.outputs) for i in 0 .. < a.actors.len: - a.actors[i] = spawn(poolWorker) + a.actors[i] = spawn(poolWorker[TIn, TOut]) proc join*[TIn, TOut](a: var TActorPool[TIn, TOut]) = ## waits for each actor in the actor pool `a` to finish and frees the ## resources attached to `a`. var t: TTask[TIn, TOut] t.shutdown = true - for i in 0 .. < a.actors.len: send(a.actors[i], t) + for i in 0 .. < a.actors.len: send(a.actors[i].i, t) for i in 0 .. < a.actors.len: join(a.actors[i]) when TOut isnot void: close(a.outputs) a.actors = nil template setupTask = - var t: TTask[TIn, TOut] t.action = action shallowCopy(t.data, input) @@ -132,7 +131,7 @@ template schedule = # it remains 'hot' ;-). Round-robin hurts for keeping threads hot. for i in 0..high(a.actors): if a.actors[i].i.ready: - a.actors[i].send(t) + a.actors[i].i.send(t) return # no thread ready :-( --> send message to the thread which has the least # messages pending: @@ -142,27 +141,29 @@ template schedule = var curr = a.actors[i].i.peek if curr == 0: # ok, is ready now: - a.actors[i].send(t) + a.actors[i].i.send(t) return if curr < minVal: minVal = curr minIdx = i - a.actors[minIdx].send(t) + a.actors[minIdx].i.send(t) -proc spawn*[TIn, TOut](p: var TActorPool[TIn, TOut], - action: proc (input: TIn): TOut {.thread.}, - input: TIn): ptr TChannel[TOut] = - ## uses the actor pool to run `action` concurrently. `spawn` is guaranteed - ## to not block. +proc spawn*[TIn, TOut](p: var TActorPool[TIn, TOut], input: TIn, + action: proc (input: TIn): TOut {.thread.} + ): ptr TChannel[TOut] = + ## uses the actor pool to run ``action(input)`` concurrently. + ## `spawn` is guaranteed to not block. + var t: TTask[TIn, TOut] setupTask() result = addr(p.outputs) + t.receiver = result schedule() -proc spawn*[TIn](p: var TActorPool[TIn, void], - action: proc (input: TIn) {.thread.}, - input: TIn) = - ## uses the actor pool to run `action` concurrently. `spawn` is guaranteed - ## to not block. +proc spawn*[TIn](p: var TActorPool[TIn, void], input: TIn, + action: proc (input: TIn) {.thread.}) = + ## uses the actor pool to run ``action(input)`` concurrently. + ## `spawn` is guaranteed to not block. + var t: TTask[TIn, void] setupTask() schedule() @@ -171,7 +172,7 @@ when isMainModule: a: TActorPool[int, void] createActorPool(a) for i in 0 .. < 300: - a.spawn(proc (x: int) {.thread.} = echo x) + a.spawn(i, proc (x: int) {.thread.} = echo x) when false: proc treeDepth(n: PNode): int {.thread.} = diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim index 67644e156..3e85a9ee6 100755 --- a/lib/pure/parsecfg.nim +++ b/lib/pure/parsecfg.nim @@ -323,6 +323,7 @@ proc getKeyValPair(c: var TCfgParser, kind: TCfgEventKind): TCfgEvent = if c.tok.kind == tkSymbol: result.value = c.tok.literal else: + reset result result.kind = cfgError result.msg = errorStr(c, "symbol expected, but found: " & c.tok.literal) rawGetTok(c, c.tok) diff --git a/lib/system/threads.nim b/lib/system/threads.nim index 2079762f8..9fbea2e1a 100755 --- a/lib/system/threads.nim +++ b/lib/system/threads.nim @@ -252,8 +252,10 @@ type object of TGcThread ## Nimrod thread. A thread is a heavy object (~14K) ## that **must not** be part of a message! Use ## a ``TThreadId`` for that. - dataFn: proc (m: TArg) - when TArg isnot void: + when TArg is void: + dataFn: proc () + else: + dataFn: proc (m: TArg) data: TArg TThreadId*[TArg] = ptr TThread[TArg] ## the current implementation uses ## a pointer as a thread ID. @@ -273,7 +275,7 @@ template ThreadProcWrapperBody(closure: expr) = when defined(registerThread): t.stackBottom = addr(t) registerThread(t) - if TArg is void: t.dataFn() + when TArg is void: t.dataFn() else: t.dataFn(t.data) when defined(registerThread): unregisterThread(t) when defined(deallocOsPages): deallocOsPages() |