Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Unified Diff: gclient_utils.py

Issue 3107009: Move ExecutionQueue and WorkItem to gclient_utils.py (Closed)
Patch Set: Update unit test Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gclient.py ('k') | tests/gclient_utils_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gclient_utils.py
diff --git a/gclient_utils.py b/gclient_utils.py
index 5fd2ef27a7f9fc7da14ca6683792d233574c482c..c530f4cb4cd79078635de9fe26a0912023e426a0 100644
--- a/gclient_utils.py
+++ b/gclient_utils.py
@@ -22,6 +22,7 @@ import stat
import subprocess
import sys
import time
+import threading
import xml.dom.minidom
import xml.parsers.expat
@@ -363,3 +364,109 @@ def GetGClientRootAndEntries(path=None):
execfile(config_path, env)
config_dir = os.path.dirname(config_path)
return config_dir, env['entries']
+
+
+class WorkItem(object):
+ """One work item."""
+ # A list of string, each being a WorkItem name.
+ requirements = []
+ # A unique string representing this work item.
+ name = None
+
+ def run(self):
+ pass
+
+
+class ExecutionQueue(object):
+ """Dependencies sometime needs to be run out of order due to From() keyword.
+
+ This class manages that all the required dependencies are run before running
+ each one.
+
+ Methods of this class are multithread safe.
+ """
+ def __init__(self, progress):
+ self.lock = threading.Lock()
+ # List of WorkItem, Dependency inherits from WorkItem.
+ self.queued = []
+ # List of strings representing each Dependency.name that was run.
+ self.ran = []
+ # List of items currently running.
+ self.running = []
+ self.progress = progress
+ if self.progress:
+ self.progress.update()
+
+ def enqueue(self, d):
+ """Enqueue one Dependency to be executed later once its requirements are
+ satisfied.
+ """
+ assert isinstance(d, WorkItem)
+ try:
+ self.lock.acquire()
+ self.queued.append(d)
+ total = len(self.queued) + len(self.ran) + len(self.running)
+ finally:
+ self.lock.release()
+ if self.progress:
+ self.progress._total = total + 1
+ self.progress.update(0)
+
+ def flush(self, *args, **kwargs):
+ """Runs all enqueued items until all are executed."""
+ while self._run_one_item(*args, **kwargs):
+ pass
+ queued = []
+ running = []
+ try:
+ self.lock.acquire()
+ if self.queued:
+ queued = self.queued
+ self.queued = []
+ if self.running:
+ running = self.running
+ self.running = []
+ finally:
+ self.lock.release()
+ if self.progress:
+ self.progress.end()
+ if queued:
+ raise gclient_utils.Error('Entries still queued: %s' % str(queued))
+ if running:
+ raise gclient_utils.Error('Entries still queued: %s' % str(running))
+
+ def _run_one_item(self, *args, **kwargs):
+ """Removes one item from the queue that has all its requirements completed
+ and execute it.
+
+ Returns False if no item could be run.
+ """
+ i = 0
+ d = None
+ try:
+ self.lock.acquire()
+ while i != len(self.queued) and not d:
+ d = self.queued.pop(i)
+ for r in d.requirements:
+ if not r in self.ran:
+ self.queued.insert(i, d)
+ d = None
+ break
+ i += 1
+ if not d:
+ return False
+ self.running.append(d)
+ finally:
+ self.lock.release()
+ d.run(*args, **kwargs)
+ try:
+ self.lock.acquire()
+ assert not d.name in self.ran
+ if not d.name in self.ran:
+ self.ran.append(d.name)
+ self.running.remove(d)
+ if self.progress:
+ self.progress.update(1)
+ finally:
+ self.lock.release()
+ return True
« no previous file with comments | « gclient.py ('k') | tests/gclient_utils_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698