From fdd82f7ac42557c82203bca5ccff350740978cd0 Mon Sep 17 00:00:00 2001 From: shortcutme Date: Mon, 20 Nov 2017 03:13:58 +0100 Subject: [PATCH] Rev3146, Limit noparallel queue to one call --- src/Config.py | 2 +- src/Test/TestNoparallel.py | 45 +++++++++++++++++++++++++++++--------- src/util/Noparallel.py | 8 +++++-- 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/Config.py b/src/Config.py index b795d696..33b368c3 100644 --- a/src/Config.py +++ b/src/Config.py @@ -10,7 +10,7 @@ class Config(object): def __init__(self, argv): self.version = "0.6.0" - self.rev = 3144 + self.rev = 3146 self.argv = argv self.action = None self.config_file = "zeronet.conf" diff --git a/src/Test/TestNoparallel.py b/src/Test/TestNoparallel.py index 596c6b23..1f1d0140 100644 --- a/src/Test/TestNoparallel.py +++ b/src/Test/TestNoparallel.py @@ -68,14 +68,38 @@ class TestNoparallel: def testQueue(self): obj1 = ExampleClass() - threads = [ - gevent.spawn(obj1.countQueue), - gevent.spawn(obj1.countQueue), - gevent.spawn(obj1.countQueue) - ] - gevent.joinall(threads) + gevent.spawn(obj1.countQueue, num=10) + gevent.spawn(obj1.countQueue, num=10) + gevent.spawn(obj1.countQueue, num=10) - assert obj1.counted == 15 # Calls should be executed sequentially + time.sleep(0.3) + assert obj1.counted == 20 # No multi-queue supported + + obj2 = ExampleClass() + gevent.spawn(obj2.countQueue, num=10) + gevent.spawn(obj2.countQueue, num=10) + + time.sleep(0.15) # Call 1 finished, call 2 still working + assert 10 < obj2.counted < 20 + + gevent.spawn(obj2.countQueue, num=10) + time.sleep(0.20) + + assert obj2.counted == 30 + + + + + def testQueueOverload(self): + obj1 = ExampleClass() + + threads = [] + for i in range(10000): + thread = gevent.spawn(obj1.countQueue, num=5) + threads.append(thread) + + gevent.joinall(threads) + assert obj1.counted == 5 * 2 # Only called twice def testIgnoreClass(self): obj1 = ExampleClass() @@ -90,8 +114,9 @@ class TestNoparallel: ] s = time.time() gevent.joinall(threads) - assert obj1.counted == 15 - assert obj2.counted == 10 + + # Queue limited to 2 calls (very call takes counts to 5 and takes 0.05 sec) + assert obj1.counted + obj2.counted == 10 taken = time.time() - s - assert taken >= 0.25 # Every count takes 0.05sec + assert 0.11 > taken >= 0.1 # 2 * 0.05s count = ~0.1s diff --git a/src/util/Noparallel.py b/src/util/Noparallel.py index 0ae9da68..9f9d3132 100644 --- a/src/util/Noparallel.py +++ b/src/util/Noparallel.py @@ -8,6 +8,7 @@ class Noparallel(object): # Only allow function running once in same time self.threads = {} self.blocking = blocking # Blocking: Acts like normal function else thread returned self.queue = queue + self.queued = False self.ignore_args = ignore_args self.ignore_class = ignore_class @@ -20,11 +21,14 @@ class Noparallel(object): # Only allow function running once in same time else: key = (func, tuple(args), str(kwargs)) # Unique key for function including parameters if key in self.threads: # Thread already running (if using blocking mode) + if self.queue: + self.queued = True thread = self.threads[key] if self.blocking: thread.join() # Blocking until its finished - if self.queue: - return wrapper(*args, **kwargs) # Run again + if self.queued: + self.queued = False + return wrapper(*args, **kwargs) # Run again after the end else: return thread.value # Return the value