-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrcu.py
146 lines (122 loc) · 4.83 KB
/
rcu.py
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#! /usr/bin/env python
__author__ = 'Suresh Sundriyal'
__license__ = 'CC0 - No rights reserved.'
__version__ = '0.0.1'
from threading import Lock
from collections import OrderedDict
from itertools import repeat
__all__ = ['RCUCache']
class RCUCache(object): # pylint: disable=too-few-public-methods
'''
TODO: Put in the class documentation.
'''
# The following makes the object unextendable.
__slots__ = ('maxsize', 'odict', 'modification_guard', '_setattr')
# The following values cannot be pickled.
_unpicklable = set(['modification_guard', '_setattr'])
def __setattr__(self, *args, **kwargs):
# Override __setattr__ to make the object itself immutable.
raise TypeError('%s is immutable' % self.__class__.__name__)
__delattr__ = __setattr__
def __init__(self, maxsize=None, items=None):
if items is None:
items = []
super(self.__class__,
self).__setattr__('_setattr',
super(self.__class__, self).__setattr__)
# pylint: disable=no-member
self._setattr('maxsize', maxsize)
self._setattr('odict', OrderedDict(items))
self._setattr('modification_guard', Lock())
# pylint: enable=no-member
def __getstate__(self):
state = {}
for var in set(self.__slots__) - self._unpicklable:
state[var] = getattr(self, var)
return state
def __setstate__(self, state):
super(self.__class__,
self).__setattr__('_setattr',
super(self.__class__, self).__setattr__)
# pylint: disable=no-member
self._setattr('modification_guard', Lock())
for var in state:
self._setattr(var, state[var])
# pylint: enable=no-member
def __contains__(self, *args, **kwargs):
'''
Lookup is disabled since looking up an object and then accessing it is
inherently a race condition.
'''
raise TypeError("Directly access the %s members to test for membership"
% self.__class__.__name__)
def __getitem__(self, key):
return self.odict[key] # pylint: disable=no-member
def __setitem__(self, key, value):
# pylint: disable=no-member
with self.modification_guard:
temp_odict = OrderedDict(self.odict)
if self.maxsize and len(self.odict) == self.maxsize:
temp_odict.popitem(last=False)
temp_odict[key] = value
self._setattr('odict', temp_odict)
# pylint: enable=no-member
def __delitem__(self, key):
# pylint: disable=no-member
with self.modification_guard:
temp_odict = OrderedDict(self.odict)
del temp_odict[key]
self._setattr('odict', temp_odict)
# pylint: enable=no-member
def __repr__(self):
# pylint: disable=no-member
return '%s(maxsize=%s, items=%r)' % (self.__class__.__name__,
self.maxsize, self.odict)
# pylint: enable=no-member
def __len__(self):
return len(self.odict) # pylint: disable=no-member
def clear(self):
'''
Clear out all the elements in the container.
'''
# pylint: disable=no-member
with self.modification_guard:
self._setattr('odict', OrderedDict())
# pylint: enable=no-member
def copy(self):
'''
Create a copy of the object
'''
return self.__class__(self.maxsize, self.odict) # pylint: disable=no-member
def update(self, *args, **kwargs):
# pylint: disable=no-member
with self.modification_guard:
temp_odict = OrderedDict(self.odict)
temp_odict.update(*args, **kwargs)
if self.maxsize and len(temp_odict) > self.maxsize:
for _ in repeat(None, (len(temp_odict) - self.maxsize)):
temp_odict.popitem(last=False)
self._setattr('odict', temp_odict)
# pylint: enable=no-member
def popitem(self, last=True):
# pylint: disable=no-member
with self.modification_guard:
temp_odict = OrderedDict(self.odict)
retval = temp_odict.popitem(last=last)
self._setattr('odict', temp_odict)
return retval
# pylint: enable=no-member
def pop(self, *args, **kwargs):
# pylint: disable=no-member
with self.modification_guard:
temp_odict = OrderedDict(self.odict)
retval = temp_odict.pop(*args, **kwargs)
self._setattr('odict', temp_odict)
return retval
# pylint: enable=no-member
def items(self, *args, **kwargs):
tempRef = self.odict
return tempRef.items()
def __iter__(self, *args, **kwargs):
tempRef = self.odict
return iter(tempRef)