#! /usr/bin/env python # the Task class attribute "maxjobs" was deprecated in Waf 1.6 # limiting the amount of jobs is commonly done by adding sequential # barriers (build groups) or even locks. But the feature might be # necessary in very few corner cases # in the following examples, remember that the method run() is the only # one actually executed by threads def configure(conf): pass def build(bld): bld.jobs = 4 bld(source='foo.a bar.a truc.a') import threading, time from waflib.TaskGen import extension from waflib import Task @extension('.a') def process_a_files(self, node): self.create_task('a_to_b', node, node.change_ext('b')) self.create_task('b_to_c', node.change_ext('b'), node.change_ext('c')) class a_to_b(Task.Task): # classical way, using a lock or a semaphore # in this case, at most 2 tasks can execute at a time # this may lead to build starvation, as may tasks can get stalled while processing lock = threading.Semaphore(2) def run(self): try: self.lock.acquire() for i in range(5): print('a to b %r' % id(self)) time.sleep(1) self.outputs[0].write('done') finally: self.lock.release() class b_to_c(Task.Task): # this will enable other tasks to run concurrently, and without additional locks active = [] def runnable_status(self): ret = Task.Task.runnable_status(self) if ret == Task.RUN_ME: self.active = [tsk for tsk in self.active if not tsk.hasrun] if len(self.active) < 2: self.active.append(self) else: # too many tasks are still active, wait ret = Task.ASK_LATER return ret def run(self): for i in range(5): print('b to c %r' % id(self)) time.sleep(1) self.outputs[0].write('done')