1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
##############################################################################
#
# Copyright (c) 2000-2008 Jens Vagelpohl and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
""" SharedResource: Unique resource store
$Id: SharedResource.py 1485 2008-06-04 16:08:38Z jens $
"""
"""Shared Resource.
'Shared Resource' is a module that manages resources shared by all threads.
Such resources can be controlled much more easily. A shared resource provides
locking capabilities (via Python's RLock) and performs automatic locking for
function calls. Access to non-functions is not protected.
A shared resource is identified by an id. The application
is responsible that id s are unique.
"""
from threading import _RLock, Lock
_ResourceMap = {}
_ResourceLock = Lock()
def getResource(id, factory, factoryArgs=()):
"""returns a resource for *id*.
If such a resource does not yet exist, one is created
by calling *factory* with *factoryArgs*.
Note, that *factory* and *factoryArgs* should only
depend on *id* and not any other context, as no
object is created, when a resource for *id* already
exists.
"""
_ResourceLock.acquire()
try:
try:
return _ResourceMap[id]
except KeyError:
_ResourceMap[id] = _SharedResource(factory(*factoryArgs))
return _ResourceMap[id]
finally:
_ResourceLock.release()
def setResource(id, resource):
""" Forcibly set the resource """
_ResourceLock.acquire()
try:
_ResourceMap[id] = _SharedResource(resource)
finally:
_ResourceLock.release()
class _SharedResource(_RLock):
# for __setattr__
_myAttributes = { '_target' : None
# _RLock instance variables
, '_RLock__block' : None
, '_RLock__count' : None
, '_RLock__owner' : None
# Verbose instance variables
, '_Verbose__verbose' : None
}
_myAttributes.update(_RLock.__dict__)
_isMyAttribute = _myAttributes.has_key
_target = None
def __init__(self, target):
self._target = target
_RLock.__init__(self)
def __getattr__(self, key):
a = getattr(self._target, key)
if callable(a):
a = _SharedCallable(self,a)
return a
def __setattr__(self, key, value):
if self._isMyAttribute(key):
self.__dict__[key] = value
else:
setattr(self._target, key, value)
def _type(self):
return type(self._target)
# def __delattr__(self,key,value): # do not implement for the time being
def __len__(self): return len(self._target)
def __getitem__(self, key): return self._target[key]
def __setitem__(self, key, value): self._target[key] = value
def __delitem__(self, key): del self._target[key]
class _SharedCallable:
def __init__(self, lock, callable):
self._lock = lock
self._callable = callable
def __call__(self, *args, **kw):
self._lock.acquire()
try:
return self._callable(*args, **kw)
finally:
self._lock.release()
|