Is it possible to conveniently access the count of _thread.RLock via ctypes?

335 views Asked by At

It is possible to create a count property for threading._RLock._count by inheriting from the class and exposing the data from the underlying attribute. This is easily demonstrated by example:

import threading


# noinspection PyProtectedMember
class RLock(threading._RLock):
    """RLock() -> RLock instance with count property"""

    @property
    def count(self):
        """Count property showing current level of lock ownership."""
        return self._count
  1. Is it possible to do the same with the _thread.RLock by getting the count via ctypes?
  2. If it is possible, would the code have any advantages over the version shown above?
  3. If it would be advantageous, what code would one have to write to access the count?
1

There are 1 answers

2
georgexsh On BEST ANSWER

Is it possible to do the same with the _thread.RLock by getting the count via ctypes?

Yes, it is possible, as rlockobject strunct definition is given:

import ctypes, _thread

class RLock(_thread.RLock):

    offsetof_rlock_count = 32 # on 64-bit system

    @property
    def count(self):
        rlock_count_b = ctypes.string_at(id(self)+self.offsetof_rlock_count, 8)
        return int.from_bytes(rlock_count_b, 'little', signed=False)

rlock = RLock()
with rlock:
    with rlock:
        print(rlock.count)

yields:

2

or a more formal version:

class S_rlockobject(ctypes.Structure):

    _fields_ = [
        ('ob_refcnt', ctypes.c_ssize_t),
        ('ob_type', ctypes.c_void_p),
        ('rlock_lock', ctypes.c_void_p),
        ('rlock_owner', ctypes.c_long),
        ('rlock_count', ctypes.c_ulong),
        ('in_weakreflist', ctypes.c_void_p),
    ]

class RLock(_thread.RLock):

    def __init__(self):
        super().__init__()
        self._s = S_rlockobject.from_address(id(self))

    @property
    def count(self):
        return self._s.rlock_count

If it is possible, would the code have any advantages over the version shown above? If it would be advantageous, what code would one have to write to access the count?

Both methods utilize non-public API, it is hard to tell which is better, but I feel the inheriting pure python RLock implementation is simpler. The performance difference is neglectable here.