from os import remove from contextlib import contextmanager from fcntl import flock, LOCK_EX, LOCK_UN class RefCounter: def __init__(self, lockpath): self.lockpath = lockpath self._lockfile = open(self.lockpath, 'a+') with self.locked(): counter = self._read_counter() self._write_counter(counter+1) @contextmanager def locked(self): flock(self._lockfile, LOCK_EX) yield flock(self._lockfile, LOCK_UN) def _read_counter(self): self._lockfile.seek(0) try: counter = int(self._lockfile.read()) except ValueError: counter = 0 return counter def _write_counter(self, counter): self._lockfile.seek(0) self._lockfile.truncate() self._lockfile.write(str(counter)) self._lockfile.flush() def teardown_instance(self): with self.locked(): counter = self._read_counter() if counter <= 1: remove(self.lockpath) self.deallocate() else: self._write_counter(counter-1) self._lockfile.close() def deallocate(self): pass