wscript (2709B)
1 #! /usr/bin/env python 2 3 # The following example shows how several build processes can collaborate 4 # to stop spawning new processes when a special task of type K is executed 5 # this may be useful for link tasks for example 6 7 def options(opt): 8 opt.add_option('--loops', action='store', type='int', default=5, help='amount of cpu-intensive loops to perform') 9 10 def configure(conf): 11 busy = conf.path.find_node('look_busy.py').abspath() 12 conf.env.NOT_BUSY = ('%s 0' % busy).split() 13 conf.env.VERY_BUSY = ('%s %d' % (busy, conf.options.loops)).split() 14 15 def build(bld): 16 bld.link_limit = 1 17 bld.lockfile = bld.path.parent.make_node('busy_lock.txt').abspath() 18 for i in range(2): 19 for k in range(5): 20 bld(rule='${NOT_BUSY}', always=True) 21 22 bld(rule='${VERY_BUSY}', always=True, exclusive=True) 23 24 for k in range(10): 25 bld(rule='${NOT_BUSY}', always=True) 26 27 import os, fcntl, threading, errno, time 28 from waflib import Task 29 30 lock = threading.Lock() 31 32 def lock_maxjob(self): 33 # lock the file, telling other build processes to avoid spawining tasks during that time 34 while True: 35 try: 36 self.lockfd = os.open(self.generator.bld.lockfile, os.O_TRUNC | os.O_CREAT | os.O_RDWR) 37 fcntl.flock(self.lockfd, fcntl.LOCK_EX | fcntl.LOCK_NB) 38 except EnvironmentError as e: 39 if e.errno in (errno.EACCES, errno.EAGAIN): 40 time.sleep(0.3) 41 continue 42 raise 43 os.write(self.lockfd, "%d" % os.getpid()) 44 self.start_time = time.time() 45 break 46 47 def release_maxjob(self): 48 # release the lock file 49 print("> long task %d" % (time.time() - self.start_time)) 50 try: 51 os.remove(self.generator.bld.lockfile) 52 os.close(self.lockfd) 53 except OSError, e: 54 # of someone else has removed the lock... bad luck! but do not fail here 55 print "unexpected failure", e 56 pass 57 58 def wait_maxjob(self): 59 # wait on the lock file.. up to a certain limit 60 while True: 61 try: 62 ini = os.stat(self.generator.bld.lockfile).st_mtime 63 except OSError, e: 64 return 65 diff = time.time() - ini 66 if diff > 300: # stale lock file? wait 5 minutes 67 return 68 time.sleep(0.5) 69 70 # the method process is called by threads... 71 def process2(self): 72 73 if getattr(self.generator, 'exclusive', False): 74 lock.acquire() 75 try: 76 self.lock_maxjob() 77 finally: 78 lock.release() 79 else: 80 self.wait_maxjob() 81 82 ret = self.process_bound_maxjobs() 83 84 if getattr(self.generator, 'exclusive', False): 85 lock.acquire() 86 try: 87 self.release_maxjob() 88 finally: 89 lock.release() 90 return ret 91 92 def process(self): 93 try: 94 process2(self) 95 except Exception, e: 96 print type(e), e 97 98 Task.Task.process_bound_maxjobs = Task.Task.process 99 Task.Task.process = process 100 Task.Task.lock_maxjob = lock_maxjob 101 Task.Task.release_maxjob = release_maxjob 102 Task.Task.wait_maxjob = wait_maxjob 103