patternpythonMinor
Invoke only by a single thread
Viewed 0 times
invokethreadsingleonly
Problem
I wrote a simple class in Python, which controls code invocation, in a multi-threaded environment, with the following logic:
The class' main method, named
In any point in time, only a single thread can invoke code the function passed as
If a specific thread tries to invoke its code, but some other thread is already invoking its code, then the
If there's an exception in the code being executed, it should raise to the calling context.
The code:
Usage:
I'd like to get some reviews: thread safety (maybe I'm missing something?), coding style, etc.
The class' main method, named
try_to_do, takes two function pointers as arguments: yes_we_can_fn and no_we_cannot_fn.In any point in time, only a single thread can invoke code the function passed as
yes_we_can_fn argument.If a specific thread tries to invoke its code, but some other thread is already invoking its code, then the
no_we_cannot_fn is invoked instead of yes_we_can_fn.If there's an exception in the code being executed, it should raise to the calling context.
The code:
from threading import Lock
class MyController():
def __init__(self):
self.locker = Lock()
self.is_active = False
def try_to_do(self, yes_we_can_fn, no_we_cannot_fn):
with self.locker:
if self.is_active:
we_can_do_it = False
else:
we_can_do_it = True
self.is_active = True
try:
if we_can_do_it:
yes_we_can_fn()
else:
no_we_cannot_fn()
finally:
if we_can_do_it:
with self.locker:
self.is_active = FalseUsage:
ctl = MyController()
def p1():
from time import sleep
print 'before sleep'
sleep(2)
print 'done'
def p2():
print 'too busy, will try some other time'
ctl.try_to_do(p1, p2)I'd like to get some reviews: thread safety (maybe I'm missing something?), coding style, etc.
Solution
You could avoid the
is_active variable by using the lock in a non-blocking manner:def try_to_do(self, yes_we_can_fn, no_we_cannot_fn):
if self.locker.acquire(False):
try:
yes_we_can_fn()
finally:
self.locker.release()
else:
no_we_cannot_fn()Code Snippets
def try_to_do(self, yes_we_can_fn, no_we_cannot_fn):
if self.locker.acquire(False):
try:
yes_we_can_fn()
finally:
self.locker.release()
else:
no_we_cannot_fn()Context
StackExchange Code Review Q#39647, answer score: 2
Revisions (0)
No revisions yet.