是否可以通过 ctypes 方便地访问 _thread.RLock 的计数?

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

通过从 class 继承并公开底层属性的数据,可以为 threading._RLock._count 创建 count 属性。这很容易通过示例证明:

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. 是否可以通过 ctypes 获取计数来对 _thread.RLock 执行相同的操作?
  2. 如果可能的话,代码是否比上面显示的版本有任何优势?
  3. 如果有利的话,必须编写什么代码才能访问计数?

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

是的,这是可能的,因为 rlockobject strunct definition 给出:

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)

产量:

2

或更正式的版本:

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?

两种方法都利用非publicAPI,很难说哪个更好,但我觉得继承纯pythonRLock实现更简单。性能差异在这里可以忽略不计。