file_baton.py 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. # mypy: allow-untyped-defs
  2. import os
  3. import time
  4. class FileBaton:
  5. """A primitive, file-based synchronization utility."""
  6. def __init__(self, lock_file_path, wait_seconds=0.1):
  7. """
  8. Create a new :class:`FileBaton`.
  9. Args:
  10. lock_file_path: The path to the file used for locking.
  11. wait_seconds: The seconds to periodically sleep (spin) when
  12. calling ``wait()``.
  13. """
  14. self.lock_file_path = lock_file_path
  15. self.wait_seconds = wait_seconds
  16. self.fd = None
  17. def try_acquire(self):
  18. """
  19. Try to atomically create a file under exclusive access.
  20. Returns:
  21. True if the file could be created, else False.
  22. """
  23. try:
  24. self.fd = os.open(self.lock_file_path, os.O_CREAT | os.O_EXCL)
  25. return True
  26. except FileExistsError:
  27. return False
  28. def wait(self):
  29. """
  30. Periodically sleeps for a certain amount until the baton is released.
  31. The amount of time slept depends on the ``wait_seconds`` parameter
  32. passed to the constructor.
  33. """
  34. while os.path.exists(self.lock_file_path):
  35. time.sleep(self.wait_seconds)
  36. def release(self):
  37. """Release the baton and removes its file."""
  38. if self.fd is not None:
  39. os.close(self.fd)
  40. os.remove(self.lock_file_path)