aboutsummaryrefslogtreecommitdiff
path: root/luxc/src/lux/compiler/parallel.clj
blob: 1c4da1a115abac01b719c939c95f0eb8a4e17fce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
(ns lux.compiler.parallel
  (:require (clojure [string :as string]
                     [set :as set]
                     [template :refer [do-template]])
            clojure.core.match
            clojure.core.match.array
            (lux [base :as & :refer [|let |do return* return |case]])))

;; [Utils]
(def ^:private !state! (ref {}))

(def ^:private get-compiler
  (fn [compiler]
    (return* compiler compiler)))

;; [Exports]
(defn setup!
  "Must always call this function before using parallel compilation to make sure that the state that is being tracked is in proper shape."
  []
  (dosync (ref-set !state! {})))

(defn parallel-compilation [compile-module*]
  (fn [module-name]
    (|do [compiler get-compiler
          :let [[task new?] (dosync (if-let [existing-task (get @!state! module-name)]
                                      (&/T [existing-task false])
                                      (let [new-task (promise)]
                                        (do (alter !state! assoc module-name new-task)
                                          (&/T [new-task true])))))
                _ (when new?
                    (.start (new Thread
                                 (fn []
                                   (let [out-str (with-out-str
                                                   (|case (&/run-state (compile-module* module-name)
                                                                       compiler)
                                                     (&/$Right post-compiler _)
                                                     (deliver task (&/$Right post-compiler))

                                                     (&/$Left ?error)
                                                     (deliver task (&/$Left ?error))))]
                                     (&/|log! out-str))))))]]
      (return task))))