bugfix: 'set' overloadable; further steps for multi threading support
This commit is contained in:
parent
170573a87f
commit
99bcc233cd
34 changed files with 934 additions and 459 deletions
89
lib/pure/collections/queues.nim
Normal file
89
lib/pure/collections/queues.nim
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Implementation of a queue. The underlying implementation uses a ``seq``.
|
||||
|
||||
import math
|
||||
|
||||
type
|
||||
TQueue* {.pure, final.}[T] = object ## a queue
|
||||
data: seq[T]
|
||||
rd, wr, count, mask: int
|
||||
|
||||
proc initQueue*[T](initialSize=4): TQueue[T] =
|
||||
## creates a new queue. `initialSize` needs to be a power of 2.
|
||||
assert IsPowerOfTwo(initialSize)
|
||||
result.mask = initialSize-1
|
||||
newSeq(result.data, initialSize)
|
||||
|
||||
proc len*[T](q: TQueue[T]): int =
|
||||
## returns the number of elements of `q`.
|
||||
result = q.count
|
||||
|
||||
iterator items*[T](q: TQueue[T]): T =
|
||||
## yields every element of `q`.
|
||||
var i = q.rd
|
||||
var c = q.count
|
||||
while c > 0:
|
||||
dec c
|
||||
yield q.data[i]
|
||||
i = (i + 1) and q.mask
|
||||
|
||||
proc add*[T](q: var TQueue[T], item: T) =
|
||||
## adds an `item` to the end of the queue `q`.
|
||||
var cap = q.mask+1
|
||||
if q.count >= cap:
|
||||
var n: seq[T]
|
||||
newSeq(n, cap*2)
|
||||
var i = 0
|
||||
for x in items(q):
|
||||
shallowCopy(n[i], x)
|
||||
inc i
|
||||
shallowCopy(q.data, n)
|
||||
q.mask = cap*2 - 1
|
||||
q.wr = q.count
|
||||
q.rd = 0
|
||||
inc q.count
|
||||
q.data[q.wr] = item
|
||||
q.wr = (q.wr + 1) and q.mask
|
||||
|
||||
proc enqueue*[T](q: var TQueue[T], item: T) =
|
||||
## alias for the ``add`` operation.
|
||||
add(q, item)
|
||||
|
||||
proc dequeue*[T](q: var TQueue[T]): T =
|
||||
## removes and returns the first element of the queue `q`.
|
||||
assert q.count > 0
|
||||
dec q.count
|
||||
result = q.data[q.rd]
|
||||
q.rd = (q.rd + 1) and q.mask
|
||||
|
||||
proc `$`*[T](q: TQueue[T]): string =
|
||||
## turns a queue into its string representation.
|
||||
result = "["
|
||||
for x in items(q):
|
||||
if result.len > 1: result.add(", ")
|
||||
result.add($x)
|
||||
result.add("]")
|
||||
|
||||
when isMainModule:
|
||||
var q = initQueue[int]()
|
||||
q.add(123)
|
||||
q.add(9)
|
||||
q.add(4)
|
||||
var first = q.dequeue
|
||||
q.add(56)
|
||||
q.add(6)
|
||||
var second = q.dequeue
|
||||
q.add(789)
|
||||
|
||||
assert first == 123
|
||||
assert second == 9
|
||||
assert($q == "[4, 56, 6, 789]")
|
||||
|
||||
|
|
@ -8,7 +8,26 @@
|
|||
#
|
||||
|
||||
## This module contains procs for serialization and deseralization of
|
||||
## arbitrary Nimrod data structures. The serialization format uses JSON.
|
||||
## arbitrary Nimrod data structures. The serialization format uses JSON.
|
||||
##
|
||||
## **Restriction**: For objects their type is **not** serialized. This means
|
||||
## essentially that it does not work if the object has some other runtime
|
||||
## type than its compiletime type:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
##
|
||||
## type
|
||||
## TA = object
|
||||
## TB = object of TA
|
||||
## f: int
|
||||
##
|
||||
## var
|
||||
## a: ref TA
|
||||
## b: ref TB
|
||||
##
|
||||
## new(b)
|
||||
## a = b
|
||||
## echo($$a[]) # produces "{}", not "{f: 0}"
|
||||
|
||||
import streams, typeinfo, json, intsets, tables
|
||||
|
||||
|
|
@ -286,3 +305,15 @@ when isMainModule:
|
|||
echo($$test7)
|
||||
testit(test7)
|
||||
|
||||
type
|
||||
TA = object
|
||||
TB = object of TA
|
||||
f: int
|
||||
|
||||
var
|
||||
a: ref TA
|
||||
b: ref TB
|
||||
new(b)
|
||||
a = b
|
||||
echo($$a[]) # produces "{}", not "{f: 0}"
|
||||
|
||||
|
|
|
|||
|
|
@ -77,11 +77,14 @@ proc startProcess*(command: string,
|
|||
## If ``env == nil`` the environment is inherited of
|
||||
## the parent process. `options` are additional flags that may be passed
|
||||
## to `startProcess`. See the documentation of ``TProcessOption`` for the
|
||||
## meaning of these flags.
|
||||
## meaning of these flags. You need to `close` the process when done.
|
||||
##
|
||||
## Return value: The newly created process object. Nil is never returned,
|
||||
## but ``EOS`` is raised in case of an error.
|
||||
|
||||
proc close*(p: PProcess) {.rtl, extern: "nosp$1".}
|
||||
## When the process has finished executing, cleanup related handles
|
||||
|
||||
proc suspend*(p: PProcess) {.rtl, extern: "nosp$1".}
|
||||
## Suspends the process `p`.
|
||||
|
||||
|
|
@ -179,6 +182,7 @@ proc execProcesses*(cmds: openArray[string],
|
|||
err.add("\n")
|
||||
echo(err)
|
||||
result = max(waitForExit(q[r]), result)
|
||||
if q[r] != nil: close(q[r])
|
||||
q[r] = startProcessAux(cmds[i], options=options)
|
||||
r = (r + 1) mod n
|
||||
else:
|
||||
|
|
@ -189,15 +193,18 @@ proc execProcesses*(cmds: openArray[string],
|
|||
if not running(q[r]):
|
||||
#echo(outputStream(q[r]).readLine())
|
||||
result = max(waitForExit(q[r]), result)
|
||||
if q[r] != nil: close(q[r])
|
||||
q[r] = startProcessAux(cmds[i], options=options)
|
||||
inc(i)
|
||||
if i > high(cmds): break
|
||||
for i in 0..m-1:
|
||||
if q[i] != nil: close(q[i])
|
||||
result = max(waitForExit(q[i]), result)
|
||||
else:
|
||||
for i in 0..high(cmds):
|
||||
var p = startProcessAux(cmds[i], options=options)
|
||||
result = max(waitForExit(p), result)
|
||||
close(p)
|
||||
|
||||
proc select*(readfds: var seq[PProcess], timeout = 500): int
|
||||
## `select` with a sensible Nimrod interface. `timeout` is in miliseconds.
|
||||
|
|
@ -215,6 +222,8 @@ when not defined(useNimRtl):
|
|||
while running(p) or not outp.atEnd(outp):
|
||||
result.add(outp.readLine())
|
||||
result.add("\n")
|
||||
outp.close(outp)
|
||||
close(p)
|
||||
|
||||
when false:
|
||||
proc deallocCStringArray(a: cstringArray) =
|
||||
|
|
@ -356,6 +365,12 @@ when defined(Windows) and not defined(useNimRtl):
|
|||
result.FProcessHandle = procInfo.hProcess
|
||||
result.id = procInfo.dwProcessID
|
||||
|
||||
proc close(p: PProcess) =
|
||||
discard CloseHandle(p.inputHandle)
|
||||
discard CloseHandle(p.outputHandle)
|
||||
discard CloseHandle(p.errorHandle)
|
||||
discard CloseHandle(p.FProcessHandle)
|
||||
|
||||
proc suspend(p: PProcess) =
|
||||
discard SuspendThread(p.FProcessHandle)
|
||||
|
||||
|
|
@ -523,6 +538,11 @@ elif not defined(useNimRtl):
|
|||
discard close(p_stdin[readIdx])
|
||||
discard close(p_stdout[writeIdx])
|
||||
|
||||
proc close(p: PProcess) =
|
||||
discard close(p.inputHandle)
|
||||
discard close(p.outputHandle)
|
||||
discard close(p.errorHandle)
|
||||
|
||||
proc suspend(p: PProcess) =
|
||||
discard kill(p.id, SIGSTOP)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue