def test_thread_safety(self): # A Queue should be thread safe. This meanst that all entries that are # put in the queue must be returned, that no entry must be returned # twice and that the order must be respected. Also no deadlock must # ever occur. # To test, fire up a bunch of threads which each fire up a bunch of # fibers, and have the fibers do some random sleeps. Then let it run # and test the result. result = [] reference = [] lock = gruvi.Lock() def put_queue(tid, fid, count): for i in range(count): with lock: gruvi.sleep(random.randint(0, 2) / 1000) queue.put((tid, fid, count)) reference.append((tid, fid, count)) def get_queue(count): for i in range(count): with lock: result.append(queue.get()) def thread_put(tid, nfibers, count): fibers = [] for i in range(nfibers): fibers.append(gruvi.spawn(put_queue, tid, i, count)) for fib in fibers: fib.join() gruvi.get_hub().close() def thread_get(nfibers, count): fibers = [] for i in range(nfibers): fibers.append(gruvi.spawn(get_queue, count)) for fib in fibers: fib.join() gruvi.get_hub().close() queue = gruvi.Queue() threads = [] # 5 procuders and 5 consumers, each with 20 fibers for i in range(5): thread = threading.Thread(target=thread_put, args=(i, 20, 5)) thread.start() threads.append(thread) for i in range(5): thread = threading.Thread(target=thread_get, args=(20, 5)) thread.start() threads.append(thread) for thread in threads: thread.join() gruvi.sleep(0) # run callbacks self.assertEqual(len(result), 500) self.assertEqual(result, reference) # Within a (tid,fid) pair, the counts must be monotonic partial_sort = sorted(result, key=lambda el: (el[0], el[1])) full_sort = sorted(result, key=lambda el: (el[0], el[1], el[2])) self.assertEqual(partial_sort, full_sort)
def test_timeout(self): # Ensure that the timeout argument to acquire() works. hub = get_hub() lock = gruvi.RLock() sync = gruvi.Lock() def lock_rlock(): lock.acquire() sync.acquire() lock.release() # This needs a new fiber, as the same fiber *can* lock the same RLock twice. sync.acquire() fiber = gruvi.spawn(lock_rlock) gruvi.sleep(0) self.assertTrue(lock.locked()) t0 = hub.loop.now() self.assertFalse(lock.acquire(timeout=0.01)) t1 = hub.loop.now() # Internally the event loop uses timestamps with a 1ms granularity. So # allow for that. self.assertGreaterEqual(t1 - t0, 10) sync.release() fiber.join() self.assertFalse(lock._callbacks)
def test_timeout(self): # Ensure that the timeout argument to acquire() works. hub = get_hub() lock = gruvi.Lock() lock.acquire() t0 = hub.loop.now() self.assertFalse(lock.acquire(timeout=0.01)) t1 = hub.loop.now() self.assertGreater(t1 - t0, 10) self.assertFalse(lock._callbacks)
def test_non_blocking(self): # Ensure that the blocking argument to acquire() works. lock = gruvi.RLock() sync = gruvi.Lock() def lock_rlock(): lock.acquire() sync.acquire() lock.release() # This needs a new fiber, as the same fiber *can* lock the same RLock twice. sync.acquire() fiber = gruvi.spawn(lock_rlock) gruvi.sleep(0) self.assertTrue(lock.locked()) self.assertFalse(lock.acquire(blocking=False)) sync.release() fiber.join() self.assertFalse(lock._callbacks)
def mem_priorityqueue(self): self.add_result( sizeof(gruvi.PriorityQueue(), exclude=('_lock', )) + sizeof(gruvi.Lock()))
def mem_lifoqueue(self): self.add_result( sizeof(gruvi.LifoQueue(), exclude=('_lock', )) + sizeof(gruvi.Lock()))
def mem_lock(self): self.add_result(sizeof(gruvi.Lock()))
def test_non_blocking(self): # Ensure that the blocking argument to acquire() works. lock = gruvi.Lock() lock.acquire() self.assertFalse(lock.acquire(blocking=False)) self.assertFalse(lock._callbacks)