Source code for simudo.fem.ffc_jit_lock

import fcntl
import os
import threading
from contextlib import contextmanager
from os import path as osp

from cached_property import cached_property

import ffc
from ffc import jitcompiler

'''
hack: monkey-patch `ffc.jitcompiler` to add file-based locking so
different dolfin instances sharing the same `cache_dir` don't
interfere with each other
'''

# TODO: get dijitso path and use that instead instead of hardcoding
lockfilename = osp.join(os.environ['HOME'], '.cache/dolfin_ffc_lock/jit.lock')

[docs]class LockFile(object): def __init__(self, filename): self.filename = filename self._lock = threading.Lock() self._lock_count = 0 @cached_property def _file(self): os.makedirs(osp.dirname(self.filename), exist_ok=True) return open(self.filename, 'w+b') @cached_property def _fd(self): return self._file.fileno()
[docs] def acquire(self): with self._lock: if self._lock_count == 0: fcntl.lockf(self._fd, fcntl.LOCK_EX) self._lock_count += 1
# print("####### acquire lock pid={}".format(os.getpid()))
[docs] def release(self): # print("####### release lock pid={}".format(os.getpid())) with self._lock: self._lock_count -= 1 if self._lock_count == 0: fcntl.lockf(self._fd, fcntl.LOCK_UN)
def __enter__(self): self.acquire() return self def __exit__(self, exc_type, exc_value, traceback): self.release()
lockfile = LockFile(lockfilename) old_jit = jitcompiler.jit
[docs]def new_jit(ufl_object, parameters=None, indirect=False): with lockfile: return old_jit(ufl_object, parameters, indirect)
jitcompiler.jit = new_jit ffc.jit = new_jit