Initial step into making Dependency thread safe

R=dpranke@chromium.org
BUG=
TEST=


Review URL: http://codereview.chromium.org/7892034

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@101135 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/gclient_utils.py b/gclient_utils.py
index 89050b7..2402519 100644
--- a/gclient_utils.py
+++ b/gclient_utils.py
@@ -456,19 +456,45 @@
   return config_dir, env['entries']
 
 
+def lockedmethod(method):
+  """Method decorator that holds self.lock for the duration of the call."""
+  def inner(self, *args, **kwargs):
+    try:
+      try:
+        self.lock.acquire()
+      except KeyboardInterrupt:
+        print >> sys.stderr, 'Was deadlocked'
+        raise
+      return method(self, *args, **kwargs)
+    finally:
+      self.lock.release()
+  return inner
+
+
 class WorkItem(object):
   """One work item."""
-  def __init__(self):
+  def __init__(self, name):
     # A list of string, each being a WorkItem name.
-    self.requirements = []
+    self._requirements = set()
     # A unique string representing this work item.
-    self.name = None
+    self._name = name
+    self.lock = threading.RLock()
 
+  @lockedmethod
   def run(self, work_queue):
     """work_queue is passed as keyword argument so it should be
     the last parameters of the function when you override it."""
     pass
 
+  @property
+  def name(self):
+    return self._name
+
+  @property
+  @lockedmethod
+  def requirements(self):
+    return tuple(self._requirements)
+
 
 class ExecutionQueue(object):
   """Runs a set of WorkItem that have interdependencies and were WorkItem are