Futures: Avoid creating the worker pool more than once.
authorMark H Weaver <mhw@netris.org>
Wed, 7 Nov 2012 13:39:42 +0000 (08:39 -0500)
committerMark H Weaver <mhw@netris.org>
Sat, 10 Nov 2012 15:08:19 +0000 (10:08 -0500)
* module/ice-9/futures.scm (%create-workers!): Use 'with-mutex' in case
  an exception is thrown.  Within the critical section, check to make
  sure the worker pool hasn't already been created by another thread.

module/ice-9/futures.scm

index 0f64b5c..7fbccf6 100644 (file)
@@ -19,6 +19,7 @@
 (define-module (ice-9 futures)
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-9)
+  #:use-module (ice-9 threads)
   #:use-module (ice-9 q)
   #:export (future make-future future? touch))
 
@@ -157,15 +158,20 @@ touched."
 (define %workers '())
 
 (define (%create-workers!)
-  (lock-mutex %futures-mutex)
-  (set! %workers
-        (unfold (lambda (i) (>= i %worker-count))
-                (lambda (i)
-                  (call-with-new-thread process-futures))
-                1+
-                0))
-  (set! create-workers! (lambda () #t))
-  (unlock-mutex %futures-mutex))
+  (with-mutex
+   %futures-mutex
+   ;; Setting 'create-workers!' to a no-op is an optimization, but it is
+   ;; still possible for '%create-workers!' to be called more than once
+   ;; from different threads.  Therefore, to avoid creating %workers more
+   ;; than once (and thus creating too many threads), we check to make
+   ;; sure %workers is empty within the critical section.
+   (when (null? %workers)
+     (set! %workers
+           (unfold (lambda (i) (>= i %worker-count))
+                   (lambda (i) (call-with-new-thread process-futures))
+                   1+
+                   0))
+     (set! create-workers! (lambda () #t)))))
 
 (define create-workers!
   (lambda () (%create-workers!)))