bugfix: 'set' overloadable; further steps for multi threading support

This commit is contained in:
Araq 2011-07-08 01:29:15 +02:00
commit 99bcc233cd
34 changed files with 934 additions and 459 deletions

View 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]")

View file

@ -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}"

View file

@ -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)