Implement locking so that simultaneous accesses to file build or check it once
authorNick Downing <downing.nick@gmail.com>
Mon, 8 Oct 2018 21:57:25 +0000 (08:57 +1100)
committerNick Downing <downing.nick@gmail.com>
Mon, 8 Oct 2018 21:59:09 +0000 (08:59 +1100)
build_cache.js

index e873043..7aab709 100644 (file)
@@ -11,24 +11,39 @@ let BuildCache = function() {
 
 BuildCache.prototype.get = async function(key, build_func) {
   let result = this.map.get(key)
-  if (result !== undefined) {
-    let deps = result.deps
-    let time = result.time
-    for (let i = 0; i < deps.length; ++i) {
-      stats = await fs_stat(deps[i])
-      if (stats.mtimeMs > time) {
-        this.map.delete(key)
-        result = undefined
-        break
-      }
-    }
-  }
   if (result === undefined) {
     result = {deps: [key], time: Date.now()}
-    await build_func(result)
+    result.done = (
+      async () => {
+        await build_func(result)
+        return result.value
+      }
+    )()
     this.map.set(key, result)
+    let value = await result.done
+    delete result.done
+    return value
+  }
+  if (result.done === undefined) {
+    result.done = (
+      async () => {
+        for (let i = 0; i < result.deps.length; ++i) {
+          stats = await fs_stat(result.deps[i])
+          if (stats.mtimeMs > result.time) {
+            result.deps = [key]
+            result.time = Date.now()
+            await build_func(result)
+            break
+          }
+        }
+        return result.value
+      }
+    )()
+    let value = await result.done
+    delete result.done
+    return result.value
   }
-  return result.value
+  return /*await*/ result.done
 }
 
 module.exports = BuildCache