basic thread analysis working
This commit is contained in:
parent
c019d17561
commit
9f9f0f0818
11 changed files with 179 additions and 44 deletions
|
|
@ -1450,7 +1450,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
|
of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
|
||||||
mInSet:
|
mInSet:
|
||||||
genSetOp(p, e, d, op)
|
genSetOp(p, e, d, op)
|
||||||
of mNewString, mNewStringOfCap, mCopyStr, mCopyStrLast, mExit:
|
of mNewString, mNewStringOfCap, mCopyStr, mCopyStrLast, mExit, mCreateThread:
|
||||||
genCall(p, e, d)
|
genCall(p, e, d)
|
||||||
of mReset: genReset(p, e)
|
of mReset: genReset(p, e)
|
||||||
of mEcho: genEcho(p, e)
|
of mEcho: genEcho(p, e)
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ Advanced options:
|
||||||
--genMapping generate a mapping file containing
|
--genMapping generate a mapping file containing
|
||||||
(Nimrod, mangled) identifier pairs
|
(Nimrod, mangled) identifier pairs
|
||||||
--lineDir:on|off generation of #line directive on|off
|
--lineDir:on|off generation of #line directive on|off
|
||||||
--checkpoints:on|off turn checkpoints on|off; for debugging Nimrod
|
--threadanalysis:on|off turn thread analysis on|off
|
||||||
--skipCfg do not read the general configuration file
|
--skipCfg do not read the general configuration file
|
||||||
--skipProjCfg do not read the project's configuration file
|
--skipProjCfg do not read the project's configuration file
|
||||||
--gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC
|
--gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC
|
||||||
|
|
@ -252,7 +252,7 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
|
||||||
of wForceBuild, wF: result = contains(gGlobalOptions, optForceFullMake)
|
of wForceBuild, wF: result = contains(gGlobalOptions, optForceFullMake)
|
||||||
of wWarnings, wW: result = contains(gOptions, optWarns)
|
of wWarnings, wW: result = contains(gOptions, optWarns)
|
||||||
of wHints: result = contains(gOptions, optHints)
|
of wHints: result = contains(gOptions, optHints)
|
||||||
of wCheckpoints: result = contains(gOptions, optCheckpoints)
|
of wThreadAnalysis: result = contains(gGlobalOptions, optThreadAnalysis)
|
||||||
of wStackTrace: result = contains(gOptions, optStackTrace)
|
of wStackTrace: result = contains(gOptions, optStackTrace)
|
||||||
of wLineTrace: result = contains(gOptions, optLineTrace)
|
of wLineTrace: result = contains(gOptions, optLineTrace)
|
||||||
of wDebugger: result = contains(gOptions, optEndb)
|
of wDebugger: result = contains(gOptions, optEndb)
|
||||||
|
|
@ -367,7 +367,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||||
of wWarning: ProcessSpecificNote(arg, wWarning, pass, info)
|
of wWarning: ProcessSpecificNote(arg, wWarning, pass, info)
|
||||||
of wHint: ProcessSpecificNote(arg, wHint, pass, info)
|
of wHint: ProcessSpecificNote(arg, wHint, pass, info)
|
||||||
of wHints: ProcessOnOffSwitch({optHints}, arg, pass, info)
|
of wHints: ProcessOnOffSwitch({optHints}, arg, pass, info)
|
||||||
of wCheckpoints: ProcessOnOffSwitch({optCheckpoints}, arg, pass, info)
|
of wThreadAnalysis: ProcessOnOffSwitchG({optThreadAnalysis}, arg, pass, info)
|
||||||
of wStackTrace: ProcessOnOffSwitch({optStackTrace}, arg, pass, info)
|
of wStackTrace: ProcessOnOffSwitch({optStackTrace}, arg, pass, info)
|
||||||
of wLineTrace: ProcessOnOffSwitch({optLineTrace}, arg, pass, info)
|
of wLineTrace: ProcessOnOffSwitch({optLineTrace}, arg, pass, info)
|
||||||
of wDebugger:
|
of wDebugger:
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ type # please make sure we have under 32 options
|
||||||
optEndb, # embedded debugger
|
optEndb, # embedded debugger
|
||||||
optByRef, # use pass by ref for objects
|
optByRef, # use pass by ref for objects
|
||||||
# (for interfacing with C)
|
# (for interfacing with C)
|
||||||
optCheckpoints, # check for checkpoints (used for debugging)
|
|
||||||
optProfiler # profiler turned on
|
optProfiler # profiler turned on
|
||||||
TOptions* = set[TOption]
|
TOptions* = set[TOption]
|
||||||
TGlobalOption* = enum
|
TGlobalOption* = enum
|
||||||
|
|
@ -46,7 +45,9 @@ type # please make sure we have under 32 options
|
||||||
optStdout, # output to stdout
|
optStdout, # output to stdout
|
||||||
optSuggest, # ideTools: 'suggest'
|
optSuggest, # ideTools: 'suggest'
|
||||||
optContext, # ideTools: 'context'
|
optContext, # ideTools: 'context'
|
||||||
optDef # ideTools: 'def'
|
optDef, # ideTools: 'def'
|
||||||
|
optThreadAnalysis # thread analysis pass
|
||||||
|
|
||||||
TGlobalOptions* = set[TGlobalOption]
|
TGlobalOptions* = set[TGlobalOption]
|
||||||
TCommands* = enum # Nimrod's commands
|
TCommands* = enum # Nimrod's commands
|
||||||
cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
|
cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToOC,
|
||||||
|
|
@ -71,7 +72,7 @@ var
|
||||||
gOptions*: TOptions = {optObjCheck, optFieldCheck, optRangeCheck,
|
gOptions*: TOptions = {optObjCheck, optFieldCheck, optRangeCheck,
|
||||||
optBoundsCheck, optOverflowCheck, optAssert, optWarns,
|
optBoundsCheck, optOverflowCheck, optAssert, optWarns,
|
||||||
optHints, optStackTrace, optLineTrace}
|
optHints, optStackTrace, optLineTrace}
|
||||||
gGlobalOptions*: TGlobalOptions = {optRefcGC}
|
gGlobalOptions*: TGlobalOptions = {optRefcGC, optThreadAnalysis}
|
||||||
gExitcode*: int8
|
gExitcode*: int8
|
||||||
searchPaths*: TLinkedList
|
searchPaths*: TLinkedList
|
||||||
outFile*: string = ""
|
outFile*: string = ""
|
||||||
|
|
|
||||||
|
|
@ -106,23 +106,23 @@ proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string =
|
||||||
else: result = defaultStr
|
else: result = defaultStr
|
||||||
|
|
||||||
proc processMagic(c: PContext, n: PNode, s: PSym) =
|
proc processMagic(c: PContext, n: PNode, s: PSym) =
|
||||||
var v: string
|
#if sfSystemModule notin c.module.flags:
|
||||||
#if not (sfSystemModule in c.module.flags) then
|
# liMessage(n.info, errMagicOnlyInSystem)
|
||||||
# liMessage(n.info, errMagicOnlyInSystem);
|
|
||||||
if n.kind != nkExprColonExpr:
|
if n.kind != nkExprColonExpr:
|
||||||
LocalError(n.info, errStringLiteralExpected)
|
LocalError(n.info, errStringLiteralExpected)
|
||||||
return
|
return
|
||||||
|
var v: string
|
||||||
if n.sons[1].kind == nkIdent: v = n.sons[1].ident.s
|
if n.sons[1].kind == nkIdent: v = n.sons[1].ident.s
|
||||||
else: v = expectStrLit(c, n)
|
else: v = expectStrLit(c, n)
|
||||||
incl(s.flags, sfImportc)
|
|
||||||
# magics don't need an implementation, so we
|
|
||||||
# treat them as imported, instead of modifing a lot of working code
|
|
||||||
# BUGFIX: magic does not imply ``lfNoDecl`` anymore!
|
|
||||||
for m in countup(low(TMagic), high(TMagic)):
|
for m in countup(low(TMagic), high(TMagic)):
|
||||||
if substr($m, 1) == v:
|
if substr($m, 1) == v:
|
||||||
s.magic = m
|
s.magic = m
|
||||||
return
|
break
|
||||||
Message(n.info, warnUnknownMagic, v)
|
if s.magic == mNone: Message(n.info, warnUnknownMagic, v)
|
||||||
|
elif s.magic != mCreateThread:
|
||||||
|
# magics don't need an implementation, so we
|
||||||
|
# treat them as imported, instead of modifing a lot of working code:
|
||||||
|
incl(s.flags, sfImportc)
|
||||||
|
|
||||||
proc wordToCallConv(sw: TSpecialWord): TCallingConvention =
|
proc wordToCallConv(sw: TSpecialWord): TCallingConvention =
|
||||||
# this assumes that the order of special words and calling conventions is
|
# this assumes that the order of special words and calling conventions is
|
||||||
|
|
|
||||||
|
|
@ -568,7 +568,8 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
of mEcho: result = semEcho(c, setMs(n, s))
|
of mEcho: result = semEcho(c, setMs(n, s))
|
||||||
of mCreateThread:
|
of mCreateThread:
|
||||||
result = semDirectOp(c, n, flags)
|
result = semDirectOp(c, n, flags)
|
||||||
if optThreads in gGlobalOptions:
|
if gGlobalOptions * {optThreads, optThreadAnalysis} ==
|
||||||
|
{optThreads, optThreadAnalysis}:
|
||||||
# XXX This analysis should be done as late as possible
|
# XXX This analysis should be done as late as possible
|
||||||
# (forward references!)
|
# (forward references!)
|
||||||
semthreads.AnalyseThread(result)
|
semthreads.AnalyseThread(result)
|
||||||
|
|
|
||||||
|
|
@ -170,12 +170,23 @@ proc analyseCall(c: PProcCtx, n: PNode): TThreadOwner =
|
||||||
var formal = skipTypes(prc.typ, abstractInst).n.sons[i].sym
|
var formal = skipTypes(prc.typ, abstractInst).n.sons[i].sym
|
||||||
newCtx.mapping[formal.id] = call.args[i-1]
|
newCtx.mapping[formal.id] = call.args[i-1]
|
||||||
pushInfoContext(n.info)
|
pushInfoContext(n.info)
|
||||||
computed[call] = analyse(newCtx, prc.ast.sons[codePos])
|
result = analyse(newCtx, prc.ast.sons[codePos])
|
||||||
|
if prc.typ.sons[0] != nil:
|
||||||
|
if prc.ast.len > resultPos:
|
||||||
|
result = newCtx.mapping[prc.ast.sons[resultPos].sym.id]
|
||||||
|
else:
|
||||||
|
result = toNil
|
||||||
|
else:
|
||||||
|
result = toVoid
|
||||||
|
computed[call] = result
|
||||||
popInfoContext()
|
popInfoContext()
|
||||||
else:
|
else:
|
||||||
# ugh, cycle! We are already computing it but don't know the outcome yet...
|
result = computed[call]
|
||||||
if prc.typ.sons[0] == nil: result = toVoid
|
if result == toUndefined:
|
||||||
else: result = toNil
|
# ugh, cycle! We are already computing it but don't know the
|
||||||
|
# outcome yet...
|
||||||
|
if prc.typ.sons[0] == nil: result = toVoid
|
||||||
|
else: result = toNil
|
||||||
|
|
||||||
proc analyseVarTuple(c: PProcCtx, n: PNode) =
|
proc analyseVarTuple(c: PProcCtx, n: PNode) =
|
||||||
if n.kind != nkVarTuple: InternalError(n.info, "analyseVarTuple")
|
if n.kind != nkVarTuple: InternalError(n.info, "analyseVarTuple")
|
||||||
|
|
@ -210,28 +221,39 @@ template aggregateOwner(result, ana: expr) =
|
||||||
if result == toNil: result = a
|
if result == toNil: result = a
|
||||||
else: localError(n.info, errDifferentHeaps)
|
else: localError(n.info, errDifferentHeaps)
|
||||||
|
|
||||||
|
proc analyseOp(c: PProcCtx, n: PNode): TThreadOwner =
|
||||||
|
if n[0].kind != nkSym or n[0].sym.kind != skProc:
|
||||||
|
Message(n.info, warnAnalysisLoophole, renderTree(n))
|
||||||
|
result = toNil
|
||||||
|
else:
|
||||||
|
var prc = n[0].sym
|
||||||
|
# XXX create thread!?
|
||||||
|
case prc.magic
|
||||||
|
of mNew, mNewFinalize, mNewSeq, mSetLengthStr, mSetLengthSeq,
|
||||||
|
mAppendSeqElem, mReset, mAppendStrCh, mAppendStrStr:
|
||||||
|
writeAccess(c, n[1], toMine)
|
||||||
|
result = toVoid
|
||||||
|
of mSwap:
|
||||||
|
var a = analyse(c, n[2])
|
||||||
|
writeAccess(c, n[1], a)
|
||||||
|
writeAccess(c, n[2], a)
|
||||||
|
result = toVoid
|
||||||
|
of mIntToStr, mInt64ToStr, mFloatToStr, mBoolToStr, mCharToStr,
|
||||||
|
mCStrToStr, mStrToStr, mEnumToStr,
|
||||||
|
mConStrStr, mConArrArr, mConArrT,
|
||||||
|
mConTArr, mConTT, mSlice,
|
||||||
|
mRepr, mArrToSeq, mCopyStr, mCopyStrLast,
|
||||||
|
mNewString, mNewStringOfCap:
|
||||||
|
# XXX no check for effects in the arguments?
|
||||||
|
result = toMine
|
||||||
|
else:
|
||||||
|
result = analyseCall(c, n)
|
||||||
|
|
||||||
proc analyse(c: PProcCtx, n: PNode): TThreadOwner =
|
proc analyse(c: PProcCtx, n: PNode): TThreadOwner =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand,
|
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand,
|
||||||
nkCallStrLit, nkHiddenCallConv:
|
nkCallStrLit, nkHiddenCallConv:
|
||||||
if n[0].kind != nkSym or n[0].sym.kind != skProc:
|
result = analyseOp(c, n)
|
||||||
Message(n.info, warnAnalysisLoophole, renderTree(n))
|
|
||||||
result = toNil
|
|
||||||
else:
|
|
||||||
var prc = n[0].sym
|
|
||||||
# XXX create thread!?
|
|
||||||
case prc.magic
|
|
||||||
of mNew, mNewFinalize, mNewSeq, mSetLengthStr, mSetLengthSeq,
|
|
||||||
mAppendSeqElem, mReset, mAppendStrCh, mAppendStrStr:
|
|
||||||
writeAccess(c, n[1], toMine)
|
|
||||||
result = toVoid
|
|
||||||
of mSwap:
|
|
||||||
var a = analyse(c, n[2])
|
|
||||||
writeAccess(c, n[1], a)
|
|
||||||
writeAccess(c, n[2], a)
|
|
||||||
result = toVoid
|
|
||||||
else:
|
|
||||||
result = analyseCall(c, n)
|
|
||||||
of nkAsgn, nkFastAsgn:
|
of nkAsgn, nkFastAsgn:
|
||||||
analyseAssign(c, n)
|
analyseAssign(c, n)
|
||||||
result = toVoid
|
result = toVoid
|
||||||
|
|
@ -290,7 +312,8 @@ proc analyse(c: PProcCtx, n: PNode): TThreadOwner =
|
||||||
of nkVarSection: result = analyseVarSection(c, n)
|
of nkVarSection: result = analyseVarSection(c, n)
|
||||||
of nkConstSection: result = analyseConstSection(c, n)
|
of nkConstSection: result = analyseConstSection(c, n)
|
||||||
of nkTypeSection, nkCommentStmt: result = toVoid
|
of nkTypeSection, nkCommentStmt: result = toVoid
|
||||||
of nkIfStmt, nkWhileStmt, nkTryStmt, nkCaseStmt, nkStmtList, nkBlockStmt:
|
of nkIfStmt, nkWhileStmt, nkTryStmt, nkCaseStmt, nkStmtList, nkBlockStmt,
|
||||||
|
nkElifBranch, nkElse, nkExceptBranch, nkOfBranch:
|
||||||
for i in 0 .. <n.len: discard analyse(c, n[i])
|
for i in 0 .. <n.len: discard analyse(c, n[i])
|
||||||
result = toVoid
|
result = toVoid
|
||||||
of nkBreakStmt, nkContinueStmt: result = toVoid
|
of nkBreakStmt, nkContinueStmt: result = toVoid
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ type
|
||||||
wPassc, wT, wPassl, wL, wListcmd, wGendoc, wGenmapping, wOs, wCpu,
|
wPassc, wT, wPassl, wL, wListcmd, wGendoc, wGenmapping, wOs, wCpu,
|
||||||
wGenerate, wG, wC, wCpp, wBorrow, wRun, wR, wVerbosity, wV, wHelp, wH,
|
wGenerate, wG, wC, wCpp, wBorrow, wRun, wR, wVerbosity, wV, wHelp, wH,
|
||||||
wSymbolFiles, wFieldChecks, wX, wVersion, wAdvanced, wSkipcfg, wSkipProjCfg,
|
wSymbolFiles, wFieldChecks, wX, wVersion, wAdvanced, wSkipcfg, wSkipProjCfg,
|
||||||
wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar,
|
wCc, wGenscript, wCheckPoint, wThreadAnalysis, wNoMain, wSubsChar,
|
||||||
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
|
wAcyclic, wShallow, wUnroll, wLinearScanEnd,
|
||||||
wIndex,
|
wIndex,
|
||||||
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit, wThreads,
|
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar, wEmit, wThreads,
|
||||||
|
|
@ -100,7 +100,7 @@ const
|
||||||
"gui", "passc", "t", "passl", "l", "listcmd", "gendoc", "genmapping", "os",
|
"gui", "passc", "t", "passl", "l", "listcmd", "gendoc", "genmapping", "os",
|
||||||
"cpu", "generate", "g", "c", "cpp", "borrow", "run", "r", "verbosity", "v",
|
"cpu", "generate", "g", "c", "cpp", "borrow", "run", "r", "verbosity", "v",
|
||||||
"help", "h", "symbolfiles", "fieldchecks", "x", "version", "advanced",
|
"help", "h", "symbolfiles", "fieldchecks", "x", "version", "advanced",
|
||||||
"skipcfg", "skipprojcfg", "cc", "genscript", "checkpoint", "checkpoints",
|
"skipcfg", "skipprojcfg", "cc", "genscript", "checkpoint", "threadanalysis",
|
||||||
"nomain", "subschar", "acyclic", "shallow", "unroll", "linearscanend",
|
"nomain", "subschar", "acyclic", "shallow", "unroll", "linearscanend",
|
||||||
"index",
|
"index",
|
||||||
"write", "putenv", "prependenv", "appendenv", "threadvar", "emit",
|
"write", "putenv", "prependenv", "appendenv", "threadvar", "emit",
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ Advanced options:
|
||||||
--genMapping generate a mapping file containing
|
--genMapping generate a mapping file containing
|
||||||
(Nimrod, mangled) identifier pairs
|
(Nimrod, mangled) identifier pairs
|
||||||
--lineDir:on|off generation of #line directive on|off
|
--lineDir:on|off generation of #line directive on|off
|
||||||
--checkpoints:on|off turn checkpoints on|off; for debugging Nimrod
|
--threadanalysis:on|off turn thread analysis on|off
|
||||||
--skipCfg do not read the general configuration file
|
--skipCfg do not read the general configuration file
|
||||||
--skipProjCfg do not read the project's configuration file
|
--skipProjCfg do not read the project's configuration file
|
||||||
--gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC
|
--gc:refc|boehm|none use Nimrod's native GC|Boehm GC|no GC
|
||||||
|
|
|
||||||
54
tests/accept/compile/tthreadanalysis.nim
Normal file
54
tests/accept/compile/tthreadanalysis.nim
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
discard """
|
||||||
|
outputsub: "101"
|
||||||
|
cmd: "nimrod cc --hints:on --threads:on $# $#"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
const
|
||||||
|
noDeadlocks = defined(system.deadlocksPrevented)
|
||||||
|
|
||||||
|
var
|
||||||
|
thr: array [0..5, TThread[tuple[a, b: int]]]
|
||||||
|
|
||||||
|
proc doNothing() = nil
|
||||||
|
|
||||||
|
type
|
||||||
|
PNode = ref TNode
|
||||||
|
TNode = object {.pure.}
|
||||||
|
le, ri: PNode
|
||||||
|
data: string
|
||||||
|
|
||||||
|
var
|
||||||
|
root: PNode
|
||||||
|
|
||||||
|
proc buildTree(depth: int): PNode =
|
||||||
|
if depth == 3: return nil
|
||||||
|
new(result)
|
||||||
|
result.le = buildTree(depth-1)
|
||||||
|
result.ri = buildTree(depth-1)
|
||||||
|
result.data = $depth
|
||||||
|
|
||||||
|
proc echoLeTree(n: PNode) =
|
||||||
|
var it: PNode
|
||||||
|
it = nil
|
||||||
|
it = n
|
||||||
|
while it != nil:
|
||||||
|
echo it.data
|
||||||
|
it = it.le
|
||||||
|
|
||||||
|
proc threadFunc(interval: tuple[a, b: int]) {.procvar.} =
|
||||||
|
doNothing()
|
||||||
|
for i in interval.a..interval.b:
|
||||||
|
var r = buildTree(i)
|
||||||
|
echoLeTree(r) # for local data
|
||||||
|
echoLeTree(root) # and the same for foreign data :-)
|
||||||
|
|
||||||
|
proc main =
|
||||||
|
root = buildTree(5)
|
||||||
|
for i in 0..high(thr):
|
||||||
|
createThread(thr[i], threadFunc, (i*3, i*3+2))
|
||||||
|
joinThreads(thr)
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
||||||
54
tests/reject/tthreadanalysis2.nim
Normal file
54
tests/reject/tthreadanalysis2.nim
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
discard """
|
||||||
|
file: "tthreadanalysis2.nim"
|
||||||
|
line: 44
|
||||||
|
errormsg: "possible inconsistency of thread local heaps"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
const
|
||||||
|
noDeadlocks = defined(system.deadlocksPrevented)
|
||||||
|
|
||||||
|
var
|
||||||
|
thr: array [0..5, TThread[tuple[a, b: int]]]
|
||||||
|
|
||||||
|
proc doNothing() = nil
|
||||||
|
|
||||||
|
type
|
||||||
|
PNode = ref TNode
|
||||||
|
TNode = object {.pure.}
|
||||||
|
le, ri: PNode
|
||||||
|
data: string
|
||||||
|
|
||||||
|
var
|
||||||
|
root: PNode
|
||||||
|
|
||||||
|
proc buildTree(depth: int): PNode =
|
||||||
|
if depth == 3: return nil
|
||||||
|
new(result)
|
||||||
|
result.le = buildTree(depth-1)
|
||||||
|
result.ri = buildTree(depth-1)
|
||||||
|
result.data = $depth
|
||||||
|
|
||||||
|
proc echoLeTree(n: PNode) =
|
||||||
|
var it = n
|
||||||
|
while it != nil:
|
||||||
|
echo it.data
|
||||||
|
it = it.le
|
||||||
|
|
||||||
|
proc threadFunc(interval: tuple[a, b: int]) {.procvar.} =
|
||||||
|
doNothing()
|
||||||
|
for i in interval.a..interval.b:
|
||||||
|
var r = buildTree(i)
|
||||||
|
echoLeTree(r) # for local data
|
||||||
|
root = buildTree(2) # BAD!
|
||||||
|
echoLeTree(root) # and the same for foreign data :-)
|
||||||
|
|
||||||
|
proc main =
|
||||||
|
root = buildTree(5)
|
||||||
|
for i in 0..high(thr):
|
||||||
|
createThread(thr[i], threadFunc, (i*100, i*100+50))
|
||||||
|
joinThreads(thr)
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
||||||
4
todo.txt
4
todo.txt
|
|
@ -1,4 +1,7 @@
|
||||||
* codegen for threadvars
|
* codegen for threadvars
|
||||||
|
* clean up thread analysis: fix remaining XXX; thread analysis as a separate
|
||||||
|
pass
|
||||||
|
* implement message passing built-ins
|
||||||
|
|
||||||
* add --deadlock_prevention:on|off switch? timeout for locks?
|
* add --deadlock_prevention:on|off switch? timeout for locks?
|
||||||
* test the sort implementation again
|
* test the sort implementation again
|
||||||
|
|
@ -37,7 +40,6 @@ Bugs
|
||||||
for i in 0 .. high(t.data)-1:
|
for i in 0 .. high(t.data)-1:
|
||||||
var maxIdx = i
|
var maxIdx = i
|
||||||
for j in i+1 .. high(t.data):
|
for j in i+1 .. high(t.data):
|
||||||
if t.data[j].val == 3: echo "touched! ", t.data[j].key
|
|
||||||
if t.data[j].val > t.data[maxIdx].val: maxIdx = j
|
if t.data[j].val > t.data[maxIdx].val: maxIdx = j
|
||||||
swap(t.data[maxIdx], t.data[i])
|
swap(t.data[maxIdx], t.data[i])
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue