Last active
August 29, 2015 14:17
-
-
Save kurtbrose/25b48114de216a5e55df to your computer and use it in GitHub Desktop.
Assigns arbitrary weakref-able objects the smallest possible unique integer IDs, such that no two objects have the same ID at the same time.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import weakref | |
import heapq | |
class Aliaser(object): | |
''' | |
Assigns arbitrary weakref-able objects the smallest possible unique | |
integer IDs, such that no two objects have the same ID at the same | |
time. | |
''' | |
def __init__(self): | |
self.mapping = weakref.WeakKeyDictionary() | |
self.ref_map = {} | |
self.free = [] | |
def get(self, a): | |
if a in self.mapping: # if mapping exists, return it | |
return self.mapping[a][0] | |
if self.free: # if there are any free numbers, use the smallest | |
nxt = heapq.heappop(self.free) | |
else: # if there are no free numbers, use the next highest number | |
nxt = len(self.mapping) | |
ref = weakref.ref(a, self._clean) | |
self.mapping[a] = (nxt, ref) | |
self.ref_map[ref] = nxt | |
return nxt | |
def drop(self, a): | |
freed, ref = self.mapping[a] | |
del self.mapping[a] | |
del self.ref_map[ref] | |
heapq.heappush(self.free, freed) | |
def _clean(self, ref): | |
heapq.heappush(self.free, self.ref_map[ref]) | |
del self.ref_map[ref] | |
def __contains__(self, a): | |
return a in self.mapping | |
def __iter__(self): | |
return self.mapping.itervalues() | |
def __len__(self): | |
return self.mapping.__len__() | |
def iteritems(self): | |
return self.mapping.iteritems() | |
def test(): | |
aliaser = Aliaser() | |
class Foo(object): pass | |
# use this circular array to have them periodically collected | |
ref_wheel = [None, None, None] | |
for i in range(1000): | |
nxt = Foo() | |
ref_wheel[i % len(ref_wheel)] = nxt | |
assert aliaser.get(nxt) <= len(ref_wheel) | |
if i % 10 == 0: | |
aliaser.drop(nxt) | |
if __name__ == "__main__": | |
test() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment