Hide keyboard shortcuts

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 

2 

3from .compat import threading 

4 

5 

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. 

10 

11 e.g.:: 

12 

13 class MyFoo(object): 

14 "some important object." 

15 def __init__(self, identifier): 

16 self.identifier = identifier 

17 

18 registry = NameRegistry(MyFoo) 

19 

20 # thread 1: 

21 my_foo = registry.get("foo1") 

22 

23 # thread 2 

24 my_foo = registry.get("foo1") 

25 

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. 

30 

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. 

35 

36 :param creator: A function that will create a new 

37 value, given the identifier passed to the :meth:`.NameRegistry.get` 

38 method. 

39 

40 """ 

41 

42 _locks = weakref.WeakValueDictionary() 

43 _mutex = threading.RLock() 

44 

45 def __init__(self, creator): 

46 """Create a new :class:`.NameRegistry`. 

47 

48 

49 """ 

50 self._values = weakref.WeakValueDictionary() 

51 self._mutex = threading.RLock() 

52 self.creator = creator 

53 

54 def get(self, identifier, *args, **kw): 

55 r"""Get and possibly create the value. 

56 

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. 

63 

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) 

72 

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()