Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/dogpile/util/nameregistry.py : 75%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import weakref
3from .compat import threading
6class NameRegistry(object):
7 """Generates and return an object, keeping it as a
8 singleton for a certain identifier for as long as its
9 strongly referenced.
11 e.g.::
13 class MyFoo(object):
14 "some important object."
15 def __init__(self, identifier):
16 self.identifier = identifier
18 registry = NameRegistry(MyFoo)
20 # thread 1:
21 my_foo = registry.get("foo1")
23 # thread 2
24 my_foo = registry.get("foo1")
26 Above, ``my_foo`` in both thread #1 and #2 will
27 be *the same object*. The constructor for
28 ``MyFoo`` will be called once, passing the
29 identifier ``foo1`` as the argument.
31 When thread 1 and thread 2 both complete or
32 otherwise delete references to ``my_foo``, the
33 object is *removed* from the :class:`.NameRegistry` as
34 a result of Python garbage collection.
36 :param creator: A function that will create a new
37 value, given the identifier passed to the :meth:`.NameRegistry.get`
38 method.
40 """
42 _locks = weakref.WeakValueDictionary()
43 _mutex = threading.RLock()
45 def __init__(self, creator):
46 """Create a new :class:`.NameRegistry`.
49 """
50 self._values = weakref.WeakValueDictionary()
51 self._mutex = threading.RLock()
52 self.creator = creator
54 def get(self, identifier, *args, **kw):
55 r"""Get and possibly create the value.
57 :param identifier: Hash key for the value.
58 If the creation function is called, this identifier
59 will also be passed to the creation function.
60 :param \*args, \**kw: Additional arguments which will
61 also be passed to the creation function if it is
62 called.
64 """
65 try:
66 if identifier in self._values:
67 return self._values[identifier]
68 else:
69 return self._sync_get(identifier, *args, **kw)
70 except KeyError:
71 return self._sync_get(identifier, *args, **kw)
73 def _sync_get(self, identifier, *args, **kw):
74 self._mutex.acquire()
75 try:
76 try:
77 if identifier in self._values:
78 return self._values[identifier]
79 else:
80 self._values[identifier] = value = self.creator(
81 identifier, *args, **kw
82 )
83 return value
84 except KeyError:
85 self._values[identifier] = value = self.creator(
86 identifier, *args, **kw
87 )
88 return value
89 finally:
90 self._mutex.release()