Created
December 22, 2017 18:32
-
-
Save agfor/96df405bbd3f7ebfc3de9f2d24a36dce to your computer and use it in GitHub Desktop.
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
#!/usr/bin/env python3 | |
import random | |
from collections import Counter, OrderedDict | |
class OrderedCounter(Counter, OrderedDict): | |
pass | |
class FakeEtcd: | |
def __init__(self, count): | |
self.locks = [0 for _ in range(count)] | |
def set(self): | |
self.locks = [lock + 1 for lock in self.locks] | |
return self.locks | |
def rem(self, lock): | |
self.locks[lock] = 0 | |
def __str__(self): | |
return str(self.locks) | |
class MultiLock: | |
def __init__(self, count): | |
self.etcd = FakeEtcd(count) | |
self.count = count | |
def get(self): | |
locks = self.etcd.set() | |
print(locks) | |
high = sum(1 for lock in locks if lock > self.count) | |
if high == self.count: | |
print("too high") | |
return None | |
elif len(set(locks)) > 1: | |
print("don't all match") | |
value = Counter(locks).most_common(1)[0][0] | |
lock = len(locks) - list(reversed(locks)).index(value) - 1 | |
if locks[lock] == max(locks) and Counter(locks)[locks[lock]] == 1: | |
return None | |
else: | |
if locks[lock] >= self.count: | |
return lock - 1 | |
else: | |
return lock | |
for i, lock in enumerate(locks): | |
if lock == 1: | |
print("lock == 1") | |
return i | |
else: | |
print("all match") | |
return len(locks) - locks[0] | |
print("fallthrough") | |
return None | |
def release(self, lock): | |
self.etcd.rem(lock) | |
def __str__(self): | |
return str(self.etcd) | |
class Tracker: | |
def __init__(self, count): | |
self.multilock = MultiLock(count) | |
self.count = count | |
self.locks = set() | |
def get(self): | |
lock = self.multilock.get() | |
print(lock) | |
if lock is None: | |
print(self.locks, "\n") | |
if len(self.locks) != self.count: | |
raise RuntimeError("Lock failed when expected to succeed") | |
elif not (0 <= lock < self.count): | |
print(self.locks, "\n") | |
raise RuntimeError("Invalid lock number") | |
elif lock in self.locks: | |
print(self.locks, "\n") | |
raise RuntimeError("Duplicate lock") | |
else: | |
self.locks.add(lock) | |
print(self.locks, "\n") | |
def rem(self): | |
if self.locks: | |
lock = self.locks.pop() | |
self.multilock.release(lock) | |
print("rem") | |
print(self.locks, "\n") | |
def main(): | |
locks = Tracker(3) | |
commands = [] | |
while True: | |
commands.append(random.choice([locks.get, locks.get, locks.rem])) | |
commands[-1]() | |
if __name__ == "__main__": | |
main() | |
""" | |
+ - max min % * % () | |
count value index offset 0 1 2 | |
3 1,2, 0,1, 0,1 of ones with same value | |
""" | |
""" | |
Two locks | |
get -> [1, 1] -> lock 0 | |
get -> [2, 2] -> lock 1 | |
get -> [3, 3] -> fail | |
del 0 -> [0, 3] | |
get -> [1, 4] -> lock 0 | |
""" | |
""" | |
Three locks | |
get -> [1, 1, 1] -> lock 0 | |
get -> [2, 2, 2] -> lock 1 | |
get -> [3, 3, 3] -> lock 2 | |
del 0 -> [0, 3, 3] | |
del 1 -> [0, 0, 3] | |
get -> [1, 1, 4] -> lock 0 | |
get -> [2, 2, 4] -> lock 1 | |
""" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment