python: Ensure greater concurrency is wsgidir.
authorFredrik Tolf <fredrik@dolda2000.com>
Tue, 13 Dec 2011 04:46:31 +0000 (05:46 +0100)
committerFredrik Tolf <fredrik@dolda2000.com>
Tue, 13 Dec 2011 04:52:53 +0000 (05:52 +0100)
python/ashd/wsgidir.py
python3/ashd/wsgidir.py

index 8b473f2..991b9f6 100644 (file)
@@ -55,7 +55,7 @@ class cachedmod(object):
     Additional data attributes can be arbitrarily added for recording
     any meta-data about the module.
     """
-    def __init__(self, mod, mtime):
+    def __init__(self, mod = None, mtime = -1):
         self.lock = threading.Lock()
         self.mod = mod
         self.mtime = mtime
@@ -91,23 +91,28 @@ def getmod(path):
     try:
         if path in modcache:
             entry = modcache[path]
-            if sb.st_mtime <= entry.mtime:
-                return entry
-        
-        f = open(path)
-        try:
-            text = f.read()
-        finally:
-            f.close()
-        code = compile(text, path, "exec")
-        mod = types.ModuleType(mangle(path))
-        mod.__file__ = path
-        exec code in mod.__dict__
-        entry = cachedmod(mod, sb.st_mtime)
-        modcache[path] = entry
-        return entry
+        else:
+            entry = cachedmod()
+            modcache[path] = entry
     finally:
         cachelock.release()
+    entry.lock.acquire()
+    try:
+        if entry.mod is None or sb.st_mtime > entry.mtime:
+            f = open(path, "r")
+            try:
+                text = f.read()
+            finally:
+                f.close()
+            code = compile(text, path, "exec")
+            mod = types.ModuleType(mangle(path))
+            mod.__file__ = path
+            exec code in mod.__dict__
+            entry.mod = mod
+            entry.mtime = sb.st_mtime
+        return entry
+    finally:
+        entry.lock.release()
 
 def chain(env, startreq):
     path = env["SCRIPT_FILENAME"]
index d4289a7..031952b 100644 (file)
@@ -37,7 +37,7 @@ must, of course, be importable). When writing such handler functions,
 you will probably want to use the getmod() function in this module.
 """
 
-import os, threading, types
+import os, threading, types, importlib
 from . import wsgiutil
 
 __all__ = ["application", "wmain", "getmod", "cachedmod"]
@@ -55,7 +55,7 @@ class cachedmod(object):
     Additional data attributes can be arbitrarily added for recording
     any meta-data about the module.
     """
-    def __init__(self, mod, mtime):
+    def __init__(self, mod = None, mtime = -1):
         self.lock = threading.Lock()
         self.mod = mod
         self.mtime = mtime
@@ -90,20 +90,19 @@ def getmod(path):
     with cachelock:
         if path in modcache:
             entry = modcache[path]
-            if sb.st_mtime <= entry.mtime:
-                return entry
-        
-        f = open(path)
-        try:
-            text = f.read()
-        finally:
-            f.close()
-        code = compile(text, path, "exec")
-        mod = types.ModuleType(mangle(path))
-        mod.__file__ = path
-        exec(code, mod.__dict__)
-        entry = cachedmod(mod, sb.st_mtime)
-        modcache[path] = entry
+        else:
+            entry = cachedmod()
+            modcache[path] = entry
+    with entry.lock:
+        if entry.mod is None or sb.st_mtime > entry.mtime:
+            with open(path, "rb") as f:
+                text = f.read()
+            code = compile(text, path, "exec")
+            mod = types.ModuleType(mangle(path))
+            mod.__file__ = path
+            exec(code, mod.__dict__)
+            entry.mod = mod
+            entry.mtime = sb.st_mtime
         return entry
 
 def chain(env, startreq):