From d7996a9edef4d8c51466495696bd2c0a3a2c03be Mon Sep 17 00:00:00 2001 From: Araq <rumpf_a@web.de> Date: Sun, 6 Sep 2015 02:40:26 +0200 Subject: attempt to support recursions for spawn --- lib/pure/concurrency/threadpool.nim | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'lib/pure/concurrency') diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim index 0079cf302..72e744d52 100644 --- a/lib/pure/concurrency/threadpool.nim +++ b/lib/pure/concurrency/threadpool.nim @@ -295,7 +295,8 @@ proc slave(w: ptr Worker) {.thread.} = readyWorker = w signal(gSomeReady) await(w.taskArrived) - # XXX Somebody needs to look into this (why does this assertion fail in Visual Studio?) + # XXX Somebody needs to look into this (why does this assertion fail + # in Visual Studio?) when not defined(vcc): assert(not w.ready) w.f(w, w.data) if w.q.len != 0: w.cleanFlowVars @@ -338,6 +339,9 @@ proc setMaxPoolSize*(size: range[1..MaxThreadPoolSize]) = let w = addr(workersData[i]) w.shutdown = true +when defined(nimRecursiveSpawn): + var localThreadId {.threadvar.}: int + proc activateWorkerThread(i: int) {.noinline.} = workersData[i].taskArrived = createSemaphore() workersData[i].taskStarted = createSemaphore() @@ -345,6 +349,8 @@ proc activateWorkerThread(i: int) {.noinline.} = workersData[i].q.empty = createSemaphore() initLock(workersData[i].q.lock) createThread(workers[i], slave, addr(workersData[i])) + when defined(nimRecursiveSpawn): + localThreadId = i+1 when defined(nimPinToCpu): if gCpus > 0: pinToCpu(workers[i], i mod gCpus) @@ -436,7 +442,19 @@ proc nimSpawn3(fn: WorkerProc; data: pointer) {.compilerProc.} = release(stateLock) # else the acquire failed, but this means some # other thread succeeded, so we don't need to do anything here. - await(gSomeReady) + when defined(nimRecursiveSpawn): + if localThreadId > 0: + # we are a worker thread, so instead of waiting for something which + # might as well never happen (see tparallel_quicksort), we run the task + # on the current thread instead. + var self = addr(workersData[localThreadId-1]) + fn(self, data) + await(self.taskStarted) + return + else: + await(gSomeReady) + else: + await(gSomeReady) var distinguishedLock: TLock -- cgit 1.4.1-2-gfad0