summary refs log tree commit diff stats
path: root/lib/pure/concurrency
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2015-09-06 02:40:26 +0200
committerAraq <rumpf_a@web.de>2015-09-06 02:40:26 +0200
commitd7996a9edef4d8c51466495696bd2c0a3a2c03be (patch)
treef8aeb1eb66164cb7d16d5bf5e7c7c5344d513414 /lib/pure/concurrency
parentb1a55d83ec8e58bd0a66fe33dd8e82812b588cec (diff)
downloadNim-d7996a9edef4d8c51466495696bd2c0a3a2c03be.tar.gz
attempt to support recursions for spawn
Diffstat (limited to 'lib/pure/concurrency')
-rw-r--r--lib/pure/concurrency/threadpool.nim22
1 files changed, 20 insertions, 2 deletions
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