mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-06 20:04:18 +00:00
basic thread support; still broken on Windows; untested on Mac OS X
This commit is contained in:
@@ -51,6 +51,8 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/idents.c -o build/1_1/idents.o
|
||||
%CC% %COMP_FLAGS% -Ibuild -c build/1_1/idents.c -o build/1_1/idents.o
|
||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/astalgo.c -o build/1_1/astalgo.o
|
||||
%CC% %COMP_FLAGS% -Ibuild -c build/1_1/astalgo.c -o build/1_1/astalgo.o
|
||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/rodutils.c -o build/1_1/rodutils.o
|
||||
%CC% %COMP_FLAGS% -Ibuild -c build/1_1/rodutils.c -o build/1_1/rodutils.o
|
||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/extccomp.c -o build/1_1/extccomp.o
|
||||
%CC% %COMP_FLAGS% -Ibuild -c build/1_1/extccomp.c -o build/1_1/extccomp.o
|
||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/osproc.c -o build/1_1/osproc.o
|
||||
@@ -146,8 +148,8 @@ ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/transf.c -o build/1_1/transf.o
|
||||
ECHO %CC% %COMP_FLAGS% -Ibuild -c build/1_1/parseopt.c -o build/1_1/parseopt.o
|
||||
%CC% %COMP_FLAGS% -Ibuild -c build/1_1/parseopt.c -o build/1_1/parseopt.o
|
||||
|
||||
ECHO %LINKER% %LINK_FLAGS% -o bin\nimrod.exe build/1_1/nim__dat.o build/1_1/system.o build/1_1/nimrod.o build/1_1/times.o build/1_1/strutils.o build/1_1/parseutils.o build/1_1/winlean.o build/1_1/commands.o build/1_1/os.o build/1_1/msgs.o build/1_1/options.o build/1_1/lists.o build/1_1/nstrtabs.o build/1_1/nhashes.o build/1_1/nversion.o build/1_1/condsyms.o build/1_1/ast.o build/1_1/crc.o build/1_1/ropes.o build/1_1/platform.o build/1_1/idents.o build/1_1/astalgo.o build/1_1/extccomp.o build/1_1/osproc.o build/1_1/strtabs.o build/1_1/hashes.o build/1_1/streams.o build/1_1/wordrecg.o build/1_1/scanner.o build/1_1/lexbase.o build/1_1/llstream.o build/1_1/nimconf.o build/1_1/main.o build/1_1/syntaxes.o build/1_1/pnimsyn.o build/1_1/pbraces.o build/1_1/ptmplsyn.o build/1_1/rnimsyn.o build/1_1/filters.o build/1_1/rodread.o build/1_1/rodwrite.o build/1_1/passes.o build/1_1/types.o build/1_1/trees.o build/1_1/math.o build/1_1/magicsys.o build/1_1/nimsets.o build/1_1/bitsets.o build/1_1/importer.o build/1_1/lookups.o build/1_1/semdata.o build/1_1/treetab.o build/1_1/sem.o build/1_1/evals.o build/1_1/semfold.o build/1_1/procfind.o build/1_1/pragmas.o build/1_1/docgen.o build/1_1/rst.o build/1_1/highlite.o build/1_1/cgen.o build/1_1/ccgutils.o build/1_1/cgmeth.o build/1_1/ecmasgen.o build/1_1/interact.o build/1_1/passaux.o build/1_1/depends.o build/1_1/transf.o build/1_1/parseopt.o
|
||||
%LINKER% %LINK_FLAGS% -o bin\nimrod.exe build/1_1/nim__dat.o build/1_1/system.o build/1_1/nimrod.o build/1_1/times.o build/1_1/strutils.o build/1_1/parseutils.o build/1_1/winlean.o build/1_1/commands.o build/1_1/os.o build/1_1/msgs.o build/1_1/options.o build/1_1/lists.o build/1_1/nstrtabs.o build/1_1/nhashes.o build/1_1/nversion.o build/1_1/condsyms.o build/1_1/ast.o build/1_1/crc.o build/1_1/ropes.o build/1_1/platform.o build/1_1/idents.o build/1_1/astalgo.o build/1_1/extccomp.o build/1_1/osproc.o build/1_1/strtabs.o build/1_1/hashes.o build/1_1/streams.o build/1_1/wordrecg.o build/1_1/scanner.o build/1_1/lexbase.o build/1_1/llstream.o build/1_1/nimconf.o build/1_1/main.o build/1_1/syntaxes.o build/1_1/pnimsyn.o build/1_1/pbraces.o build/1_1/ptmplsyn.o build/1_1/rnimsyn.o build/1_1/filters.o build/1_1/rodread.o build/1_1/rodwrite.o build/1_1/passes.o build/1_1/types.o build/1_1/trees.o build/1_1/math.o build/1_1/magicsys.o build/1_1/nimsets.o build/1_1/bitsets.o build/1_1/importer.o build/1_1/lookups.o build/1_1/semdata.o build/1_1/treetab.o build/1_1/sem.o build/1_1/evals.o build/1_1/semfold.o build/1_1/procfind.o build/1_1/pragmas.o build/1_1/docgen.o build/1_1/rst.o build/1_1/highlite.o build/1_1/cgen.o build/1_1/ccgutils.o build/1_1/cgmeth.o build/1_1/ecmasgen.o build/1_1/interact.o build/1_1/passaux.o build/1_1/depends.o build/1_1/transf.o build/1_1/parseopt.o
|
||||
ECHO %LINKER% %LINK_FLAGS% -o bin\nimrod.exe build/1_1/nim__dat.o build/1_1/system.o build/1_1/nimrod.o build/1_1/times.o build/1_1/strutils.o build/1_1/parseutils.o build/1_1/winlean.o build/1_1/commands.o build/1_1/os.o build/1_1/msgs.o build/1_1/options.o build/1_1/lists.o build/1_1/nstrtabs.o build/1_1/nhashes.o build/1_1/nversion.o build/1_1/condsyms.o build/1_1/ast.o build/1_1/crc.o build/1_1/ropes.o build/1_1/platform.o build/1_1/idents.o build/1_1/astalgo.o build/1_1/rodutils.o build/1_1/extccomp.o build/1_1/osproc.o build/1_1/strtabs.o build/1_1/hashes.o build/1_1/streams.o build/1_1/wordrecg.o build/1_1/scanner.o build/1_1/lexbase.o build/1_1/llstream.o build/1_1/nimconf.o build/1_1/main.o build/1_1/syntaxes.o build/1_1/pnimsyn.o build/1_1/pbraces.o build/1_1/ptmplsyn.o build/1_1/rnimsyn.o build/1_1/filters.o build/1_1/rodread.o build/1_1/rodwrite.o build/1_1/passes.o build/1_1/types.o build/1_1/trees.o build/1_1/math.o build/1_1/magicsys.o build/1_1/nimsets.o build/1_1/bitsets.o build/1_1/importer.o build/1_1/lookups.o build/1_1/semdata.o build/1_1/treetab.o build/1_1/sem.o build/1_1/evals.o build/1_1/semfold.o build/1_1/procfind.o build/1_1/pragmas.o build/1_1/docgen.o build/1_1/rst.o build/1_1/highlite.o build/1_1/cgen.o build/1_1/ccgutils.o build/1_1/cgmeth.o build/1_1/ecmasgen.o build/1_1/interact.o build/1_1/passaux.o build/1_1/depends.o build/1_1/transf.o build/1_1/parseopt.o
|
||||
%LINKER% %LINK_FLAGS% -o bin\nimrod.exe build/1_1/nim__dat.o build/1_1/system.o build/1_1/nimrod.o build/1_1/times.o build/1_1/strutils.o build/1_1/parseutils.o build/1_1/winlean.o build/1_1/commands.o build/1_1/os.o build/1_1/msgs.o build/1_1/options.o build/1_1/lists.o build/1_1/nstrtabs.o build/1_1/nhashes.o build/1_1/nversion.o build/1_1/condsyms.o build/1_1/ast.o build/1_1/crc.o build/1_1/ropes.o build/1_1/platform.o build/1_1/idents.o build/1_1/astalgo.o build/1_1/rodutils.o build/1_1/extccomp.o build/1_1/osproc.o build/1_1/strtabs.o build/1_1/hashes.o build/1_1/streams.o build/1_1/wordrecg.o build/1_1/scanner.o build/1_1/lexbase.o build/1_1/llstream.o build/1_1/nimconf.o build/1_1/main.o build/1_1/syntaxes.o build/1_1/pnimsyn.o build/1_1/pbraces.o build/1_1/ptmplsyn.o build/1_1/rnimsyn.o build/1_1/filters.o build/1_1/rodread.o build/1_1/rodwrite.o build/1_1/passes.o build/1_1/types.o build/1_1/trees.o build/1_1/math.o build/1_1/magicsys.o build/1_1/nimsets.o build/1_1/bitsets.o build/1_1/importer.o build/1_1/lookups.o build/1_1/semdata.o build/1_1/treetab.o build/1_1/sem.o build/1_1/evals.o build/1_1/semfold.o build/1_1/procfind.o build/1_1/pragmas.o build/1_1/docgen.o build/1_1/rst.o build/1_1/highlite.o build/1_1/cgen.o build/1_1/ccgutils.o build/1_1/cgmeth.o build/1_1/ecmasgen.o build/1_1/interact.o build/1_1/passaux.o build/1_1/depends.o build/1_1/transf.o build/1_1/parseopt.o
|
||||
|
||||
ECHO SUCCESS
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Configuration file for the Nimrod Compiler.
|
||||
# (c) 2010 Andreas Rumpf
|
||||
# (c) 2011 Andreas Rumpf
|
||||
|
||||
# Feel free to edit the default values as you need.
|
||||
|
||||
@@ -14,6 +14,7 @@ cc = gcc
|
||||
lib = "nimlib"
|
||||
@end
|
||||
|
||||
path="$lib/core"
|
||||
path="$lib/pure"
|
||||
path="$lib/impure"
|
||||
path="$lib/wrappers"
|
||||
|
||||
@@ -31,6 +31,9 @@ Core
|
||||
implicitly by the compiler. Do not import it directly. It relies on compiler
|
||||
magic to work.
|
||||
|
||||
* `threads <threads.html>`_
|
||||
Nimrod thread support.
|
||||
|
||||
* `macros <macros.html>`_
|
||||
Contains the AST API and documentation of Nimrod for writing macros.
|
||||
|
||||
|
||||
20
install.sh
20
install.sh
@@ -321,6 +321,8 @@ if [ $# -eq 1 ] ; then
|
||||
chmod 644 $libdir/system/sysstr.nim
|
||||
cp lib/system/systhread.nim $libdir/system/systhread.nim
|
||||
chmod 644 $libdir/system/systhread.nim
|
||||
cp lib/pure/base64.nim $libdir/pure/base64.nim
|
||||
chmod 644 $libdir/pure/base64.nim
|
||||
cp lib/pure/browsers.nim $libdir/pure/browsers.nim
|
||||
chmod 644 $libdir/pure/browsers.nim
|
||||
cp lib/pure/cgi.nim $libdir/pure/cgi.nim
|
||||
@@ -329,12 +331,12 @@ if [ $# -eq 1 ] ; then
|
||||
chmod 644 $libdir/pure/colors.nim
|
||||
cp lib/pure/complex.nim $libdir/pure/complex.nim
|
||||
chmod 644 $libdir/pure/complex.nim
|
||||
cp lib/pure/cookies.nim $libdir/pure/cookies.nim
|
||||
chmod 644 $libdir/pure/cookies.nim
|
||||
cp lib/pure/dynlib.nim $libdir/pure/dynlib.nim
|
||||
chmod 644 $libdir/pure/dynlib.nim
|
||||
cp lib/pure/hashes.nim $libdir/pure/hashes.nim
|
||||
chmod 644 $libdir/pure/hashes.nim
|
||||
cp lib/pure/hashtabs.nim $libdir/pure/hashtabs.nim
|
||||
chmod 644 $libdir/pure/hashtabs.nim
|
||||
cp lib/pure/htmlparser.nim $libdir/pure/htmlparser.nim
|
||||
chmod 644 $libdir/pure/htmlparser.nim
|
||||
cp lib/pure/httpclient.nim $libdir/pure/httpclient.nim
|
||||
@@ -347,8 +349,6 @@ if [ $# -eq 1 ] ; then
|
||||
chmod 644 $libdir/pure/lexbase.nim
|
||||
cp lib/pure/logging.nim $libdir/pure/logging.nim
|
||||
chmod 644 $libdir/pure/logging.nim
|
||||
cp lib/pure/macros.nim $libdir/pure/macros.nim
|
||||
chmod 644 $libdir/pure/macros.nim
|
||||
cp lib/pure/math.nim $libdir/pure/math.nim
|
||||
chmod 644 $libdir/pure/math.nim
|
||||
cp lib/pure/md5.nim $libdir/pure/md5.nim
|
||||
@@ -377,6 +377,10 @@ if [ $# -eq 1 ] ; then
|
||||
chmod 644 $libdir/pure/regexprs.nim
|
||||
cp lib/pure/ropes.nim $libdir/pure/ropes.nim
|
||||
chmod 644 $libdir/pure/ropes.nim
|
||||
cp lib/pure/scgi.nim $libdir/pure/scgi.nim
|
||||
chmod 644 $libdir/pure/scgi.nim
|
||||
cp lib/pure/smtp.nim $libdir/pure/smtp.nim
|
||||
chmod 644 $libdir/pure/smtp.nim
|
||||
cp lib/pure/sockets.nim $libdir/pure/sockets.nim
|
||||
chmod 644 $libdir/pure/sockets.nim
|
||||
cp lib/pure/streams.nim $libdir/pure/streams.nim
|
||||
@@ -391,8 +395,6 @@ if [ $# -eq 1 ] ; then
|
||||
chmod 644 $libdir/pure/times.nim
|
||||
cp lib/pure/unicode.nim $libdir/pure/unicode.nim
|
||||
chmod 644 $libdir/pure/unicode.nim
|
||||
cp lib/pure/variants.nim $libdir/pure/variants.nim
|
||||
chmod 644 $libdir/pure/variants.nim
|
||||
cp lib/pure/xmldom.nim $libdir/pure/xmldom.nim
|
||||
chmod 644 $libdir/pure/xmldom.nim
|
||||
cp lib/pure/xmldomparser.nim $libdir/pure/xmldomparser.nim
|
||||
@@ -421,10 +423,14 @@ if [ $# -eq 1 ] ; then
|
||||
chmod 644 $libdir/impure/osinfo_win.nim
|
||||
cp lib/impure/re.nim $libdir/impure/re.nim
|
||||
chmod 644 $libdir/impure/re.nim
|
||||
cp lib/impure/ssl.nim $libdir/impure/ssl.nim
|
||||
chmod 644 $libdir/impure/ssl.nim
|
||||
cp lib/impure/web.nim $libdir/impure/web.nim
|
||||
chmod 644 $libdir/impure/web.nim
|
||||
cp lib/impure/zipfiles.nim $libdir/impure/zipfiles.nim
|
||||
chmod 644 $libdir/impure/zipfiles.nim
|
||||
cp lib/wrappers/claro.nim $libdir/wrappers/claro.nim
|
||||
chmod 644 $libdir/wrappers/claro.nim
|
||||
cp lib/wrappers/expat.nim $libdir/wrappers/expat.nim
|
||||
chmod 644 $libdir/wrappers/expat.nim
|
||||
cp lib/wrappers/iup.nim $libdir/wrappers/iup.nim
|
||||
@@ -435,6 +441,8 @@ if [ $# -eq 1 ] ; then
|
||||
chmod 644 $libdir/wrappers/mysql.nim
|
||||
cp lib/wrappers/odbcsql.nim $libdir/wrappers/odbcsql.nim
|
||||
chmod 644 $libdir/wrappers/odbcsql.nim
|
||||
cp lib/wrappers/openssl.nim $libdir/wrappers/openssl.nim
|
||||
chmod 644 $libdir/wrappers/openssl.nim
|
||||
cp lib/wrappers/pcre.nim $libdir/wrappers/pcre.nim
|
||||
chmod 644 $libdir/wrappers/pcre.nim
|
||||
cp lib/wrappers/postgres.nim $libdir/wrappers/postgres.nim
|
||||
|
||||
259
lib/core/marshal.nim
Normal file
259
lib/core/marshal.nim
Normal file
@@ -0,0 +1,259 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module contains procs for serialization and deseralization of
|
||||
## arbitrary Nimrod data structures. XXX This is not implemented yet!
|
||||
|
||||
import streams
|
||||
|
||||
proc load*[T](s: PStream, data: var T) {.magic: "Load".}
|
||||
## loads `data` from the stream `s`. Raises `EIO` in case of an error.
|
||||
|
||||
proc store*[T](s: PStream, data: T) {.magic: "Store".}
|
||||
## stores `data` into the stream `s`. Raises `EIO` in case of an error.
|
||||
|
||||
|
||||
proc reprInt(x: int64): string {.compilerproc.} = return $x
|
||||
proc reprFloat(x: float): string {.compilerproc.} = return $x
|
||||
|
||||
proc reprPointer(x: pointer): string {.compilerproc.} =
|
||||
var buf: array [0..59, char]
|
||||
c_sprintf(buf, "%p", x)
|
||||
return $buf
|
||||
|
||||
proc reprStrAux(result: var string, s: string) =
|
||||
if cast[pointer](s) == nil:
|
||||
add result, "nil"
|
||||
return
|
||||
add result, reprPointer(cast[pointer](s)) & "\""
|
||||
for c in items(s):
|
||||
case c
|
||||
of '"': add result, "\\\""
|
||||
of '\\': add result, "\\\\" # BUGFIX: forgotten
|
||||
of '\10': add result, "\\10\"\n\"" # " \n " # better readability
|
||||
of '\128' .. '\255', '\0'..'\9', '\11'..'\31':
|
||||
add result, "\\" & reprInt(ord(c))
|
||||
else: result.add(c)
|
||||
add result, "\""
|
||||
|
||||
proc reprStr(s: string): string {.compilerRtl.} =
|
||||
result = ""
|
||||
reprStrAux(result, s)
|
||||
|
||||
proc reprBool(x: bool): string {.compilerRtl.} =
|
||||
if x: result = "true"
|
||||
else: result = "false"
|
||||
|
||||
proc reprChar(x: char): string {.compilerRtl.} =
|
||||
result = "\'"
|
||||
case x
|
||||
of '"': add result, "\\\""
|
||||
of '\\': add result, "\\\\"
|
||||
of '\128' .. '\255', '\0'..'\31': add result, "\\" & reprInt(ord(x))
|
||||
else: add result, x
|
||||
add result, "\'"
|
||||
|
||||
proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} =
|
||||
if e <% typ.node.len: # BUGFIX
|
||||
result = $typ.node.sons[e].name
|
||||
else:
|
||||
result = $e & " (invalid data!)"
|
||||
|
||||
type
|
||||
pbyteArray = ptr array[0.. 0xffff, byte]
|
||||
|
||||
proc addSetElem(result: var string, elem: int, typ: PNimType) =
|
||||
case typ.kind
|
||||
of tyEnum: add result, reprEnum(elem, typ)
|
||||
of tyBool: add result, reprBool(bool(elem))
|
||||
of tyChar: add result, reprChar(chr(elem))
|
||||
of tyRange: addSetElem(result, elem, typ.base)
|
||||
of tyInt..tyInt64: add result, reprInt(elem)
|
||||
else: # data corrupt --> inform the user
|
||||
add result, " (invalid data!)"
|
||||
|
||||
proc reprSetAux(result: var string, p: pointer, typ: PNimType) =
|
||||
# "typ.slots.len" field is for sets the "first" field
|
||||
var elemCounter = 0 # we need this flag for adding the comma at
|
||||
# the right places
|
||||
add result, "{"
|
||||
var u: int64
|
||||
case typ.size
|
||||
of 1: u = ze64(cast[ptr int8](p)^)
|
||||
of 2: u = ze64(cast[ptr int16](p)^)
|
||||
of 4: u = ze64(cast[ptr int32](p)^)
|
||||
of 8: u = cast[ptr int64](p)^
|
||||
else:
|
||||
var a = cast[pbyteArray](p)
|
||||
for i in 0 .. typ.size*8-1:
|
||||
if (ze(a[i div 8]) and (1 shl (i mod 8))) != 0:
|
||||
if elemCounter > 0: add result, ", "
|
||||
addSetElem(result, i+typ.node.len, typ.base)
|
||||
inc(elemCounter)
|
||||
if typ.size <= 8:
|
||||
for i in 0..sizeof(int64)*8-1:
|
||||
if (u and (1 shl i)) != 0:
|
||||
if elemCounter > 0: add result, ", "
|
||||
addSetElem(result, i+typ.node.len, typ.base)
|
||||
inc(elemCounter)
|
||||
add result, "}"
|
||||
|
||||
proc reprSet(p: pointer, typ: PNimType): string {.compilerRtl.} =
|
||||
result = ""
|
||||
reprSetAux(result, p, typ)
|
||||
|
||||
type
|
||||
TReprClosure {.final.} = object # we cannot use a global variable here
|
||||
# as this wouldn't be thread-safe
|
||||
marked: TCellSet
|
||||
recdepth: int # do not recurse endless
|
||||
indent: int # indentation
|
||||
|
||||
when not defined(useNimRtl):
|
||||
proc initReprClosure(cl: var TReprClosure) =
|
||||
Init(cl.marked)
|
||||
cl.recdepth = -1 # default is to display everything!
|
||||
cl.indent = 0
|
||||
|
||||
proc deinitReprClosure(cl: var TReprClosure) =
|
||||
Deinit(cl.marked)
|
||||
|
||||
proc reprBreak(result: var string, cl: TReprClosure) =
|
||||
add result, "\n"
|
||||
for i in 0..cl.indent-1: add result, ' '
|
||||
|
||||
proc reprAux(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure)
|
||||
|
||||
proc reprArray(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
add result, "["
|
||||
var bs = typ.base.size
|
||||
for i in 0..typ.size div bs - 1:
|
||||
if i > 0: add result, ", "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), typ.base, cl)
|
||||
add result, "]"
|
||||
|
||||
proc reprSequence(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
if p == nil:
|
||||
add result, "nil"
|
||||
return
|
||||
result.add(reprPointer(p) & "[")
|
||||
var bs = typ.base.size
|
||||
for i in 0..cast[PGenericSeq](p).len-1:
|
||||
if i > 0: add result, ", "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + GenericSeqSize + i*bs),
|
||||
typ.Base, cl)
|
||||
add result, "]"
|
||||
|
||||
proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
|
||||
cl: var TReprClosure) =
|
||||
case n.kind
|
||||
of nkNone: assert(false)
|
||||
of nkSlot:
|
||||
add result, $n.name
|
||||
add result, " = "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
|
||||
of nkList:
|
||||
for i in 0..n.len-1:
|
||||
if i > 0: add result, ",\n"
|
||||
reprRecordAux(result, p, n.sons[i], cl)
|
||||
of nkCase:
|
||||
var m = selectBranch(p, n)
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + n.offset), n.typ, cl)
|
||||
if m != nil: reprRecordAux(result, p, m, cl)
|
||||
|
||||
proc reprRecord(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
add result, "["
|
||||
reprRecordAux(result, p, typ.node, cl)
|
||||
add result, "]"
|
||||
|
||||
proc reprRef(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
# we know that p is not nil here:
|
||||
when defined(boehmGC) or defined(nogc):
|
||||
var cell = cast[PCell](p)
|
||||
else:
|
||||
var cell = usrToCell(p)
|
||||
add result, "ref " & reprPointer(p)
|
||||
if cell notin cl.marked:
|
||||
# only the address is shown:
|
||||
incl(cl.marked, cell)
|
||||
add result, " --> "
|
||||
reprAux(result, p, typ.base, cl)
|
||||
|
||||
proc reprAux(result: var string, p: pointer, typ: PNimType,
|
||||
cl: var TReprClosure) =
|
||||
if cl.recdepth == 0:
|
||||
add result, "..."
|
||||
return
|
||||
dec(cl.recdepth)
|
||||
case typ.kind
|
||||
of tySet: reprSetAux(result, p, typ)
|
||||
of tyArray: reprArray(result, p, typ, cl)
|
||||
of tyTuple, tyPureObject: reprRecord(result, p, typ, cl)
|
||||
of tyObject:
|
||||
var t = cast[ptr PNimType](p)^
|
||||
reprRecord(result, p, t, cl)
|
||||
of tyRef, tyPtr:
|
||||
assert(p != nil)
|
||||
if cast[ppointer](p)^ == nil: add result, "nil"
|
||||
else: reprRef(result, cast[ppointer](p)^, typ, cl)
|
||||
of tySequence:
|
||||
reprSequence(result, cast[ppointer](p)^, typ, cl)
|
||||
of tyInt: add result, $(cast[ptr int](p)^)
|
||||
of tyInt8: add result, $int(cast[ptr Int8](p)^)
|
||||
of tyInt16: add result, $int(cast[ptr Int16](p)^)
|
||||
of tyInt32: add result, $int(cast[ptr Int32](p)^)
|
||||
of tyInt64: add result, $(cast[ptr Int64](p)^)
|
||||
of tyFloat: add result, $(cast[ptr float](p)^)
|
||||
of tyFloat32: add result, $(cast[ptr float32](p)^)
|
||||
of tyFloat64: add result, $(cast[ptr float64](p)^)
|
||||
of tyEnum: add result, reprEnum(cast[ptr int](p)^, typ)
|
||||
of tyBool: add result, reprBool(cast[ptr bool](p)^)
|
||||
of tyChar: add result, reprChar(cast[ptr char](p)^)
|
||||
of tyString: reprStrAux(result, cast[ptr string](p)^)
|
||||
of tyCString: reprStrAux(result, $(cast[ptr cstring](p)^))
|
||||
of tyRange: reprAux(result, p, typ.base, cl)
|
||||
of tyProc, tyPointer:
|
||||
if cast[ppointer](p)^ == nil: add result, "nil"
|
||||
else: add result, reprPointer(cast[ppointer](p)^)
|
||||
else:
|
||||
add result, "(invalid data!)"
|
||||
inc(cl.recdepth)
|
||||
|
||||
proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {.
|
||||
compilerRtl.} =
|
||||
var
|
||||
cl: TReprClosure
|
||||
initReprClosure(cl)
|
||||
result = "["
|
||||
var bs = elemtyp.size
|
||||
for i in 0..length - 1:
|
||||
if i > 0: add result, ", "
|
||||
reprAux(result, cast[pointer](cast[TAddress](p) + i*bs), elemtyp, cl)
|
||||
add result, "]"
|
||||
deinitReprClosure(cl)
|
||||
|
||||
when not defined(useNimRtl):
|
||||
proc reprAny(p: pointer, typ: PNimType): string =
|
||||
var
|
||||
cl: TReprClosure
|
||||
initReprClosure(cl)
|
||||
result = ""
|
||||
if typ.kind in {tyObject, tyPureObject, tyTuple, tyArray, tySet}:
|
||||
reprAux(result, p, typ, cl)
|
||||
else:
|
||||
var p = p
|
||||
reprAux(result, addr(p), typ, cl)
|
||||
add result, "\n"
|
||||
deinitReprClosure(cl)
|
||||
|
||||
174
lib/core/threads.nim
Normal file
174
lib/core/threads.nim
Normal file
@@ -0,0 +1,174 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Basic thread support for Nimrod. Note that Nimrod's default GC is still
|
||||
## single-threaded. This means that either your threads should not allocate
|
||||
## GC'ed memory, or you should compile with ``--gc:none`` or ``--gc:boehm``.
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
##
|
||||
## var
|
||||
## thr: array [0..4, TThread]
|
||||
## L: TLock
|
||||
##
|
||||
## proc threadFunc(c: pointer) {.procvar.} =
|
||||
## for i in 0..9:
|
||||
## Aquire(L) # lock stdout
|
||||
## echo i
|
||||
## Release(L)
|
||||
##
|
||||
## InitLock(L)
|
||||
##
|
||||
## for i in 0..high(thr):
|
||||
## createThread(thr[i], threadFunc)
|
||||
## for i in 0..high(thr):
|
||||
## joinThread(thr[i])
|
||||
|
||||
|
||||
# We jump through some hops here to ensure that Nimrod thread procs can have
|
||||
# the Nimrod calling convention. This is needed because thread procs are
|
||||
# ``stdcall`` on Windows and ``noconv`` on UNIX. Alternative would be to just
|
||||
# use ``stdcall`` since it is mapped to ``noconv`` on UNIX anyway. However,
|
||||
# the current approach will likely result in less problems later when we have
|
||||
# GC'ed closures in Nimrod.
|
||||
|
||||
type
|
||||
TThreadProc* = proc (closure: pointer) ## Standard Nimrod thread proc.
|
||||
TThreadProcClosure {.pure, final.} = object
|
||||
fn: TThreadProc
|
||||
data: pointer
|
||||
|
||||
when defined(Windows):
|
||||
type
|
||||
THandle = int
|
||||
TSysThread = THandle
|
||||
TSysLock {.final, pure.} = object # CRITICAL_SECTION in WinApi
|
||||
DebugInfo: pointer
|
||||
LockCount: int32
|
||||
RecursionCount: int32
|
||||
OwningThread: int
|
||||
LockSemaphore: int
|
||||
Reserved: int32
|
||||
|
||||
TWinThreadProc = proc (x: pointer): int32 {.stdcall.}
|
||||
|
||||
TLock* = TSysLock ## Standard Nimrod Lock type.
|
||||
|
||||
proc InitLock*(L: var TLock) {.stdcall,
|
||||
dynlib: "kernel32", importc: "InitializeCriticalSection".}
|
||||
## Initializes the lock `L`.
|
||||
|
||||
proc Aquire*(L: var TLock) {.stdcall,
|
||||
dynlib: "kernel32", importc: "EnterCriticalSection".}
|
||||
## Aquires the lock `L`.
|
||||
|
||||
proc Release*(L: var TLock) {.stdcall,
|
||||
dynlib: "kernel32", importc: "LeaveCriticalSection".}
|
||||
## Releases the lock `L`.
|
||||
|
||||
proc CreateThread(lpThreadAttributes: Pointer, dwStackSize: int32,
|
||||
lpStartAddress: TWinThreadProc,
|
||||
lpParameter: Pointer,
|
||||
dwCreationFlags: int32, lpThreadId: var int32): THandle {.
|
||||
stdcall, dynlib: "kernel32", importc: "CreateThread".}
|
||||
|
||||
when false:
|
||||
proc winSuspendThread(hThread: TSysThread): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "SuspendThread".}
|
||||
|
||||
proc winResumeThread(hThread: TSysThread): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "ResumeThread".}
|
||||
|
||||
proc WaitForMultipleObjects(nCount: int32,
|
||||
lpHandles: ptr array[0..10, THandle],
|
||||
bWaitAll: int32,
|
||||
dwMilliseconds: int32): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".}
|
||||
|
||||
proc WaitForSingleObject(hHandle: THANDLE, dwMilliseconds: int32): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "WaitForSingleObject".}
|
||||
|
||||
proc TerminateThread(hThread: THandle, dwExitCode: int32): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "TerminateThread".}
|
||||
|
||||
proc threadProcWrapper(closure: pointer): int32 {.stdcall.} =
|
||||
var c = cast[ptr TThreadProcClosure](closure)
|
||||
c.fn(c.data)
|
||||
# implicitely return 0
|
||||
|
||||
else:
|
||||
type
|
||||
TSysLock {.importc: "pthread_mutex_t", header: "<sys/types.h>".} = int
|
||||
TSysThread {.importc: "pthread_t", header: "<sys/types.h>".} = int
|
||||
|
||||
TLock* = TSysLock
|
||||
|
||||
proc InitLockAux(L: var TSysLock, attr: pointer = nil) {.
|
||||
importc: "pthread_mutex_init", header: "<pthread.h>".}
|
||||
|
||||
proc InitLock*(L: var TLock) {.inline.} =
|
||||
InitLockAux(L)
|
||||
proc Aquire*(L: var TLock) {.
|
||||
importc: "pthread_mutex_lock", header: "<pthread.h>".}
|
||||
proc Release*(L: var TLock) {.
|
||||
importc: "pthread_mutex_unlock", header: "<pthread.h>".}
|
||||
|
||||
proc pthread_create(a1: var TSysThread, a2: ptr int,
|
||||
a3: proc (x: pointer) {.noconv.},
|
||||
a4: pointer): cint {.importc: "pthread_create",
|
||||
header: "<pthread.h>".}
|
||||
proc pthread_join(a1: TSysThread, a2: ptr pointer): cint {.
|
||||
importc, header: "<pthread.h>".}
|
||||
|
||||
proc pthread_cancel(a1: TSysThread): cint {.
|
||||
importc: "pthread_cancel", header: "<pthread.h>".}
|
||||
|
||||
proc threadProcWrapper(closure: pointer) {.noconv.} =
|
||||
var c = cast[ptr TThreadProcClosure](closure)
|
||||
c.fn(c.data)
|
||||
|
||||
{.passL: "-pthread".}
|
||||
{.passC: "-pthread".}
|
||||
|
||||
type
|
||||
TThread* = object of TObject ## Nimrod thread.
|
||||
sys: TSysThread
|
||||
c: TThreadProcClosure
|
||||
|
||||
|
||||
proc createThread*(t: var TThread, tp: TThreadProc,
|
||||
closure: pointer = nil) =
|
||||
## creates a new thread `t` and starts its execution. Entry point is the
|
||||
## proc `tp`. `closure` is passed to `tp`.
|
||||
t.c.data = closure
|
||||
t.c.fn = tp
|
||||
when defined(windows):
|
||||
var dummyThreadId: int32
|
||||
t.sys = CreateThread(nil, 0'i32, threadProcWrapper, addr(t.c), 0'i32,
|
||||
dummyThreadId)
|
||||
else:
|
||||
discard pthread_create(t.sys, nil, threadProcWrapper, addr(t.c))
|
||||
|
||||
proc joinThread*(t: TThread) =
|
||||
## waits for the thread `t` until it has terminated.
|
||||
when defined(windows):
|
||||
discard WaitForSingleObject(t.sys, -1'i32)
|
||||
else:
|
||||
discard pthread_join(t.sys, nil)
|
||||
|
||||
proc destroyThread*(t: var TThread) =
|
||||
## forces the thread `t` to terminate. This is potentially dangerous if
|
||||
## you don't have full control over `t` and its aquired ressources.
|
||||
when defined(windows):
|
||||
discard TerminateThread(t.sys, 1'i32)
|
||||
else:
|
||||
discard pthread_cancel(t.sys)
|
||||
|
||||
@@ -71,7 +71,11 @@ __TINYC__
|
||||
# define NIM_CONST const
|
||||
#endif
|
||||
|
||||
#define NIM_THREADVAR __thread
|
||||
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
||||
# define NIM_THREADVAR __declspec(thread)
|
||||
#else
|
||||
# define NIM_THREADVAR __thread
|
||||
#endif
|
||||
|
||||
/* --------------- how int64 constants should be declared: ----------- */
|
||||
#if defined(__GNUC__) || defined(__LCC__) || \
|
||||
@@ -415,8 +419,9 @@ struct TFrame {
|
||||
NI len;
|
||||
};
|
||||
|
||||
/*
|
||||
extern TFrame* framePtr;
|
||||
/*extern TSafePoint* excHandler; */
|
||||
extern TSafePoint* excHandler; */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
struct NimException {
|
||||
|
||||
@@ -1259,6 +1259,18 @@ var
|
||||
## each executed instruction. This should only be used by debuggers!
|
||||
## Only code compiled with the ``debugger:on`` switch calls this hook.
|
||||
|
||||
type
|
||||
PFrame = ptr TFrame
|
||||
TFrame {.importc, nodecl, final.} = object
|
||||
prev: PFrame
|
||||
procname: CString
|
||||
line: int # current line number
|
||||
filename: CString
|
||||
len: int # length of slots (when not debugging always zero)
|
||||
|
||||
var
|
||||
framePtr {.threadvar, compilerproc.}: PFrame
|
||||
|
||||
when not defined(ECMAScript):
|
||||
{.push overflow_checks:off}
|
||||
proc add* (x: var string, y: cstring) =
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# Nimrod's Runtime Library
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
# (c) Copyright 2011 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -40,10 +40,10 @@ type
|
||||
context: C_JmpBuf
|
||||
|
||||
var
|
||||
excHandler {.compilerproc.}: PSafePoint = nil
|
||||
excHandler {.threadvar, compilerproc.}: PSafePoint = nil
|
||||
# list of exception handlers
|
||||
# a global variable for the root of all try blocks
|
||||
currException: ref E_Base
|
||||
currException {.threadvar.}: ref E_Base
|
||||
|
||||
proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} =
|
||||
s.prev = excHandler
|
||||
@@ -107,23 +107,11 @@ when nativeStacktrace:
|
||||
# interested in
|
||||
enabled = true
|
||||
|
||||
type
|
||||
PFrame = ptr TFrame
|
||||
TFrame {.importc, nodecl, final.} = object
|
||||
prev: PFrame
|
||||
procname: CString
|
||||
line: int # current line number
|
||||
filename: CString
|
||||
len: int # length of slots (when not debugging always zero)
|
||||
|
||||
var
|
||||
buf: string # cannot be allocated on the stack!
|
||||
assertBuf: string # we need a different buffer for
|
||||
# assert, as it raises an exception and
|
||||
# exception handler needs the buffer too
|
||||
|
||||
framePtr {.exportc.}: PFrame
|
||||
|
||||
tempFrames: array [0..127, PFrame] # cannot be allocated on the stack!
|
||||
|
||||
proc auxWriteStackTrace(f: PFrame, s: var string) =
|
||||
|
||||
@@ -61,8 +61,9 @@ type
|
||||
decStack: TCellSeq # cells in the stack that are to decref again
|
||||
cycleRoots: TCellSet
|
||||
tempStack: TCellSeq # temporary stack for recursion elimination
|
||||
cycleRootsLock: TSysLock
|
||||
zctLock: TSysLock
|
||||
when hasThreadSupport:
|
||||
cycleRootsLock: TSysLock
|
||||
zctLock: TSysLock
|
||||
stat: TGcStat
|
||||
|
||||
var
|
||||
@@ -281,8 +282,9 @@ proc initGC() =
|
||||
init(gch.tempStack)
|
||||
Init(gch.cycleRoots)
|
||||
Init(gch.decStack)
|
||||
InitLock(gch.cycleRootsLock)
|
||||
InitLock(gch.zctLock)
|
||||
when hasThreadSupport:
|
||||
InitLock(gch.cycleRootsLock)
|
||||
InitLock(gch.zctLock)
|
||||
new(gOutOfMem) # reserve space for the EOutOfMemory exception here!
|
||||
|
||||
proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
|
||||
|
||||
@@ -44,83 +44,4 @@ proc atomicDec(memLoc: var int, x: int): int =
|
||||
else:
|
||||
dec(memLoc, x)
|
||||
result = memLoc
|
||||
|
||||
when defined(Windows):
|
||||
type
|
||||
THandle = int
|
||||
TSysThread = THandle
|
||||
TSysLock {.final, pure.} = object # CRITICAL_SECTION in WinApi
|
||||
DebugInfo: pointer
|
||||
LockCount: int32
|
||||
RecursionCount: int32
|
||||
OwningThread: int
|
||||
LockSemaphore: int
|
||||
Reserved: int32
|
||||
|
||||
proc InitLock(L: var TSysLock) {.stdcall,
|
||||
dynlib: "kernel32", importc: "InitializeCriticalSection".}
|
||||
proc Aquire(L: var TSysLock) {.stdcall,
|
||||
dynlib: "kernel32", importc: "EnterCriticalSection".}
|
||||
proc Release(L: var TSysLock) {.stdcall,
|
||||
dynlib: "kernel32", importc: "LeaveCriticalSection".}
|
||||
|
||||
proc CreateThread(lpThreadAttributes: Pointer, dwStackSize: int32,
|
||||
lpStartAddress: pointer, lpParameter: Pointer,
|
||||
dwCreationFlags: int32, lpThreadId: var int32): THandle {.
|
||||
stdcall, dynlib: "kernel32", importc: "CreateThread".}
|
||||
|
||||
proc winSuspendThread(hThread: TSysThread): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "SuspendThread".}
|
||||
|
||||
proc winResumeThread(hThread: TSysThread): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "ResumeThread".}
|
||||
|
||||
proc WaitForMultipleObjects(nCount: int32,
|
||||
lpHandles: ptr array[0..10, THandle],
|
||||
bWaitAll: int32,
|
||||
dwMilliseconds: int32): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".}
|
||||
|
||||
proc WaitForSingleObject(hHandle: THANDLE, dwMilliseconds: int32): int32 {.
|
||||
stdcall, dynlib: "kernel32", importc: "WaitForSingleObject".}
|
||||
|
||||
else:
|
||||
type
|
||||
TSysLock {.importc: "pthread_mutex_t", header: "<sys/types.h>".} = int
|
||||
TSysThread {.importc: "pthread_t", header: "<sys/types.h>".} = int
|
||||
|
||||
proc InitLock(L: var TSysLock, attr: pointer = nil) {.
|
||||
importc: "pthread_mutex_init", header: "<pthread.h>".}
|
||||
proc Aquire(L: var TSysLock) {.
|
||||
importc: "pthread_mutex_lock", header: "<pthread.h>".}
|
||||
proc Release(L: var TSysLock) {.
|
||||
importc: "pthread_mutex_unlock", header: "<pthread.h>".}
|
||||
|
||||
proc pthread_create(a1: ptr TSysThread, a2: ptr int,
|
||||
a3: proc (x: pointer): pointer {.noconv.},
|
||||
a4: pointer): cint {.importc: "pthread_create",
|
||||
header: "<pthread.h>".}
|
||||
proc pthread_join(a1: TSysThread, a2: ptr pointer): cint {.
|
||||
importc, header: "<pthread.h>".}
|
||||
|
||||
|
||||
type
|
||||
TThread* = TSysThread
|
||||
TLock* = TSysLock
|
||||
TThreadFunc* = proc (closure: pointer) {.cdecl.}
|
||||
|
||||
proc createThread*(t: var TThread, fn: TThreadFunc, closure: pointer) =
|
||||
when defined(windows):
|
||||
nil
|
||||
else:
|
||||
nil
|
||||
#pthread_create(
|
||||
|
||||
proc joinThread*(t: TThread) =
|
||||
nil
|
||||
|
||||
#proc pthread_exit(void *value_ptr)
|
||||
|
||||
proc destroyThread*(t: var TThread) =
|
||||
nil
|
||||
|
||||
|
||||
@@ -477,7 +477,7 @@ proc genTryStmtCpp(p: BProc, t: PNode) =
|
||||
rethrowFlag = getTempName()
|
||||
appf(p.s[cpsLocals], "volatile NIM_BOOL $1 = NIM_FALSE;$n", [rethrowFlag])
|
||||
if optStackTrace in p.Options:
|
||||
app(p.s[cpsStmts], "framePtr = (TFrame*)&F;" & tnl)
|
||||
appcg(p, cpsStmts, "#framePtr = (TFrame*)&F;" & tnl)
|
||||
app(p.s[cpsStmts], "try {" & tnl)
|
||||
add(p.nestedTryStmts, t)
|
||||
genStmts(p, t.sons[0])
|
||||
@@ -542,7 +542,7 @@ proc genTryStmt(p: BProc, t: PNode) =
|
||||
appcg(p, cpsStmts, "#pushSafePoint(&$1);$n" &
|
||||
"$1.status = setjmp($1.context);$n", [safePoint])
|
||||
if optStackTrace in p.Options:
|
||||
app(p.s[cpsStmts], "framePtr = (TFrame*)&F;" & tnl)
|
||||
appcg(p, cpsStmts, "#framePtr = (TFrame*)&F;" & tnl)
|
||||
appf(p.s[cpsStmts], "if ($1.status == 0) {$n", [safePoint])
|
||||
var length = sonsLen(t)
|
||||
add(p.nestedTryStmts, t)
|
||||
|
||||
23
rod/cgen.nim
23
rod/cgen.nim
@@ -386,10 +386,10 @@ proc assignGlobalVar(p: BProc, s: PSym) =
|
||||
useHeader(p.module, s)
|
||||
if lfNoDecl in s.loc.flags: return
|
||||
if sfImportc in s.flags: app(p.module.s[cfsVars], "extern ")
|
||||
if sfThreadVar in s.flags: app(p.module.s[cfsVars], "NIM_THREADVAR ")
|
||||
app(p.module.s[cfsVars], getTypeDesc(p.module, s.loc.t))
|
||||
if sfRegister in s.flags: app(p.module.s[cfsVars], " register")
|
||||
if sfVolatile in s.flags: app(p.module.s[cfsVars], " volatile")
|
||||
if sfThreadVar in s.flags: app(p.module.s[cfsVars], " NIM_THREADVAR")
|
||||
appf(p.module.s[cfsVars], " $1;$n", [s.loc.r])
|
||||
if {optStackTrace, optEndb} * p.module.module.options ==
|
||||
{optStackTrace, optEndb}:
|
||||
@@ -550,19 +550,12 @@ proc retIsNotVoid(s: PSym): bool =
|
||||
result = (s.typ.sons[0] != nil) and not isInvalidReturnType(s.typ.sons[0])
|
||||
|
||||
proc initFrame(p: BProc, procname, filename: PRope): PRope =
|
||||
inc(p.labels, 5)
|
||||
result = ropeff("F.procname = $1;$n" & "F.prev = framePtr;$n" &
|
||||
"F.filename = $2;$n" & "F.line = 0;$n" & "framePtr = (TFrame*)&F;$n",
|
||||
"%LOC$3 = getelementptr %TF %F, %NI 1$n" &
|
||||
"%LOC$4 = getelementptr %TF %F, %NI 0$n" &
|
||||
"%LOC$5 = getelementptr %TF %F, %NI 3$n" &
|
||||
"%LOC$6 = getelementptr %TF %F, %NI 2$n" & "store i8* $1, i8** %LOC$3$n" &
|
||||
"store %TFrame* @framePtr, %TFrame** %LOC$4$n" &
|
||||
"store i8* $2, i8** %LOC$5$n" & "store %NI 0, %NI* %LOC$6$n" &
|
||||
"%LOC$7 = bitcast %TF* %F to %TFrame*$n" &
|
||||
"store %TFrame* %LOC$7, %TFrame** @framePtr$n", [procname, filename,
|
||||
toRope(p.labels), toRope(p.labels - 1), toRope(p.labels - 2),
|
||||
toRope(p.labels - 3), toRope(p.labels - 4)])
|
||||
result = ropecg(p.module,
|
||||
"F.procname = $1;$n" &
|
||||
"F.prev = #framePtr;$n" &
|
||||
"F.filename = $2;$n" &
|
||||
"F.line = 0;$n" &
|
||||
"framePtr = (TFrame*)&F;$n", [procname, filename])
|
||||
|
||||
proc deinitFrame(p: BProc): PRope =
|
||||
inc(p.labels, 3)
|
||||
@@ -693,10 +686,10 @@ proc genVarPrototype(m: BModule, sym: PSym) =
|
||||
[sym.loc.r, getTypeDesc(m, sym.loc.t)])
|
||||
else:
|
||||
app(m.s[cfsVars], "extern ")
|
||||
if sfThreadVar in sym.flags: app(m.s[cfsVars], "NIM_THREADVAR ")
|
||||
app(m.s[cfsVars], getTypeDesc(m, sym.loc.t))
|
||||
if sfRegister in sym.flags: app(m.s[cfsVars], " register")
|
||||
if sfVolatile in sym.flags: app(m.s[cfsVars], " volatile")
|
||||
if sfThreadVar in sym.flags: app(m.s[cfsVars], " NIM_THREADVAR")
|
||||
appf(m.s[cfsVars], " $1;$n", [sym.loc.r])
|
||||
|
||||
proc genConstPrototype(m: BModule, sym: PSym) =
|
||||
|
||||
21
tests/gc/tthreads.nim
Normal file
21
tests/gc/tthreads.nim
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
import threads
|
||||
|
||||
var
|
||||
thr: array [0..4, TThread]
|
||||
L: TLock
|
||||
|
||||
proc threadFunc(c: pointer) {.procvar.} =
|
||||
for i in 0..9:
|
||||
Aquire(L)
|
||||
echo i
|
||||
Release(L)
|
||||
|
||||
InitLock(L)
|
||||
|
||||
for i in 0..high(thr):
|
||||
createThread(thr[i], threadFunc)
|
||||
for i in 0..high(thr):
|
||||
joinThread(thr[i])
|
||||
|
||||
|
||||
6
todo.txt
6
todo.txt
@@ -1,10 +1,14 @@
|
||||
- thread support: threadvar on Windows seems broken;
|
||||
add --deadlock_prevention:on|off switch
|
||||
|
||||
- we need a way to disable tests
|
||||
- deprecate ^ and make it available as operator
|
||||
- test branch coverage
|
||||
- checked exceptions
|
||||
- built-in serialization
|
||||
- do not ambiguity error for methods if amibiguity only affects the same
|
||||
- do not ambiguity error for methods if ambiguity only affects the same
|
||||
dispatcher anyway
|
||||
- slicing
|
||||
|
||||
|
||||
High priority (version 0.9.0)
|
||||
|
||||
@@ -49,6 +49,7 @@ Additions
|
||||
``array[TMyEnum, string]`` mapping.
|
||||
- Indices in array literals may be explicitly given, enhancing readability:
|
||||
``[enumValueA: "a", enumValueB: "b"]``.
|
||||
- Added basic thread support via the ``threads`` core module.
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user