Skip to content

Commit

Permalink
[WIP] Refactoring to get publicly usable Locks
Browse files Browse the repository at this point in the history
  • Loading branch information
jsbueno committed Sep 29, 2024
1 parent 00e4276 commit 70eea18
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 65 deletions.
128 changes: 63 additions & 65 deletions src/extrainterpreters/memoryboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,18 @@
from . import interpreters, running_interpreters, get_current, raw_list_all
from . import _memoryboard
from .utils import (
guard_internal_use,
Field,
_InstMode,
_remote_memory,
_address_and_size,
_atomic_byte_lock,
DoubleField,
Field,
StructBase,
_InstMode,
ResourceBusyError,
guard_internal_use
)

from ._memoryboard import _remote_memory, _address_and_size, _atomic_byte_lock

_remote_memory = guard_internal_use(_remote_memory)
_address_and_size = guard_internal_use(_address_and_size)
_atomic_byte_lock = guard_internal_use(_atomic_byte_lock)

from .lock import _CrossInterpreterStructLock

class RemoteState:
building = 0
Expand Down Expand Up @@ -52,61 +50,61 @@ class RemoteDataState:
REMOTE_HEADER_SIZE = RemoteHeader._size


class _CrossInterpreterStructLock:
def __init__(self, struct, timeout=DEFAULT_TIMEOUT):
buffer_ptr, size = _address_and_size(struct._data) # , struct._offset)
# struct_ptr = buffer_ptr + struct._offset
lock_offset = struct._offset + struct._get_offset_for_field("lock")
if lock_offset >= size:
raise ValueError("Lock address out of bounds for struct buffer")
self._lock_address = buffer_ptr + lock_offset
self._original_timeout = self._timeout = timeout
self._entered = 0

def timeout(self, timeout: None | float):
"""One use only timeout, for the same lock
with lock.timeout(0.5):
...
"""
self._timeout = timeout
return self

def __enter__(self):
if self._entered:
self._entered += 1
return self
if self._timeout is None:
if not _atomic_byte_lock(self._lock_address):
self._timeout = self._original_timeout
raise ResourceBusyError("Couldn't acquire lock")
else:
threshold = time.time() + self._timeout
while time.time() <= threshold:
if _atomic_byte_lock(self._lock_address):
break
else:
self._timeout = self._original_timeout
raise TimeoutError("Timeout trying to acquire lock")
self._entered += 1
return self

def __exit__(self, *args):
if not self._entered:
return
self._entered -= 1
if self._entered:
return
buffer = _remote_memory(self._lock_address, 1)
buffer[0] = 0
del buffer
self._entered = False
self._timeout = self._original_timeout

def __getstate__(self):
state = self.__dict__.copy()
state["_entered"] = False
return state
#class _CrossInterpreterStructLock:
#def __init__(self, struct, timeout=DEFAULT_TIMEOUT):
#buffer_ptr, size = _address_and_size(struct._data) # , struct._offset)
## struct_ptr = buffer_ptr + struct._offset
#lock_offset = struct._offset + struct._get_offset_for_field("lock")
#if lock_offset >= size:
#raise ValueError("Lock address out of bounds for struct buffer")
#self._lock_address = buffer_ptr + lock_offset
#self._original_timeout = self._timeout = timeout
#self._entered = 0

#def timeout(self, timeout: None | float):
#"""One use only timeout, for the same lock

#with lock.timeout(0.5):
#...
#"""
#self._timeout = timeout
#return self

#def __enter__(self):
#if self._entered:
#self._entered += 1
#return self
#if self._timeout is None:
#if not _atomic_byte_lock(self._lock_address):
#self._timeout = self._original_timeout
#raise ResourceBusyError("Couldn't acquire lock")
#else:
#threshold = time.time() + self._timeout
#while time.time() <= threshold:
#if _atomic_byte_lock(self._lock_address):
#break
#else:
#self._timeout = self._original_timeout
#raise TimeoutError("Timeout trying to acquire lock")
#self._entered += 1
#return self

#def __exit__(self, *args):
#if not self._entered:
#return
#self._entered -= 1
#if self._entered:
#return
#buffer = _remote_memory(self._lock_address, 1)
#buffer[0] = 0
#del buffer
#self._entered = False
#self._timeout = self._original_timeout

#def __getstate__(self):
#state = self.__dict__.copy()
#state["_entered"] = False
#return state


# when a RemoteArray can't be destroyed in parent,
Expand Down Expand Up @@ -468,7 +466,7 @@ def __del__(self):
if getattr(self, "_data", None) is not None:
try:
self.close()
except TypeError:
except (TypeError, AttributeError):
# at interpreter shutdown, some of the names needed in "close"
# may have been deleted
pass
Expand Down
7 changes: 7 additions & 0 deletions src/extrainterpreters/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ def wrapper(*args, **kwargs):
return wrapper


from ._memoryboard import _remote_memory, _address_and_size, _atomic_byte_lock

_remote_memory = guard_internal_use(_remote_memory)
_address_and_size = guard_internal_use(_address_and_size)
_atomic_byte_lock = guard_internal_use(_atomic_byte_lock)


class clsproperty:
def __init__(self, method):
self.method = method
Expand Down

0 comments on commit 70eea18

Please sign in to comment.