lib/blocks/block.rb in bake-toolkit-2.34.3 vs lib/blocks/block.rb in bake-toolkit-2.34.4
- old
+ new
@@ -294,103 +294,101 @@
rescue ErrNoWaitingThread
end
end
end
- def execute_in_thread(method)
- if method == :execute
- @@mutex.synchronize do
- Block::waitForFreeThread()
- return if blockAbort?(true)
+ def execute_in_thread(steps)
+ @@mutex.synchronize do
+ Block::waitForFreeThread()
+ return if blockAbort?(true)
- @@threads << Thread.new(Thread.current[:stdout], Thread.current[:errorStream]) { |outStr, errStr|
- STDOUT.puts "DEBUG_THREADS: Started: #{Thread.current.object_id} (#{@projectName}, #{@config.name})" if Bake.options.debug_threads
- Thread.current[:stdout] = outStr
- Thread.current[:errorStream] = errStr
- exceptionOccured = false
- begin
- yield
- exceptionOccured = true
- rescue Bake::SystemCommandFailed => scf # normal compilation error
- rescue SystemExit => exSys
- rescue Exception => ex1
- if not Bake::IDEInterface.instance.get_abort
- SyncOut.mutex.synchronize do
- Bake.formatter.printError("Error: #{ex1.message}")
- puts ex1.backtrace if Bake.options.debug
- end
+ tmpstdout = Thread.current[:tmpStdout].nil? ? nil : Thread.current[:tmpStdout].dup
+ @@threads << Thread.new(Thread.current[:stdout], Thread.current[:errorStream], tmpstdout, steps) { |outStr, errStr, tmpStdout, steps|
+ STDOUT.puts "DEBUG_THREADS: Started: #{Thread.current.object_id} (#{@projectName}, #{@config.name})" if Bake.options.debug_threads
+ Thread.current[:stdout] = outStr
+ Thread.current[:errorStream] = errStr
+ Thread.current[:tmpStdout] = tmpStdout
+ Thread.current[:steps] = steps
+ exceptionOccured = false
+ begin
+ yield
+ exceptionOccured = true
+ rescue Bake::SystemCommandFailed => scf # normal compilation error
+ rescue SystemExit => exSys
+ rescue Exception => ex1
+ if not Bake::IDEInterface.instance.get_abort
+ SyncOut.mutex.synchronize do
+ Bake.formatter.printError("Error: #{ex1.message}")
+ puts ex1.backtrace if Bake.options.debug
end
end
- if !exceptionOccured
- @result = false
- @@delayed_result = false
- end
- STDOUT.puts "DEBUG_THREADS: Stopped: #{Thread.current.object_id} (#{@projectName}, #{@config.name})" if Bake.options.debug_threads
- }
+ end
+ if !exceptionOccured
+ @result = false
+ @@delayed_result = false
+ end
+ STDOUT.puts "DEBUG_THREADS: Stopped: #{Thread.current.object_id} (#{@projectName}, #{@config.name})" if Bake.options.debug_threads
+ }
- Block::waitForFreeThread()
- return if blockAbort?(true)
- end
- else
- yield
+ Block::waitForFreeThread()
+ return if blockAbort?(true)
end
raise AbortException.new if Bake::IDEInterface.instance.get_abort
end
def blockAbort?(res)
((not res) || !@@delayed_result) and Bake.options.stopOnFirstError or Bake::IDEInterface.instance.get_abort
end
+ def independent?(method, step)
+ method == :execute && (Library === step || Compile === step ||
+ (CommandLine === step && step.config.independent) ||
+ (Makefile === step && step.config.independent))
+ end
+
def callSteps(method)
@config.writeEnvVars()
Thread.current[:lastCommand] = nil
- preSteps.each do |step|
- Blocks::Block::waitForAllThreads()
- @result = executeStep(step, method) if @result
- return @result if blockAbort?(@result)
- end unless @prebuild
+ allSteps = (preSteps + mainSteps + postSteps)
- threadableSteps = mainSteps.select { |step| method == :execute && (Library === step || Compile === step) }
- nonThreadableSteps = mainSteps.select { |step| method != :execute || !(Library === step || Compile === step) }
+ # check if we have to delay the output (if the last step of this block is not in a thread)
+ # todo: sync output if commandline and makefile!!!!!!!!!!!!!!!!!!!
+ @outputStep = nil
+ allSteps.each { |step| @outputStep = independent?(method, step) ? step : nil }
- @outputInMainThread = nonThreadableSteps.any?{ |step| !@prebuild || (Library === step) } ||
- postSteps.length > 0 ||
- (threadableSteps.length == 0 && preSteps.length > 0)
-
- execute_in_thread(method) {
- begin
- threadableSteps.each do |step|
- if !@prebuild || (Library === step)
- Multithread::Jobs.incThread() if Library === step
- begin
- @result = executeStep(step, method) if @result
- ensure
- Multithread::Jobs.decThread() if Library === step
- end
- @@delayed_result &&= @result
- end
- break if blockAbort?(@result)
- end
- ensure
- SyncOut.stopStream(@result) if !@outputInMainThread
+ while !allSteps.empty?
+ parallel = []
+ while allSteps.first && independent?(method, allSteps.first)
+ parallel << allSteps.shift
end
- } if !threadableSteps.empty?
- nonThreadableSteps.each do |step|
- if !@prebuild || (Library === step)
+ if parallel.length > 0
+ execute_in_thread(parallel) {
+ lastStep = Thread.current[:steps].last
+ begin
+ Thread.current[:steps].each do |step|
+ Multithread::Jobs.incThread() if !Compile === step
+ begin
+ @result = executeStep(step, :execute) if @result
+ ensure
+ Multithread::Jobs.decThread() if !Compile === step
+ end
+ @@delayed_result &&= @result
+ break if blockAbort?(@result)
+ end
+ ensure
+ SyncOut.stopStream(@result) if lastStep == @outputStep if Bake.options.syncedOutput
+ end
+ }
+ else
+ step = allSteps.shift
Blocks::Block::waitForAllThreads()
@result = executeStep(step, method) if @result
end
return @result if blockAbort?(@result)
end
- postSteps.each do |step|
- Blocks::Block::waitForAllThreads()
- @result = executeStep(step, method) if @result
- return @result if blockAbort?(@result)
- end unless @prebuild
-
return @result
end
def execute
if (@inDeps)
@@ -412,11 +410,11 @@
Bake::IDEInterface.instance.set_build_info(@projectName, @configName)
begin
SyncOut.mutex.synchronize do
- @outputInMainThread = true
+ @outputStep = nil
SyncOut.startStream() if Bake.options.syncedOutput
if Bake.options.verbose >= 2 || isBuildBlock? || @prebuild
typeStr = "Building"
if @prebuild
typeStr = "Using"
@@ -435,14 +433,16 @@
puts "Project path: #{@projectDir}" if Bake.options.projectPaths
end
@result = callSteps(:execute)
ensure
- if @outputInMainThread
- SyncOut.stopStream(@result)
- else
- SyncOut.discardStreams()
+ if Bake.options.syncedOutput
+ if !@outputStep
+ SyncOut.stopStream(@result)
+ else
+ SyncOut.discardStreams()
+ end
end
end
return (depResult && @result)# && @@delayed_result)
@@ -483,10 +483,10 @@
end
cleanSteps.each do |step|
@result = executeStep(step, :cleanStep) if @result
return false if not @result and Bake.options.stopOnFirstError
- end unless @prebuild
+ end
return (depResult && @result)
end
def self.init_threads()
\ No newline at end of file