From 8ca952cbd5090395374516b16378de6d2b9aa67b Mon Sep 17 00:00:00 2001 From: stevenknight Date: Wed, 27 Nov 2002 16:51:08 +0000 Subject: [PATCH] Serialize calls to Node.prepare() (Anthony Roach) git-svn-id: http://scons.tigris.org/svn/scons/trunk@509 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- src/engine/SCons/Job.py | 4 +- src/engine/SCons/JobTests.py | 22 +++++++++- src/engine/SCons/Script/__init__.py | 64 +++++++++++++++-------------- src/engine/SCons/Taskmaster.py | 15 +++++-- src/engine/SCons/TaskmasterTests.py | 8 ++++ 5 files changed, 76 insertions(+), 37 deletions(-) diff --git a/src/engine/SCons/Job.py b/src/engine/SCons/Job.py index 21f4617a..c06cf231 100644 --- a/src/engine/SCons/Job.py +++ b/src/engine/SCons/Job.py @@ -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: diff --git a/src/engine/SCons/JobTests.py b/src/engine/SCons/JobTests.py index 55e5f0f5..c97ad55d 100644 --- a/src/engine/SCons/JobTests.py +++ b/src/engine/SCons/JobTests.py @@ -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) diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index dd44621e..57d0eeb0 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -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 diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index bf2d918c..a32def4d 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -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): diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py index f3bf1822..23d7e0ad 100644 --- a/src/engine/SCons/TaskmasterTests.py +++ b/src/engine/SCons/TaskmasterTests.py @@ -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() -- 2.26.2