Serialize calls to Node.prepare() (Anthony Roach)
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 27 Nov 2002 16:51:08 +0000 (16:51 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Wed, 27 Nov 2002 16:51:08 +0000 (16:51 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@509 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/engine/SCons/Job.py
src/engine/SCons/JobTests.py
src/engine/SCons/Script/__init__.py
src/engine/SCons/Taskmaster.py
src/engine/SCons/TaskmasterTests.py

index 21f4617a4b180f1f0c478da64e5cb4be9442b5e2..c06cf2310d64fb4950ee9077e0bd1f332447ca03 100644 (file)
@@ -123,6 +123,7 @@ class Serial:
                 break
 
             try:
+                task.prepare()
                 task.execute()
             except KeyboardInterrupt:
                 raise
@@ -243,8 +244,9 @@ class Parallel:
                 if task == None:
                     break
 
-                cv.release()
                 try:
+                    task.prepare()
+                    cv.release()
                     try:
                         task.execute()
                     finally:
index 55e5f0f5a09b1aeb9856d14e9ed6e65b452445f0..c97ad55de61d4c8ba3e6791546c6901e1653ef11 100644 (file)
@@ -59,8 +59,15 @@ class Task:
         self.i = i
         self.taskmaster = taskmaster
         self.was_executed = 0
+        self.was_prepared = 0
+        
+    def prepare(self):
+        self.was_prepared = 1
         
     def execute(self):
+        self.taskmaster.test_case.failUnless(self.was_prepared,
+                                  "the task wasn't prepared")
+        
         self.taskmaster.guard.acquire()
         self.taskmaster.begin_list.append(self.i)
         self.taskmaster.guard.release()
@@ -78,6 +85,8 @@ class Task:
     def executed(self):
         self.taskmaster.num_executed = self.taskmaster.num_executed + 1
 
+        self.taskmaster.test_case.failUnless(self.was_prepared,
+                                  "the task wasn't prepared")
         self.taskmaster.test_case.failUnless(self.was_executed,
                                   "the task wasn't really executed")
         self.taskmaster.test_case.failUnless(self.__class__ is Task,
@@ -86,12 +95,19 @@ class Task:
     def failed(self):
         self.taskmaster.num_failed = self.taskmaster.num_failed + 1
         self.taskmaster.stop = 1
+        self.taskmaster.test_case.failUnless(self.was_prepared,
+                                  "the task wasn't prepared")
+
 
 class ExceptionTask:
     """A dummy task class for testing purposes."""
 
     def __init__(self, i, taskmaster):
         self.taskmaster = taskmaster
+        self.was_prepared = 0
+
+    def prepare(self):
+        self.was_prepared = 1
         
     def execute(self):
         raise "exception"
@@ -99,6 +115,8 @@ class ExceptionTask:
     def executed(self):
         self.taskmaster.num_executed = self.taskmaster.num_executed + 1
 
+        self.taskmaster.test_case.failUnless(self.was_prepared,
+                                  "the task wasn't prepared")
         self.taskmaster.test_case.failUnless(self.was_executed,
                                   "the task wasn't really executed")
         self.taskmaster.test_case.failUnless(self.__class__ is Task,
@@ -107,6 +125,8 @@ class ExceptionTask:
     def failed(self):
         self.taskmaster.num_failed = self.taskmaster.num_failed + 1
         self.taskmaster.stop = 1
+        self.taskmaster.test_case.failUnless(self.was_prepared,
+                                  "the task wasn't prepared")
 
 class Taskmaster:
     """A dummy taskmaster class for testing the job classes."""
@@ -147,7 +167,7 @@ class Taskmaster:
 
     def all_tasks_are_iterated(self):
         return self.num_iterated == self.num_tasks
-    
+
     def is_blocked(self):
         # simulate blocking tasks
         return self.num_iterated - self.num_executed >= max(num_jobs/2, 2)
index dd44621e144b30cea72f6677157a880dad43ae1a..57d0eeb0894cd4933a78afbdf0bbf32463a61cb4 100644 (file)
@@ -77,37 +77,14 @@ class BuildTask(SCons.Taskmaster.Task):
             if self.top:
                 display('scons: "%s" is up to date.' % str(self.targets[0]))
         else:
-            try:
-                self.targets[0].prepare()
-                if print_time:
-                    start_time = time.time()
-                self.targets[0].build()
-                if print_time:
-                    finish_time = time.time()
-                    global command_time
-                    command_time = command_time+finish_time-start_time
-                    print "Command execution time: %f seconds"%(finish_time-start_time)
-   
-            except BuildError, e:
-                sys.stderr.write("scons: *** [%s] %s\n" % (e.node, e.errstr))
-                if e.errstr == 'Exception':
-                    traceback.print_exception(e.args[0], e.args[1],
-                                              e.args[2])
-                raise
-            except UserError, e:
-                # We aren't being called out of a user frame, so
-                # don't try to walk the stack, just print the error.
-                sys.stderr.write("\nSCons error: %s\n" % e)
-                raise
-            except StopError, e:
-                s = str(e)
-                if not keep_going_on_error:
-                    s = s + '  Stop.'
-                sys.stderr.write("scons: *** %s\n" % s)
-                raise
-            except:
-                sys.stderr.write("scons: *** %s\n" % sys.exc_value)
-                raise
+            if print_time:
+                start_time = time.time()
+            self.targets[0].build()
+            if print_time:
+                finish_time = time.time()
+                global command_time
+                command_time = command_time+finish_time-start_time
+                print "Command execution time: %f seconds"%(finish_time-start_time)
 
     def executed(self):
         SCons.Taskmaster.Task.executed(self)
@@ -124,6 +101,25 @@ class BuildTask(SCons.Taskmaster.Task):
 
     def failed(self):
         global exit_status
+
+        e = sys.exc_value
+        if sys.exc_type == BuildError:
+            sys.stderr.write("scons: *** [%s] %s\n" % (e.node, e.errstr))
+            if e.errstr == 'Exception':
+                traceback.print_exception(e.args[0], e.args[1],
+                                          e.args[2])
+        elif sys.exc_type == UserError:
+            # We aren't being called out of a user frame, so
+            # don't try to walk the stack, just print the error.
+            sys.stderr.write("\nSCons error: %s\n" % e)
+        elif sys.exc_type == StopError:
+            s = str(e)
+            if not keep_going_on_error:
+                s = s + '  Stop.'
+            sys.stderr.write("scons: *** %s\n" % s)
+        else:
+            sys.stderr.write("scons: *** %s\n" % e)
+        
         if ignore_errors:
             SCons.Taskmaster.Task.executed(self)
         elif keep_going_on_error:
@@ -152,8 +148,14 @@ class CleanTask(SCons.Taskmaster.Task):
 
     execute = remove
 
+    def prepare(self):
+        pass
+
 class QuestionTask(SCons.Taskmaster.Task):
     """An SCons task for the -q (question) option."""
+    def prepare(self):
+        pass
+    
     def execute(self):
         if self.targets[0].get_state() != SCons.Node.up_to_date:
             global exit_status
index bf2d918c63bae22df1809e71c9491de33a626e6b..a32def4d52edd6b5ce0de3211cceb42b8f843dd9 100644 (file)
@@ -60,12 +60,19 @@ class Task:
         self.top = top
         self.node = node
 
-    def execute(self):
-        # This methods is called from multiple threads in
-        # a parallel build, so only do thread safe stuff here.
-        # Do thread unsafe stuff in executed() or failed().
+
+    def prepare(self):
+        """Called just before the task is executed."""
         if self.targets[0].get_state() != SCons.Node.up_to_date:
             self.targets[0].prepare()
+
+    def execute(self):
+        """Called to execute the task.
+        
+        This methods is called from multiple threads in
+        a parallel build, so only do thread safe stuff here.
+        Do thread unsafe stuff in prepare(), executed() or failed()."""
+        if self.targets[0].get_state() != SCons.Node.up_to_date:
             self.targets[0].build()
 
     def get_target(self):
index f3bf1822e7089b85906efc3537f64d3ffaba687c..23d7e0ad215b6c7bdd2c4b5c8a09d147dc5824f4 100644 (file)
@@ -124,6 +124,7 @@ class TaskmasterTestCase(unittest.TestCase):
         n1 = Node("n1")
         tm = SCons.Taskmaster.Taskmaster([n1, n1])
         t = tm.next_task()
+        t.prepare()
         t.execute()
         t = tm.next_task()
         assert t == None
@@ -135,16 +136,19 @@ class TaskmasterTestCase(unittest.TestCase):
         tm = SCons.Taskmaster.Taskmaster([n3])
 
         t = tm.next_task()
+        t.prepare()
         t.execute()
         assert built_text == "n1 built", built_text
         t.executed()
 
         t = tm.next_task()
+        t.prepare()
         t.execute()
         assert built_text == "n2 built", built_text
         t.executed()
 
         t = tm.next_task()
+        t.prepare()
         t.execute()
         assert built_text == "n3 built", built_text
         t.executed()
@@ -176,16 +180,19 @@ class TaskmasterTestCase(unittest.TestCase):
                                          tasker = MyTask, calc = MyCalc())
 
         t = tm.next_task()
+        t.prepare()
         t.execute()
         assert built_text == "n1 up-to-date", built_text
         t.executed()
 
         t = tm.next_task()
+        t.prepare()
         t.execute()
         assert built_text == "n2 up-to-date", built_text
         t.executed()
 
         t = tm.next_task()
+        t.prepare()
         t.execute()
         assert built_text == "n3 up-to-date top", built_text
         t.executed()
@@ -372,6 +379,7 @@ class TaskmasterTestCase(unittest.TestCase):
         
         tm = SCons.Taskmaster.Taskmaster([n3])
         t = tm.next_task()
+        t.prepare()
         t.execute()
         assert built_text == "n1 built", built_text
         t.executed()