case consistency improvements

This commit is contained in:
Araq 2014-01-11 21:56:05 +01:00
commit 346443d1b5
18 changed files with 139 additions and 137 deletions

View file

@ -216,7 +216,7 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr: of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
result = isAssignable(owner, n.sons[0]) result = isAssignable(owner, n.sons[0])
else: else:
nil discard
proc matchNodeKinds*(p, n: PNode): bool = proc matchNodeKinds*(p, n: PNode): bool =
# matches the parameter constraint 'p' against the concrete AST 'n'. # matches the parameter constraint 'p' against the concrete AST 'n'.

View file

@ -178,9 +178,9 @@ proc cleanAux(dir: string) =
of "nimcache": of "nimcache":
echo "removing dir: ", path echo "removing dir: ", path
removeDir(path) removeDir(path)
of "dist", ".git", "icons": nil of "dist", ".git", "icons": discard
else: cleanAux(path) else: cleanAux(path)
else: nil else: discard
proc removePattern(pattern: string) = proc removePattern(pattern: string) =
for f in walkFiles(pattern): for f in walkFiles(pattern):

View file

@ -45,28 +45,28 @@ when noDeadlocks:
locksLen {.threadvar.}: int locksLen {.threadvar.}: int
locks {.threadvar.}: array [0..MaxLocksPerThread-1, pointer] locks {.threadvar.}: array [0..MaxLocksPerThread-1, pointer]
proc OrderedLocks(): bool = proc orderedLocks(): bool =
for i in 0 .. locksLen-2: for i in 0 .. locksLen-2:
if locks[i] >= locks[i+1]: return false if locks[i] >= locks[i+1]: return false
result = true result = true
proc InitLock*(lock: var TLock) {.inline.} = proc initLock*(lock: var TLock) {.inline.} =
## Initializes the given lock. ## Initializes the given lock.
InitSysLock(lock) initSysLock(lock)
proc DeinitLock*(lock: var TLock) {.inline.} = proc deinitLock*(lock: var TLock) {.inline.} =
## Frees the resources associated with the lock. ## Frees the resources associated with the lock.
DeinitSys(lock) deinitSys(lock)
proc TryAcquire*(lock: var TLock): bool {.tags: [FAquireLock].} = proc tryAcquire*(lock: var TLock): bool {.tags: [FAquireLock].} =
## Tries to acquire the given lock. Returns `true` on success. ## Tries to acquire the given lock. Returns `true` on success.
result = TryAcquireSys(lock) result = tryAcquireSys(lock)
when noDeadlocks: when noDeadlocks:
if not result: return if not result: return
# we have to add it to the ordered list. Oh, and we might fail if # we have to add it to the ordered list. Oh, and we might fail if
# there is no space in the array left ... # there is no space in the array left ...
if locksLen >= len(locks): if locksLen >= len(locks):
ReleaseSys(lock) releaseSys(lock)
raise newException(EResourceExhausted, "cannot acquire additional lock") raise newException(EResourceExhausted, "cannot acquire additional lock")
# find the position to add: # find the position to add:
var p = addr(lock) var p = addr(lock)
@ -83,14 +83,14 @@ proc TryAcquire*(lock: var TLock): bool {.tags: [FAquireLock].} =
dec L dec L
locks[i] = p locks[i] = p
inc(locksLen) inc(locksLen)
assert OrderedLocks() assert orderedLocks()
return return
# simply add to the end: # simply add to the end:
locks[locksLen] = p locks[locksLen] = p
inc(locksLen) inc(locksLen)
assert OrderedLocks() assert orderedLocks()
proc Acquire*(lock: var TLock) {.tags: [FAquireLock].} = proc acquire*(lock: var TLock) {.tags: [FAquireLock].} =
## Acquires the given lock. ## Acquires the given lock.
when nodeadlocks: when nodeadlocks:
var p = addr(lock) var p = addr(lock)
@ -106,36 +106,36 @@ proc Acquire*(lock: var TLock) {.tags: [FAquireLock].} =
raise newException(EResourceExhausted, raise newException(EResourceExhausted,
"cannot acquire additional lock") "cannot acquire additional lock")
while L >= i: while L >= i:
ReleaseSys(cast[ptr TSysLock](locks[L])[]) releaseSys(cast[ptr TSysLock](locks[L])[])
locks[L+1] = locks[L] locks[L+1] = locks[L]
dec L dec L
# acquire the current lock: # acquire the current lock:
AcquireSys(lock) acquireSys(lock)
locks[i] = p locks[i] = p
inc(locksLen) inc(locksLen)
# acquire old locks in proper order again: # acquire old locks in proper order again:
L = locksLen-1 L = locksLen-1
inc i inc i
while i <= L: while i <= L:
AcquireSys(cast[ptr TSysLock](locks[i])[]) acquireSys(cast[ptr TSysLock](locks[i])[])
inc(i) inc(i)
# DANGER: We can only modify this global var if we gained every lock! # DANGER: We can only modify this global var if we gained every lock!
# NO! We need an atomic increment. Crap. # NO! We need an atomic increment. Crap.
discard system.atomicInc(deadlocksPrevented, 1) discard system.atomicInc(deadlocksPrevented, 1)
assert OrderedLocks() assert orderedLocks()
return return
# simply add to the end: # simply add to the end:
if locksLen >= len(locks): if locksLen >= len(locks):
raise newException(EResourceExhausted, "cannot acquire additional lock") raise newException(EResourceExhausted, "cannot acquire additional lock")
AcquireSys(lock) acquireSys(lock)
locks[locksLen] = p locks[locksLen] = p
inc(locksLen) inc(locksLen)
assert OrderedLocks() assert orderedLocks()
else: else:
AcquireSys(lock) acquireSys(lock)
proc Release*(lock: var TLock) {.tags: [FReleaseLock].} = proc release*(lock: var TLock) {.tags: [FReleaseLock].} =
## Releases the given lock. ## Releases the given lock.
when nodeadlocks: when nodeadlocks:
var p = addr(lock) var p = addr(lock)
@ -145,20 +145,20 @@ proc Release*(lock: var TLock) {.tags: [FReleaseLock].} =
for j in i..L-2: locks[j] = locks[j+1] for j in i..L-2: locks[j] = locks[j+1]
dec locksLen dec locksLen
break break
ReleaseSys(lock) releaseSys(lock)
proc InitCond*(cond: var TCond) {.inline.} = proc initCond*(cond: var TCond) {.inline.} =
## Initializes the given condition variable. ## Initializes the given condition variable.
InitSysCond(cond) initSysCond(cond)
proc DeinitCond*(cond: var TCond) {.inline.} = proc deinitCond*(cond: var TCond) {.inline.} =
## Frees the resources associated with the lock. ## Frees the resources associated with the lock.
DeinitSysCond(cond) deinitSysCond(cond)
proc wait*(cond: var TCond, lock: var TLock) {.inline.} = proc wait*(cond: var TCond, lock: var TLock) {.inline.} =
## waits on the condition variable `cond`. ## waits on the condition variable `cond`.
WaitSysCond(cond, lock) waitSysCond(cond, lock)
proc signal*(cond: var TCond) {.inline.} = proc signal*(cond: var TCond) {.inline.} =
## sends a signal to the condition variable `cond`. ## sends a signal to the condition variable `cond`.

View file

@ -47,12 +47,12 @@ proc dbError*(db: TDbConn, msg: string) {.noreturn.} =
e.msg = $db.err & " " & msg e.msg = $db.err & " " & msg
raise e raise e
proc Close*(db: var TDbConn) {.tags: [FDB].} = proc close*(db: var TDbConn) {.tags: [FDB].} =
## closes the database connection. ## closes the database connection.
disconnect(db) disconnect(db)
destroy(db) destroy(db)
proc Open*(host: string = defaultHost, port: int = defaultPort): TDbConn {. proc open*(host: string = defaultHost, port: int = defaultPort): TDbConn {.
tags: [FDB].} = tags: [FDB].} =
## opens a database connection. Raises `EDb` if the connection could not ## opens a database connection. Raises `EDb` if the connection could not
## be established. ## be established.
@ -113,7 +113,7 @@ proc getId*(obj: var TBSon): TOid =
else: else:
raise newException(EInvalidIndex, "_id not in object") raise newException(EInvalidIndex, "_id not in object")
proc insertID*(db: var TDbConn, namespace: string, data: PJsonNode): TOid {. proc insertId*(db: var TDbConn, namespace: string, data: PJsonNode): TOid {.
tags: [FWriteDb].} = tags: [FWriteDb].} =
## converts `data` to BSON format and inserts it in `namespace`. Returns ## converts `data` to BSON format and inserts it in `namespace`. Returns
## the generated OID for the ``_id`` field. ## the generated OID for the ``_id`` field.

View file

@ -65,7 +65,7 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
else: else:
add(result, c) add(result, c)
proc TryExec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): bool {. proc tryExec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): bool {.
tags: [FReadDB, FWriteDb].} = tags: [FReadDB, FWriteDb].} =
## tries to execute the query and returns true if successful, false otherwise. ## tries to execute the query and returns true if successful, false otherwise.
var q = dbFormat(query, args) var q = dbFormat(query, args)
@ -75,7 +75,7 @@ proc rawExec(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) =
var q = dbFormat(query, args) var q = dbFormat(query, args)
if mysql.RealQuery(db, q, q.len) != 0'i32: dbError(db) if mysql.RealQuery(db, q, q.len) != 0'i32: dbError(db)
proc Exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {. proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
tags: [FReadDB, FWriteDb].} = tags: [FReadDB, FWriteDb].} =
## executes the query and raises EDB if not successful. ## executes the query and raises EDB if not successful.
var q = dbFormat(query, args) var q = dbFormat(query, args)
@ -90,7 +90,7 @@ proc properFreeResult(sqlres: mysql.PRES, row: cstringArray) =
while mysql.FetchRow(sqlres) != nil: nil while mysql.FetchRow(sqlres) != nil: nil
mysql.FreeResult(sqlres) mysql.FreeResult(sqlres)
iterator FastRows*(db: TDbConn, query: TSqlQuery, iterator fastRows*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
## executes the query and iterates over the result dataset. This is very ## executes the query and iterates over the result dataset. This is very
## fast, but potenially dangerous: If the for-loop-body executes another ## fast, but potenially dangerous: If the for-loop-body executes another
@ -126,7 +126,7 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
add(result[i], row[i]) add(result[i], row[i])
properFreeResult(sqlres, row) properFreeResult(sqlres, row)
proc GetAllRows*(db: TDbConn, query: TSqlQuery, proc getAllRows*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} = args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
## executes the query and returns the whole result dataset. ## executes the query and returns the whole result dataset.
result = @[] result = @[]
@ -145,12 +145,12 @@ proc GetAllRows*(db: TDbConn, query: TSqlQuery,
inc(j) inc(j)
mysql.FreeResult(sqlres) mysql.FreeResult(sqlres)
iterator Rows*(db: TDbConn, query: TSqlQuery, iterator rows*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
## same as `FastRows`, but slower and safe. ## same as `FastRows`, but slower and safe.
for r in items(GetAllRows(db, query, args)): yield r for r in items(GetAllRows(db, query, args)): yield r
proc GetValue*(db: TDbConn, query: TSqlQuery, proc getValue*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): string {.tags: [FReadDB].} = args: varargs[string, `$`]): string {.tags: [FReadDB].} =
## executes the query and returns the first column of the first row of the ## executes the query and returns the first column of the first row of the
## result dataset. Returns "" if the dataset contains no rows or the database ## result dataset. Returns "" if the dataset contains no rows or the database
@ -160,7 +160,7 @@ proc GetValue*(db: TDbConn, query: TSqlQuery,
result = row[0] result = row[0]
break break
proc TryInsertID*(db: TDbConn, query: TSqlQuery, proc tryInsertId*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
## executes the query (typically "INSERT") and returns the ## executes the query (typically "INSERT") and returns the
## generated ID for the row or -1 in case of an error. ## generated ID for the row or -1 in case of an error.
@ -170,14 +170,14 @@ proc TryInsertID*(db: TDbConn, query: TSqlQuery,
else: else:
result = mysql.InsertId(db) result = mysql.InsertId(db)
proc InsertID*(db: TDbConn, query: TSqlQuery, proc insertId*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
## executes the query (typically "INSERT") and returns the ## executes the query (typically "INSERT") and returns the
## generated ID for the row. ## generated ID for the row.
result = TryInsertID(db, query, args) result = TryInsertID(db, query, args)
if result < 0: dbError(db) if result < 0: dbError(db)
proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery, proc execAffectedRows*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): int64 {. args: varargs[string, `$`]): int64 {.
tags: [FReadDB, FWriteDb].} = tags: [FReadDB, FWriteDb].} =
## runs the query (typically "UPDATE") and returns the ## runs the query (typically "UPDATE") and returns the
@ -185,11 +185,11 @@ proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery,
rawExec(db, query, args) rawExec(db, query, args)
result = mysql.AffectedRows(db) result = mysql.AffectedRows(db)
proc Close*(db: TDbConn) {.tags: [FDb].} = proc close*(db: TDbConn) {.tags: [FDb].} =
## closes the database connection. ## closes the database connection.
if db != nil: mysql.Close(db) if db != nil: mysql.close(db)
proc Open*(connection, user, password, database: string): TDbConn {. proc open*(connection, user, password, database: string): TDbConn {.
tags: [FDb].} = tags: [FDb].} =
## opens a database connection. Raises `EDb` if the connection could not ## opens a database connection. Raises `EDb` if the connection could not
## be established. ## be established.

View file

@ -64,7 +64,7 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
else: else:
add(result, c) add(result, c)
proc TryExec*(db: TDbConn, query: TSqlQuery, proc tryExec*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} = args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} =
## tries to execute the query and returns true if successful, false otherwise. ## tries to execute the query and returns true if successful, false otherwise.
var q = dbFormat(query, args) var q = dbFormat(query, args)
@ -72,7 +72,7 @@ proc TryExec*(db: TDbConn, query: TSqlQuery,
result = PQresultStatus(res) == PGRES_COMMAND_OK result = PQresultStatus(res) == PGRES_COMMAND_OK
PQclear(res) PQclear(res)
proc Exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {. proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
tags: [FReadDB, FWriteDb].} = tags: [FReadDB, FWriteDb].} =
## executes the query and raises EDB if not successful. ## executes the query and raises EDB if not successful.
var q = dbFormat(query, args) var q = dbFormat(query, args)
@ -96,7 +96,7 @@ proc setRow(res: PPGresult, r: var TRow, line, cols: int32) =
var x = PQgetvalue(res, line, col) var x = PQgetvalue(res, line, col)
add(r[col], x) add(r[col], x)
iterator FastRows*(db: TDbConn, query: TSqlQuery, iterator fastRows*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
## executes the query and iterates over the result dataset. This is very ## executes the query and iterates over the result dataset. This is very
## fast, but potenially dangerous: If the for-loop-body executes another ## fast, but potenially dangerous: If the for-loop-body executes another
@ -119,19 +119,19 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
setRow(res, result, 0, L) setRow(res, result, 0, L)
PQclear(res) PQclear(res)
proc GetAllRows*(db: TDbConn, query: TSqlQuery, proc getAllRows*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} = args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
## executes the query and returns the whole result dataset. ## executes the query and returns the whole result dataset.
result = @[] result = @[]
for r in FastRows(db, query, args): for r in FastRows(db, query, args):
result.add(r) result.add(r)
iterator Rows*(db: TDbConn, query: TSqlQuery, iterator rows*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
## same as `FastRows`, but slower and safe. ## same as `FastRows`, but slower and safe.
for r in items(GetAllRows(db, query, args)): yield r for r in items(GetAllRows(db, query, args)): yield r
proc GetValue*(db: TDbConn, query: TSqlQuery, proc getValue*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): string {.tags: [FReadDB].} = args: varargs[string, `$`]): string {.tags: [FReadDB].} =
## executes the query and returns the first column of the first row of the ## executes the query and returns the first column of the first row of the
## result dataset. Returns "" if the dataset contains no rows or the database ## result dataset. Returns "" if the dataset contains no rows or the database
@ -139,7 +139,7 @@ proc GetValue*(db: TDbConn, query: TSqlQuery,
var x = PQgetvalue(setupQuery(db, query, args), 0, 0) var x = PQgetvalue(setupQuery(db, query, args), 0, 0)
result = if isNil(x): "" else: $x result = if isNil(x): "" else: $x
proc TryInsertID*(db: TDbConn, query: TSqlQuery, proc tryInsertID*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): int64 {.tags: [FWriteDb].}= args: varargs[string, `$`]): int64 {.tags: [FWriteDb].}=
## executes the query (typically "INSERT") and returns the ## executes the query (typically "INSERT") and returns the
## generated ID for the row or -1 in case of an error. For Postgre this adds ## generated ID for the row or -1 in case of an error. For Postgre this adds
@ -152,7 +152,7 @@ proc TryInsertID*(db: TDbConn, query: TSqlQuery,
else: else:
result = -1 result = -1
proc InsertID*(db: TDbConn, query: TSqlQuery, proc insertID*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
## executes the query (typically "INSERT") and returns the ## executes the query (typically "INSERT") and returns the
## generated ID for the row. For Postgre this adds ## generated ID for the row. For Postgre this adds
@ -161,7 +161,7 @@ proc InsertID*(db: TDbConn, query: TSqlQuery,
result = TryInsertID(db, query, args) result = TryInsertID(db, query, args)
if result < 0: dbError(db) if result < 0: dbError(db)
proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery, proc execAffectedRows*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): int64 {.tags: [ args: varargs[string, `$`]): int64 {.tags: [
FReadDB, FWriteDb].} = FReadDB, FWriteDb].} =
## executes the query (typically "UPDATE") and returns the ## executes the query (typically "UPDATE") and returns the
@ -172,11 +172,11 @@ proc ExecAffectedRows*(db: TDbConn, query: TSqlQuery,
result = parseBiggestInt($PQcmdTuples(res)) result = parseBiggestInt($PQcmdTuples(res))
PQclear(res) PQclear(res)
proc Close*(db: TDbConn) {.tags: [FDb].} = proc close*(db: TDbConn) {.tags: [FDb].} =
## closes the database connection. ## closes the database connection.
if db != nil: PQfinish(db) if db != nil: PQfinish(db)
proc Open*(connection, user, password, database: string): TDbConn {. proc open*(connection, user, password, database: string): TDbConn {.
tags: [FDb].} = tags: [FDb].} =
## opens a database connection. Raises `EDb` if the connection could not ## opens a database connection. Raises `EDb` if the connection could not
## be established. ## be established.

View file

@ -343,7 +343,7 @@ proc fillRect*(sur: PSurface, r: TRect, col: TColor) =
if sdl.FillRect(sur.s, addr(rect), sur.createSdlColor(col)) == -1: if sdl.FillRect(sur.s, addr(rect), sur.createSdlColor(col)) == -1:
raiseEGraphics() raiseEGraphics()
proc Plot4EllipsePoints(sur: PSurface, CX, CY, X, Y: Natural, col: TColor) = proc plot4EllipsePoints(sur: PSurface, CX, CY, X, Y: Natural, col: TColor) =
var video = cast[PPixels](sur.s.pixels) var video = cast[PPixels](sur.s.pixels)
var pitch = sur.s.pitch.int div ColSize var pitch = sur.s.pitch.int div ColSize
if CX+X <= sur.s.w-1: if CX+X <= sur.s.w-1:

View file

@ -151,7 +151,7 @@ const
# GetSystemMetrics # GetSystemMetrics
SM_SERVERR2 = 89 SM_SERVERR2 = 89
proc GlobalMemoryStatusEx*(lpBuffer: var TMEMORYSTATUSEX){.stdcall, dynlib: "kernel32", proc globalMemoryStatusEx*(lpBuffer: var TMEMORYSTATUSEX){.stdcall, dynlib: "kernel32",
importc: "GlobalMemoryStatusEx".} importc: "GlobalMemoryStatusEx".}
proc getMemoryInfo*(): TMemoryInfo = proc getMemoryInfo*(): TMemoryInfo =
@ -159,7 +159,7 @@ proc getMemoryInfo*(): TMemoryInfo =
var statex: TMEMORYSTATUSEX var statex: TMEMORYSTATUSEX
statex.dwLength = sizeof(statex).int32 statex.dwLength = sizeof(statex).int32
GlobalMemoryStatusEx(statex) globalMemoryStatusEx(statex)
result.MemoryLoad = statex.dwMemoryLoad result.MemoryLoad = statex.dwMemoryLoad
result.TotalPhysMem = statex.ullTotalPhys result.TotalPhysMem = statex.ullTotalPhys
result.AvailablePhysMem = statex.ullAvailPhys result.AvailablePhysMem = statex.ullAvailPhys
@ -168,20 +168,20 @@ proc getMemoryInfo*(): TMemoryInfo =
result.TotalVirtualMem = statex.ullTotalVirtual result.TotalVirtualMem = statex.ullTotalVirtual
result.AvailableVirtualMem = statex.ullAvailExtendedVirtual result.AvailableVirtualMem = statex.ullAvailExtendedVirtual
proc GetVersionEx*(lpVersionInformation: var TOSVERSIONINFOEX): WINBOOL{.stdcall, proc getVersionEx*(lpVersionInformation: var TOSVERSIONINFOEX): WINBOOL{.stdcall,
dynlib: "kernel32", importc: "GetVersionExA".} dynlib: "kernel32", importc: "GetVersionExA".}
proc GetProcAddress*(hModule: int, lpProcName: cstring): pointer{.stdcall, proc getProcAddress*(hModule: int, lpProcName: cstring): pointer{.stdcall,
dynlib: "kernel32", importc: "GetProcAddress".} dynlib: "kernel32", importc: "GetProcAddress".}
proc GetModuleHandleA*(lpModuleName: cstring): int{.stdcall, proc getModuleHandleA*(lpModuleName: cstring): int{.stdcall,
dynlib: "kernel32", importc.} dynlib: "kernel32", importc: "GetModuleHandleA".}
proc getVersionInfo*(): TVersionInfo = proc getVersionInfo*(): TVersionInfo =
## Retrieves operating system info ## Retrieves operating system info
var osvi: TOSVERSIONINFOEX var osvi: TOSVERSIONINFOEX
osvi.dwOSVersionInfoSize = sizeof(osvi).int32 osvi.dwOSVersionInfoSize = sizeof(osvi).int32
discard GetVersionEx(osvi) discard getVersionEx(osvi)
result.majorVersion = osvi.dwMajorVersion result.majorVersion = osvi.dwMajorVersion
result.minorVersion = osvi.dwMinorVersion result.minorVersion = osvi.dwMinorVersion
result.buildNumber = osvi.dwBuildNumber result.buildNumber = osvi.dwBuildNumber
@ -197,8 +197,8 @@ proc getProductInfo*(majorVersion, minorVersion, SPMajorVersion,
## Retrieves Windows' ProductInfo, this function only works in Vista and 7 ## Retrieves Windows' ProductInfo, this function only works in Vista and 7
var pGPI = cast[proc (dwOSMajorVersion, dwOSMinorVersion, var pGPI = cast[proc (dwOSMajorVersion, dwOSMinorVersion,
dwSpMajorVersion, dwSpMinorVersion: int32, outValue: Pint32)](GetProcAddress( dwSpMajorVersion, dwSpMinorVersion: int32, outValue: Pint32)](getProcAddress(
GetModuleHandleA("kernel32.dll"), "GetProductInfo")) getModuleHandleA("kernel32.dll"), "GetProductInfo"))
if pGPI != nil: if pGPI != nil:
var dwType: int32 var dwType: int32
@ -207,25 +207,25 @@ proc getProductInfo*(majorVersion, minorVersion, SPMajorVersion,
else: else:
return PRODUCT_UNDEFINED return PRODUCT_UNDEFINED
proc GetSystemInfo*(lpSystemInfo: LPSYSTEM_INFO){.stdcall, dynlib: "kernel32", proc getSystemInfo*(lpSystemInfo: LPSYSTEM_INFO){.stdcall, dynlib: "kernel32",
importc: "GetSystemInfo".} importc: "GetSystemInfo".}
proc getSystemInfo*(): TSYSTEM_INFO = proc getSystemInfo*(): TSYSTEM_INFO =
## Returns the SystemInfo ## Returns the SystemInfo
# Use GetNativeSystemInfo if it's available # Use GetNativeSystemInfo if it's available
var pGNSI = cast[proc (lpSystemInfo: LPSYSTEM_INFO)](GetProcAddress( var pGNSI = cast[proc (lpSystemInfo: LPSYSTEM_INFO)](getProcAddress(
GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo")) getModuleHandleA("kernel32.dll"), "GetNativeSystemInfo"))
var systemi: TSYSTEM_INFO var systemi: TSYSTEM_INFO
if pGNSI != nil: if pGNSI != nil:
pGNSI(addr(systemi)) pGNSI(addr(systemi))
else: else:
GetSystemInfo(addr(systemi)) getSystemInfo(addr(systemi))
return systemi return systemi
proc GetSystemMetrics*(nIndex: int32): int32{.stdcall, dynlib: "user32", proc getSystemMetrics*(nIndex: int32): int32{.stdcall, dynlib: "user32",
importc: "GetSystemMetrics".} importc: "GetSystemMetrics".}
proc `$`*(osvi: TVersionInfo): string = proc `$`*(osvi: TVersionInfo): string =
@ -283,11 +283,11 @@ proc `$`*(osvi: TVersionInfo): string =
of PRODUCT_WEB_SERVER: of PRODUCT_WEB_SERVER:
result.add("Web Server Edition") result.add("Web Server Edition")
else: else:
nil discard
# End of Windows 6.* # End of Windows 6.*
if osvi.majorVersion == 5 and osvi.minorVersion == 2: if osvi.majorVersion == 5 and osvi.minorVersion == 2:
if GetSystemMetrics(SM_SERVERR2) != 0: if getSystemMetrics(SM_SERVERR2) != 0:
result.add("Windows Server 2003 R2, ") result.add("Windows Server 2003 R2, ")
elif (osvi.SuiteMask and VER_SUITE_PERSONAL) != 0: # Not sure if this will work elif (osvi.SuiteMask and VER_SUITE_PERSONAL) != 0: # Not sure if this will work
result.add("Windows Storage Server 2003") result.add("Windows Storage Server 2003")
@ -365,21 +365,21 @@ proc `$`*(osvi: TVersionInfo): string =
result = "Unknown version of windows[Kernel version <= 4]" result = "Unknown version of windows[Kernel version <= 4]"
proc getFileSize*(file: string): biggestInt = proc getFileSize*(file: string): BiggestInt =
var fileData: TWIN32_FIND_DATA var fileData: TWIN32_FIND_DATA
when useWinUnicode: when useWinUnicode:
var aa = newWideCString(file) var aa = newWideCString(file)
var hFile = FindFirstFileW(aa, fileData) var hFile = findFirstFileW(aa, fileData)
else: else:
var hFile = FindFirstFileA(file, fileData) var hFile = findFirstFileA(file, fileData)
if hFile == INVALID_HANDLE_VALUE: if hFile == INVALID_HANDLE_VALUE:
raise newException(EIO, $GetLastError()) raise newException(EIO, $getLastError())
return fileData.nFileSizeLow return fileData.nFileSizeLow
proc GetDiskFreeSpaceEx*(lpDirectoryName: cstring, lpFreeBytesAvailableToCaller, proc getDiskFreeSpaceEx*(lpDirectoryName: cstring, lpFreeBytesAvailableToCaller,
lpTotalNumberOfBytes, lpTotalNumberOfBytes,
lpTotalNumberOfFreeBytes: var TFiletime): WINBOOL{. lpTotalNumberOfFreeBytes: var TFiletime): WINBOOL{.
stdcall, dynlib: "kernel32", importc: "GetDiskFreeSpaceExA".} stdcall, dynlib: "kernel32", importc: "GetDiskFreeSpaceExA".}
@ -387,7 +387,7 @@ proc GetDiskFreeSpaceEx*(lpDirectoryName: cstring, lpFreeBytesAvailableToCaller,
proc getPartitionInfo*(partition: string): TPartitionInfo = proc getPartitionInfo*(partition: string): TPartitionInfo =
## Retrieves partition info, for example ``partition`` may be ``"C:\"`` ## Retrieves partition info, for example ``partition`` may be ``"C:\"``
var FreeBytes, TotalBytes, TotalFreeBytes: TFiletime var FreeBytes, TotalBytes, TotalFreeBytes: TFiletime
var res = GetDiskFreeSpaceEx(r"C:\", FreeBytes, TotalBytes, var res = getDiskFreeSpaceEx(r"C:\", FreeBytes, TotalBytes,
TotalFreeBytes) TotalFreeBytes)
return (FreeBytes, TotalBytes) return (FreeBytes, TotalBytes)

View file

@ -56,7 +56,7 @@ else:
# initialization: # initialization:
# disable auto-complete: # disable auto-complete:
proc doNothing(a, b: cint): cint {.cdecl, procvar.} = nil proc doNothing(a, b: cint): cint {.cdecl, procvar.} = discard
discard readline.bind_key('\t'.ord, doNothing) discard readline.bind_key('\t'.ord, doNothing)

View file

@ -23,7 +23,8 @@ elif sizeof(int) == 8: # 64bit
TRaw = range[0..4611686018427387903] TRaw = range[0..4611686018427387903]
## The range of uint values that can be stored directly in a value slot ## The range of uint values that can be stored directly in a value slot
## when on a 64 bit platform ## when on a 64 bit platform
else: echo("unsupported platform") else:
{.error: "unsupported platform".}
type type
TEntry = tuple TEntry = tuple

View file

@ -588,7 +588,7 @@ proc `<` *(x, y: int64): bool {.magic: "LtI64", noSideEffect.}
## Returns true iff `x` is less than `y`. ## Returns true iff `x` is less than `y`.
type type
IntMax32 = bool|int|int8|int16|int32 IntMax32 = int|int8|int16|int32
proc `+%` *(x, y: IntMax32): IntMax32 {.magic: "AddU", noSideEffect.} proc `+%` *(x, y: IntMax32): IntMax32 {.magic: "AddU", noSideEffect.}
proc `+%` *(x, y: int64): int64 {.magic: "AddU", noSideEffect.} proc `+%` *(x, y: int64): int64 {.magic: "AddU", noSideEffect.}

View file

@ -36,7 +36,7 @@ when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
## This proc implements an atomic load operation. It returns the contents at p. ## This proc implements an atomic load operation. It returns the contents at p.
## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_ACQUIRE, ATOMIC_CONSUME. ## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_ACQUIRE, ATOMIC_CONSUME.
proc atomicLoad*[T: TAtomType](p: ptr T, ret: ptr T, mem: AtomMemModel) {. proc atomicLoad*[T: TAtomType](p, ret: ptr T, mem: AtomMemModel) {.
importc: "__atomic_load", nodecl.} importc: "__atomic_load", nodecl.}
## This is the generic version of an atomic load. It returns the contents at p in ret. ## This is the generic version of an atomic load. It returns the contents at p in ret.
@ -45,7 +45,7 @@ when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
## This proc implements an atomic store operation. It writes val at p. ## This proc implements an atomic store operation. It writes val at p.
## ATOMIC_RELAXED, ATOMIC_SEQ_CST, and ATOMIC_RELEASE. ## ATOMIC_RELAXED, ATOMIC_SEQ_CST, and ATOMIC_RELEASE.
proc atomicStore*[T: TAtomType](p: ptr T, val: ptr T, mem: AtomMemModel) {. proc atomicStore*[T: TAtomType](p, val: ptr T, mem: AtomMemModel) {.
importc: "__atomic_store", nodecl.} importc: "__atomic_store", nodecl.}
## This is the generic version of an atomic store. It stores the value of val at p ## This is the generic version of an atomic store. It stores the value of val at p
@ -55,12 +55,12 @@ when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
## and returns the previous contents at p. ## and returns the previous contents at p.
## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_ACQUIRE, ATOMIC_RELEASE, ATOMIC_ACQ_REL ## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_ACQUIRE, ATOMIC_RELEASE, ATOMIC_ACQ_REL
proc atomicExchange*[T: TAtomType](p: ptr T, val: ptr T, ret: ptr T, mem: AtomMemModel) {. proc atomicExchange*[T: TAtomType](p, val, ret: ptr T, mem: AtomMemModel) {.
importc: "__atomic_exchange", nodecl.} importc: "__atomic_exchange", nodecl.}
## This is the generic version of an atomic exchange. It stores the contents at val at p. ## This is the generic version of an atomic exchange. It stores the contents at val at p.
## The original value at p is copied into ret. ## The original value at p is copied into ret.
proc atomicCompareExchangeN*[T: TAtomType](p: ptr T, expected: ptr T, desired: T, proc atomicCompareExchangeN*[T: TAtomType](p, expected: ptr T, desired: T,
weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {. weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {.
importc: "__atomic_compare_exchange_n ", nodecl.} importc: "__atomic_compare_exchange_n ", nodecl.}
## This proc implements an atomic compare and exchange operation. This compares the ## This proc implements an atomic compare and exchange operation. This compares the
@ -76,7 +76,7 @@ when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
## cannot be __ATOMIC_RELEASE nor __ATOMIC_ACQ_REL. It also cannot be a stronger model ## cannot be __ATOMIC_RELEASE nor __ATOMIC_ACQ_REL. It also cannot be a stronger model
## than that specified by success_memmodel. ## than that specified by success_memmodel.
proc atomicCompareExchange*[T: TAtomType](p: ptr T, expected: ptr T, desired: ptr T, proc atomicCompareExchange*[T: TAtomType](p, expected, desired: ptr T,
weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {. weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {.
importc: "__atomic_compare_exchange_n ", nodecl.} importc: "__atomic_compare_exchange_n ", nodecl.}
## This proc implements the generic version of atomic_compare_exchange. ## This proc implements the generic version of atomic_compare_exchange.
@ -108,7 +108,7 @@ when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
importc: "__atomic_fetch_and", nodecl.} importc: "__atomic_fetch_and", nodecl.}
proc atomicFetchXor*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {. proc atomicFetchXor*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
importc: "__atomic_fetch_xor", nodecl.} importc: "__atomic_fetch_xor", nodecl.}
proc atomicFetchAand*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {. proc atomicFetchNand*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
importc: "__atomic_fetch_nand", nodecl.} importc: "__atomic_fetch_nand", nodecl.}
proc atomicTestAndSet*(p: pointer, mem: AtomMemModel): bool {. proc atomicTestAndSet*(p: pointer, mem: AtomMemModel): bool {.
@ -176,7 +176,7 @@ else:
#elif not hasThreadSupport: #elif not hasThreadSupport:
# proc compareAndSwap*[T](mem: ptr T, # proc compareAndSwap*[T](mem: ptr T,
# expected: T, newValue: T): bool {.inline.} = # expected: T, newValue: T): bool {.inline.} =
# ## Returns true if successfully set value at mem to newValue when value # ## Returns true if successfully set value at mem to newValue when value
# ## at mem == expected # ## at mem == expected
# var oldval = mem[] # var oldval = mem[]
@ -202,4 +202,4 @@ proc atomicDec*(memLoc: var int, x: int = 1): int =
result = atomic_add_fetch(memLoc.addr, -x, ATOMIC_RELAXED) result = atomic_add_fetch(memLoc.addr, -x, ATOMIC_RELAXED)
else: else:
dec(memLoc, x) dec(memLoc, x)
result = memLoc result = memLoc

View file

@ -48,9 +48,9 @@ proc deinitRawChannel(p: pointer) =
deinitSys(c.lock) deinitSys(c.lock)
deinitSysCond(c.cond) deinitSysCond(c.cond)
proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel, proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel,
mode: TLoadStoreMode) mode: TLoadStoreMode)
proc storeAux(dest, src: Pointer, n: ptr TNimNode, t: PRawChannel, proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel,
mode: TLoadStoreMode) = mode: TLoadStoreMode) =
var var
d = cast[TAddress](dest) d = cast[TAddress](dest)
@ -67,7 +67,7 @@ proc storeAux(dest, src: Pointer, n: ptr TNimNode, t: PRawChannel,
if m != nil: storeAux(dest, src, m, t, mode) if m != nil: storeAux(dest, src, m, t, mode)
of nkNone: sysAssert(false, "storeAux") of nkNone: sysAssert(false, "storeAux")
proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel, proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel,
mode: TLoadStoreMode) = mode: TLoadStoreMode) =
var var
d = cast[TAddress](dest) d = cast[TAddress](dest)
@ -82,7 +82,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
x[] = nil x[] = nil
else: else:
var ss = cast[NimString](s2) var ss = cast[NimString](s2)
var ns = cast[NimString](Alloc(t.region, ss.len+1 + GenericSeqSize)) var ns = cast[NimString](alloc(t.region, ss.len+1 + GenericSeqSize))
copyMem(ns, ss, ss.len+1 + GenericSeqSize) copyMem(ns, ss, ss.len+1 + GenericSeqSize)
x[] = ns x[] = ns
else: else:
@ -92,7 +92,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
unsureAsgnRef(x, s2) unsureAsgnRef(x, s2)
else: else:
unsureAsgnRef(x, copyString(cast[NimString](s2))) unsureAsgnRef(x, copyString(cast[NimString](s2)))
Dealloc(t.region, s2) dealloc(t.region, s2)
of tySequence: of tySequence:
var s2 = cast[ppointer](src)[] var s2 = cast[ppointer](src)[]
var seq = cast[PGenericSeq](s2) var seq = cast[PGenericSeq](s2)
@ -105,7 +105,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
else: else:
sysAssert(dest != nil, "dest == nil") sysAssert(dest != nil, "dest == nil")
if mode == mStore: if mode == mStore:
x[] = Alloc(t.region, seq.len *% mt.base.size +% GenericSeqSize) x[] = alloc(t.region, seq.len *% mt.base.size +% GenericSeqSize)
else: else:
unsureAsgnRef(x, newObj(mt, seq.len * mt.base.size + GenericSeqSize)) unsureAsgnRef(x, newObj(mt, seq.len * mt.base.size + GenericSeqSize))
var dst = cast[taddress](cast[ppointer](dest)[]) var dst = cast[taddress](cast[ppointer](dest)[])
@ -118,7 +118,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
var dstseq = cast[PGenericSeq](dst) var dstseq = cast[PGenericSeq](dst)
dstseq.len = seq.len dstseq.len = seq.len
dstseq.reserved = seq.len dstseq.reserved = seq.len
if mode != mStore: Dealloc(t.region, s2) if mode != mStore: dealloc(t.region, s2)
of tyObject: of tyObject:
# copy type field: # copy type field:
var pint = cast[ptr PNimType](dest) var pint = cast[ptr PNimType](dest)
@ -143,7 +143,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
unsureAsgnRef(x, nil) unsureAsgnRef(x, nil)
else: else:
if mode == mStore: if mode == mStore:
x[] = Alloc(t.region, mt.base.size) x[] = alloc(t.region, mt.base.size)
else: else:
# XXX we should use the dynamic type here too, but that is not stored # XXX we should use the dynamic type here too, but that is not stored
# in the inbox at all --> use source[]'s object type? but how? we need # in the inbox at all --> use source[]'s object type? but how? we need
@ -151,7 +151,7 @@ proc storeAux(dest, src: Pointer, mt: PNimType, t: PRawChannel,
var obj = newObj(mt, mt.base.size) var obj = newObj(mt, mt.base.size)
unsureAsgnRef(x, obj) unsureAsgnRef(x, obj)
storeAux(x[], s, mt.base, t, mode) storeAux(x[], s, mt.base, t, mode)
if mode != mStore: Dealloc(t.region, s) if mode != mStore: dealloc(t.region, s)
else: else:
copyMem(dest, src, mt.size) # copy raw bits copyMem(dest, src, mt.size) # copy raw bits
@ -161,7 +161,7 @@ proc rawSend(q: PRawChannel, data: pointer, typ: PNimType) =
if q.count >= cap: if q.count >= cap:
# start with capacity for 2 entries in the queue: # start with capacity for 2 entries in the queue:
if cap == 0: cap = 1 if cap == 0: cap = 1
var n = cast[pbytes](Alloc0(q.region, cap*2*typ.size)) var n = cast[pbytes](alloc0(q.region, cap*2*typ.size))
var z = 0 var z = 0
var i = q.rd var i = q.rd
var c = q.count var c = q.count
@ -170,7 +170,7 @@ proc rawSend(q: PRawChannel, data: pointer, typ: PNimType) =
copyMem(addr(n[z*typ.size]), addr(q.data[i*typ.size]), typ.size) copyMem(addr(n[z*typ.size]), addr(q.data[i*typ.size]), typ.size)
i = (i + 1) and q.mask i = (i + 1) and q.mask
inc z inc z
if q.data != nil: Dealloc(q.region, q.data) if q.data != nil: dealloc(q.region, q.data)
q.data = n q.data = n
q.mask = cap*2 - 1 q.mask = cap*2 - 1
q.wr = q.count q.wr = q.count
@ -200,7 +200,7 @@ template sendImpl(q: expr) {.immediate.} =
rawSend(q, addr(m), typ) rawSend(q, addr(m), typ)
q.elemType = typ q.elemType = typ
releaseSys(q.lock) releaseSys(q.lock)
SignalSysCond(q.cond) signalSysCond(q.cond)
proc send*[TMsg](c: var TChannel[TMsg], msg: TMsg) = proc send*[TMsg](c: var TChannel[TMsg], msg: TMsg) =
## sends a message to a thread. `msg` is deeply copied. ## sends a message to a thread. `msg` is deeply copied.
@ -212,7 +212,7 @@ proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) =
acquireSys(q.lock) acquireSys(q.lock)
q.ready = true q.ready = true
while q.count <= 0: while q.count <= 0:
WaitSysCond(q.cond, q.lock) waitSysCond(q.cond, q.lock)
q.ready = false q.ready = false
if typ != q.elemType: if typ != q.elemType:
releaseSys(q.lock) releaseSys(q.lock)

View file

@ -66,6 +66,9 @@ when defined(Windows):
discard waitForSingleObject(cond, -1'i32) discard waitForSingleObject(cond, -1'i32)
acquireSys(lock) acquireSys(lock)
proc waitSysCondWindows(cond: var TSysCond) =
discard waitForSingleObject(cond, -1'i32)
else: else:
type type
TSysLock {.importc: "pthread_mutex_t", pure, final, TSysLock {.importc: "pthread_mutex_t", pure, final,

View file

@ -29,11 +29,11 @@
## ##
## proc threadFunc(interval: tuple[a,b: int]) {.thread.} = ## proc threadFunc(interval: tuple[a,b: int]) {.thread.} =
## for i in interval.a..interval.b: ## for i in interval.a..interval.b:
## Acquire(L) # lock stdout ## acquire(L) # lock stdout
## echo i ## echo i
## Release(L) ## release(L)
## ##
## InitLock(L) ## initLock(L)
## ##
## for i in 0..high(thr): ## for i in 0..high(thr):
## createThread(thr[i], threadFunc, (i*10, i*10+5)) ## createThread(thr[i], threadFunc, (i*10, i*10+5))
@ -54,9 +54,9 @@ when defined(windows):
TSysThread = THandle TSysThread = THandle
TWinThreadProc = proc (x: pointer): int32 {.stdcall.} TWinThreadProc = proc (x: pointer): int32 {.stdcall.}
proc CreateThread(lpThreadAttributes: Pointer, dwStackSize: int32, proc createThread(lpThreadAttributes: pointer, dwStackSize: int32,
lpStartAddress: TWinThreadProc, lpStartAddress: TWinThreadProc,
lpParameter: Pointer, lpParameter: pointer,
dwCreationFlags: int32, dwCreationFlags: int32,
lpThreadId: var int32): TSysThread {. lpThreadId: var int32): TSysThread {.
stdcall, dynlib: "kernel32", importc: "CreateThread".} stdcall, dynlib: "kernel32", importc: "CreateThread".}
@ -67,23 +67,23 @@ when defined(windows):
proc winResumeThread(hThread: TSysThread): int32 {. proc winResumeThread(hThread: TSysThread): int32 {.
stdcall, dynlib: "kernel32", importc: "ResumeThread".} stdcall, dynlib: "kernel32", importc: "ResumeThread".}
proc WaitForMultipleObjects(nCount: int32, proc waitForMultipleObjects(nCount: int32,
lpHandles: ptr TSysThread, lpHandles: ptr TSysThread,
bWaitAll: int32, bWaitAll: int32,
dwMilliseconds: int32): int32 {. dwMilliseconds: int32): int32 {.
stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".} stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".}
proc TerminateThread(hThread: TSysThread, dwExitCode: int32): int32 {. proc terminateThread(hThread: TSysThread, dwExitCode: int32): int32 {.
stdcall, dynlib: "kernel32", importc: "TerminateThread".} stdcall, dynlib: "kernel32", importc: "TerminateThread".}
type type
TThreadVarSlot = distinct int32 TThreadVarSlot = distinct int32
proc ThreadVarAlloc(): TThreadVarSlot {. proc threadVarAlloc(): TThreadVarSlot {.
importc: "TlsAlloc", stdcall, dynlib: "kernel32".} importc: "TlsAlloc", stdcall, dynlib: "kernel32".}
proc ThreadVarSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {. proc threadVarSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {.
importc: "TlsSetValue", stdcall, dynlib: "kernel32".} importc: "TlsSetValue", stdcall, dynlib: "kernel32".}
proc ThreadVarGetValue(dwTlsIndex: TThreadVarSlot): pointer {. proc threadVarGetValue(dwTlsIndex: TThreadVarSlot): pointer {.
importc: "TlsGetValue", stdcall, dynlib: "kernel32".} importc: "TlsGetValue", stdcall, dynlib: "kernel32".}
else: else:
@ -116,14 +116,14 @@ else:
proc pthread_cancel(a1: TSysThread): cint {. proc pthread_cancel(a1: TSysThread): cint {.
importc: "pthread_cancel", header: "<pthread.h>".} importc: "pthread_cancel", header: "<pthread.h>".}
proc AcquireSysTimeoutAux(L: var TSysLock, timeout: var Ttimespec): cint {. proc acquireSysTimeoutAux(L: var TSysLock, timeout: var Ttimespec): cint {.
importc: "pthread_mutex_timedlock", header: "<time.h>".} importc: "pthread_mutex_timedlock", header: "<time.h>".}
proc AcquireSysTimeout(L: var TSysLock, msTimeout: int) {.inline.} = proc acquireSysTimeout(L: var TSysLock, msTimeout: int) {.inline.} =
var a: Ttimespec var a: Ttimespec
a.tv_sec = msTimeout div 1000 a.tv_sec = msTimeout div 1000
a.tv_nsec = (msTimeout mod 1000) * 1000 a.tv_nsec = (msTimeout mod 1000) * 1000
var res = AcquireSysTimeoutAux(L, a) var res = acquireSysTimeoutAux(L, a)
if res != 0'i32: raise newException(EResourceExhausted, $strerror(res)) if res != 0'i32: raise newException(EResourceExhausted, $strerror(res))
type type
@ -141,11 +141,11 @@ else:
proc pthread_setspecific(a1: TThreadVarSlot, a2: pointer): int32 {. proc pthread_setspecific(a1: TThreadVarSlot, a2: pointer): int32 {.
importc: "pthread_setspecific", header: "<pthread.h>".} importc: "pthread_setspecific", header: "<pthread.h>".}
proc ThreadVarAlloc(): TThreadVarSlot {.inline.} = proc threadVarAlloc(): TThreadVarSlot {.inline.} =
discard pthread_key_create(addr(result), nil) discard pthread_key_create(addr(result), nil)
proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {.inline.} = proc threadVarSetValue(s: TThreadVarSlot, value: pointer) {.inline.} =
discard pthread_setspecific(s, value) discard pthread_setspecific(s, value)
proc ThreadVarGetValue(s: TThreadVarSlot): pointer {.inline.} = proc threadVarGetValue(s: TThreadVarSlot): pointer {.inline.} =
result = pthread_getspecific(s) result = pthread_getspecific(s)
when useStackMaskHack: when useStackMaskHack:
@ -159,7 +159,7 @@ const
when emulatedThreadVars: when emulatedThreadVars:
# the compiler generates this proc for us, so that we can get the size of # the compiler generates this proc for us, so that we can get the size of
# the thread local var block; we use this only for sanity checking though # the thread local var block; we use this only for sanity checking though
proc NimThreadVarsSize(): int {.noconv, importc: "NimThreadVarsSize".} proc nimThreadVarsSize(): int {.noconv, importc: "NimThreadVarsSize".}
# we preallocate a fixed size for thread local storage, so that no heap # we preallocate a fixed size for thread local storage, so that no heap
# allocations are needed. Currently less than 7K are used on a 64bit machine. # allocations are needed. Currently less than 7K are used on a 64bit machine.
@ -184,7 +184,7 @@ type
# XXX it'd be more efficient to not use a global variable for the # XXX it'd be more efficient to not use a global variable for the
# thread storage slot, but to rely on the implementation to assign slot X # thread storage slot, but to rely on the implementation to assign slot X
# for us... ;-) # for us... ;-)
var globalsSlot = ThreadVarAlloc() var globalsSlot = threadVarAlloc()
#const globalsSlot = TThreadVarSlot(0) #const globalsSlot = TThreadVarSlot(0)
#sysAssert checkSlot.int == globalsSlot.int #sysAssert checkSlot.int == globalsSlot.int
@ -193,7 +193,7 @@ when emulatedThreadVars:
result = addr(cast[PGcThread](ThreadVarGetValue(globalsSlot)).tls) result = addr(cast[PGcThread](ThreadVarGetValue(globalsSlot)).tls)
when useStackMaskHack: when useStackMaskHack:
proc MaskStackPointer(offset: int): pointer {.compilerRtl, inl.} = proc maskStackPointer(offset: int): pointer {.compilerRtl, inl.} =
var x {.volatile.}: pointer var x {.volatile.}: pointer
x = addr(x) x = addr(x)
result = cast[pointer]((cast[int](x) and not ThreadStackMask) +% result = cast[pointer]((cast[int](x) and not ThreadStackMask) +%
@ -205,7 +205,7 @@ when not defined(useNimRtl):
when not useStackMaskHack: when not useStackMaskHack:
var mainThread: TGcThread var mainThread: TGcThread
ThreadVarSetValue(globalsSlot, addr(mainThread)) threadVarSetValue(globalsSlot, addr(mainThread))
when not defined(createNimRtl): initStackBottom() when not defined(createNimRtl): initStackBottom()
initGC() initGC()
@ -220,18 +220,18 @@ when not defined(useNimRtl):
proc registerThread(t: PGcThread) = proc registerThread(t: PGcThread) =
# we need to use the GC global lock here! # we need to use the GC global lock here!
AcquireSys(HeapLock) acquireSys(HeapLock)
t.prev = nil t.prev = nil
t.next = threadList t.next = threadList
if threadList != nil: if threadList != nil:
sysAssert(threadList.prev == nil, "threadList.prev == nil") sysAssert(threadList.prev == nil, "threadList.prev == nil")
threadList.prev = t threadList.prev = t
threadList = t threadList = t
ReleaseSys(HeapLock) releaseSys(HeapLock)
proc unregisterThread(t: PGcThread) = proc unregisterThread(t: PGcThread) =
# we need to use the GC global lock here! # we need to use the GC global lock here!
AcquireSys(HeapLock) acquireSys(HeapLock)
if t == threadList: threadList = t.next if t == threadList: threadList = t.next
if t.next != nil: t.next.prev = t.prev if t.next != nil: t.next.prev = t.prev
if t.prev != nil: t.prev.next = t.next if t.prev != nil: t.prev.next = t.next
@ -239,7 +239,7 @@ when not defined(useNimRtl):
# code executes `destroyThread`: # code executes `destroyThread`:
t.next = nil t.next = nil
t.prev = nil t.prev = nil
ReleaseSys(HeapLock) releaseSys(HeapLock)
# on UNIX, the GC uses ``SIGFREEZE`` to tell every thread to stop so that # on UNIX, the GC uses ``SIGFREEZE`` to tell every thread to stop so that
# the GC can examine the stacks? # the GC can examine the stacks?
@ -266,7 +266,7 @@ type
when not defined(boehmgc) and not hasSharedHeap: when not defined(boehmgc) and not hasSharedHeap:
proc deallocOsPages() proc deallocOsPages()
template ThreadProcWrapperBody(closure: expr) {.immediate.} = template threadProcWrapperBody(closure: expr) {.immediate.} =
when defined(globalsSlot): ThreadVarSetValue(globalsSlot, closure) when defined(globalsSlot): ThreadVarSetValue(globalsSlot, closure)
var t = cast[ptr TThread[TArg]](closure) var t = cast[ptr TThread[TArg]](closure)
when useStackMaskHack: when useStackMaskHack:
@ -294,11 +294,11 @@ template ThreadProcWrapperBody(closure: expr) {.immediate.} =
{.push stack_trace:off.} {.push stack_trace:off.}
when defined(windows): when defined(windows):
proc threadProcWrapper[TArg](closure: pointer): int32 {.stdcall.} = proc threadProcWrapper[TArg](closure: pointer): int32 {.stdcall.} =
ThreadProcWrapperBody(closure) threadProcWrapperBody(closure)
# implicitly return 0 # implicitly return 0
else: else:
proc threadProcWrapper[TArg](closure: pointer) {.noconv.} = proc threadProcWrapper[TArg](closure: pointer) {.noconv.} =
ThreadProcWrapperBody(closure) threadProcWrapperBody(closure)
{.pop.} {.pop.}
proc running*[TArg](t: TThread[TArg]): bool {.inline.} = proc running*[TArg](t: TThread[TArg]): bool {.inline.} =
@ -308,7 +308,7 @@ proc running*[TArg](t: TThread[TArg]): bool {.inline.} =
proc joinThread*[TArg](t: TThread[TArg]) {.inline.} = proc joinThread*[TArg](t: TThread[TArg]) {.inline.} =
## waits for the thread `t` to finish. ## waits for the thread `t` to finish.
when hostOS == "windows": when hostOS == "windows":
discard WaitForSingleObject(t.sys, -1'i32) discard waitForSingleObject(t.sys, -1'i32)
else: else:
discard pthread_join(t.sys, nil) discard pthread_join(t.sys, nil)
@ -318,7 +318,7 @@ proc joinThreads*[TArg](t: varargs[TThread[TArg]]) =
var a: array[0..255, TSysThread] var a: array[0..255, TSysThread]
sysAssert a.len >= t.len, "a.len >= t.len" sysAssert a.len >= t.len, "a.len >= t.len"
for i in 0..t.high: a[i] = t[i].sys for i in 0..t.high: a[i] = t[i].sys
discard WaitForMultipleObjects(t.len.int32, discard waitForMultipleObjects(t.len.int32,
cast[ptr TSysThread](addr(a)), 1, -1) cast[ptr TSysThread](addr(a)), 1, -1)
else: else:
for i in 0..t.high: joinThread(t[i]) for i in 0..t.high: joinThread(t[i])
@ -346,7 +346,7 @@ proc createThread*[TArg](t: var TThread[TArg],
when hasSharedHeap: t.stackSize = ThreadStackSize when hasSharedHeap: t.stackSize = ThreadStackSize
when hostOS == "windows": when hostOS == "windows":
var dummyThreadId: int32 var dummyThreadId: int32
t.sys = CreateThread(nil, ThreadStackSize, threadProcWrapper[TArg], t.sys = createThread(nil, ThreadStackSize, threadProcWrapper[TArg],
addr(t), 0'i32, dummyThreadId) addr(t), 0'i32, dummyThreadId)
if t.sys <= 0: if t.sys <= 0:
raise newException(EResourceExhausted, "cannot create thread") raise newException(EResourceExhausted, "cannot create thread")

View file

@ -19,7 +19,7 @@ when defined(Windows):
type type
my_bool* = bool my_bool* = bool
Pmy_bool* = ptr my_bool Pmy_bool* = ptr my_bool
PVIO* = Pointer PVIO* = pointer
Pgptr* = ptr gptr Pgptr* = ptr gptr
gptr* = cstring gptr* = cstring
Pmy_socket* = ptr my_socket Pmy_socket* = ptr my_socket
@ -645,7 +645,7 @@ type
next_slave*: Pst_mysql next_slave*: Pst_mysql
last_used_slave*: Pst_mysql # needed for round-robin slave pick last_used_slave*: Pst_mysql # needed for round-robin slave pick
last_used_con*: Pst_mysql # needed for send/read/store/use result to work correctly with replication last_used_con*: Pst_mysql # needed for send/read/store/use result to work correctly with replication
stmts*: Pointer # was PList, list of all statements stmts*: pointer # was PList, list of all statements
methods*: Pst_mysql_methods methods*: Pst_mysql_methods
thd*: pointer # Points to boolean flag in MYSQL_RES or MYSQL_STMT. We set this flag thd*: pointer # Points to boolean flag in MYSQL_RES or MYSQL_STMT. We set this flag
# from mysql_stmt_close if close had to cancel result set of this object. # from mysql_stmt_close if close had to cancel result set of this object.

View file

@ -1,7 +1,3 @@
# Converted by Pas2mor v1.54
# Used command line arguments:
# -m -q -o bootstrap\options.mor options.pas
#
type type
# please make sure we have under 32 options (improves code efficiency!) # please make sure we have under 32 options (improves code efficiency!)

View file

@ -1,6 +1,8 @@
version 0.9.4 version 0.9.4
============= =============
- better tester
- ensure (ref T)(a, b) works as a type conversion and type constructor
- Aporia doesn't compile under devel - Aporia doesn't compile under devel
- document new templating symbol binding rules - document new templating symbol binding rules
- make '--implicitStatic:on' the default - make '--implicitStatic:on' the default