Skip to content

Commit

Permalink
restore default Lock token storage, add toggle to make it thread-local
Browse files Browse the repository at this point in the history
* add thread_local=False parameter to Lock.__init__() and StrictRedis.lock()
* use thread_local to decide whether to put token in thread-local storage
chillipino committed Jun 6, 2014
1 parent 318bab7 commit b010f4f
Showing 3 changed files with 24 additions and 4 deletions.
10 changes: 8 additions & 2 deletions redis/client.py
Original file line number Diff line number Diff line change
@@ -478,7 +478,7 @@ def transaction(self, func, *watches, **kwargs):
continue

def lock(self, name, timeout=None, sleep=0.1, blocking_timeout=None,
lock_class=None):
lock_class=None, thread_local=False):
"""
Return a new Lock object using key ``name`` that mimics
the behavior of threading.Lock.
@@ -496,6 +496,11 @@ def lock(self, name, timeout=None, sleep=0.1, blocking_timeout=None,
float or integer, both representing the number of seconds to wait.
``lock_class`` forces the specified lock implementation.
``thread_local`` indicates whether the lock token is placed in
thread-local storage. Setting this to True may be necessary if
multiple execution contexts (such as threads or coroutines) share
a single Lock instance within a process. Defaults to False.
"""
if lock_class is None:
if self._use_lua_lock is None:
@@ -508,7 +513,8 @@ def lock(self, name, timeout=None, sleep=0.1, blocking_timeout=None,
self._use_lua_lock = False
lock_class = self._use_lua_lock and LuaLock or Lock
return lock_class(self, name, timeout=timeout, sleep=sleep,
blocking_timeout=blocking_timeout)
blocking_timeout=blocking_timeout,
thread_local=thread_local)

def pubsub(self, **kwargs):
"""
11 changes: 9 additions & 2 deletions redis/lock.py
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
import time as mod_time
import uuid
from redis.exceptions import LockError, WatchError
from redis.utils import dummy
from redis._compat import b


@@ -14,7 +15,7 @@ class Lock(object):
multiple clients play nicely together.
"""
def __init__(self, redis, name, timeout=None, sleep=0.1,
blocking=True, blocking_timeout=None):
blocking=True, blocking_timeout=None, thread_local=False):
"""
Create a new Lock instance named ``name`` using the Redis client
supplied by ``redis``.
@@ -38,14 +39,20 @@ def __init__(self, redis, name, timeout=None, sleep=0.1,
spend trying to acquire the lock. A value of ``None`` indicates
continue trying forever. ``blocking_timeout`` can be specified as a
float or integer, both representing the number of seconds to wait.
``thread_local`` indicates whether the lock token is placed in
thread-local storage. Setting this to True may be necessary if
multiple execution contexts (such as threads or coroutines) share
a single Lock instance within a process. Defaults to False.
"""
self.redis = redis
self.name = name
self.timeout = timeout
self.sleep = sleep
self.blocking = blocking
self.blocking_timeout = blocking_timeout
self.local = threading.local()
self.thread_local = bool(thread_local)
self.local = threading.local() if self.thread_local else dummy()
self.local.token = None
if self.timeout and self.sleep > self.timeout:
raise LockError("'sleep' must be less than 'timeout'")
7 changes: 7 additions & 0 deletions redis/utils.py
Original file line number Diff line number Diff line change
@@ -24,3 +24,10 @@ def pipeline(redis_obj):
p = redis_obj.pipeline()
yield p
p.execute()


class dummy(object):
"""
Instances of this class can be used as an attribute container.
"""
pass

0 comments on commit b010f4f

Please sign in to comment.