🔍 Code Extractor

function with_lock_v1

Maturity: 32

A decorator that implements reentrant locking for async methods, allowing the same task to acquire the lock multiple times without deadlocking.

File:
/tf/active/vicechatdev/rmcl/items.py
Lines:
26 - 35
Complexity:
moderate

Purpose

This decorator wraps async methods to ensure thread-safe execution using a Trio lock. It checks if the current task already owns the lock (reentrant behavior) and if so, executes the function directly without attempting to acquire the lock again. Otherwise, it acquires the lock before executing the function. This is useful for protecting shared resources in async class methods where methods might call each other.

Source Code

def with_lock(func):
    @functools.wraps(func)
    async def decorated(self, *args, **kw):
        if self._lock.statistics().owner == trio.lowlevel.current_task():
            return await func(self, *args, **kw)

        async with self._lock:
            return await func(self, *args, **kw)

    return decorated

Parameters

Name Type Default Kind
func - - positional_or_keyword

Parameter Details

func: An async function/method to be decorated. Expected to be a method that takes 'self' as its first parameter, followed by any number of positional and keyword arguments. The function must be async (coroutine).

Return Value

Returns a decorated async function that wraps the original function with lock acquisition logic. When called, the decorated function returns whatever the original function returns, but ensures it executes within a lock context unless the current task already owns the lock.

Dependencies

  • functools
  • trio

Required Imports

import functools
import trio

Usage Example

import functools
import trio

class MyResource:
    def __init__(self):
        self._lock = trio.Lock()
        self.data = []
    
    @with_lock
    async def add_item(self, item):
        self.data.append(item)
        await trio.sleep(0.1)
    
    @with_lock
    async def add_multiple(self, items):
        # This can call add_item without deadlock due to reentrant behavior
        for item in items:
            await self.add_item(item)

async def main():
    resource = MyResource()
    await resource.add_item('test')
    await resource.add_multiple(['a', 'b', 'c'])
    print(resource.data)

trio.run(main)

Best Practices

  • Only use this decorator on async methods (coroutines), not regular synchronous functions
  • Ensure the class has a '_lock' attribute initialized as a trio.Lock before any decorated methods are called
  • The decorator assumes 'self' is the first parameter, so it's designed for instance methods, not standalone functions
  • Be aware that reentrant locking allows the same task to enter the lock multiple times, which can mask certain concurrency bugs
  • Use this pattern when you have methods that need to call each other while maintaining thread safety
  • Consider the performance implications of lock acquisition in high-frequency method calls

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function add_sync 62.4% similar

    A decorator that creates a synchronous wrapper function for an async function, automatically running it with trio.run() and injecting it into the caller's namespace with a suffix.

    From: /tf/active/vicechatdev/rmcl/sync.py
  • function with_lock 61.7% similar

    A decorator that wraps callback functions (both sync and async) to mark them for execution with a Bokeh document lock, allowing safe modification of Bokeh models.

    From: /tf/active/vicechatdev/patches/server.py
  • function async_execute 52.9% similar

    Wraps and schedules async function execution in the appropriate event loop context, ensuring proper lock propagation and document context management for Bokeh/Panel applications.

    From: /tf/active/vicechatdev/patches/server.py
  • function get_task_status_v1 51.8% similar

    Thread-safe function that retrieves the current status of a task from a shared dictionary using a task identifier.

    From: /tf/active/vicechatdev/docchat/app.py
  • function update_task_progress 50.5% similar

    Thread-safe function that updates the progress and timestamp of an active task identified by task_id in a shared dictionary.

    From: /tf/active/vicechatdev/docchat/app.py
← Back to Browse