ó âqLc@s dZdZddlZddlZddlZddlZdZdZ dZ de fd„ƒYZ de fd „ƒYZ d e fd „ƒYZyddlZddlZWnek r¿nFXd ejfd „ƒYZde fd„ƒYZde fd„ƒYZdS(s»SCons.Job This module defines the Serial and Parallel classes that execute tasks to complete a build. The Jobs class provides a higher level interface to start, stop, and wait on jobs. s6src/engine/SCons/Job.py 5023 2010/06/14 22:05:46 sconsiÿÿÿÿNisBuild interrupted.tInterruptStatecBs#eZd„Zd„Zd„ZRS(cCs t|_dS(N(tFalset interrupted(tself((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyt__init__8scCs t|_dS(N(tTrueR(R((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pytset;scCs|jS(N(R(R((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyt__call__>s(t__name__t __module__RRR(((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyR7s  tJobscBsAeZdZd„Zd„d„Zd„Zd„Zd„ZRS(s~An instance of this class initializes N jobs, and provides methods for starting, stopping, and waiting on all N jobs. cCs—d|_|dkrit}|dkr0t}ny"t|||ƒ|_||_Wqitk reqiXn|jdkr“t|ƒ|_d|_ndS(só create 'num' jobs using the given taskmaster. If 'num' is 1 or less, then a serial job will be used, otherwise a parallel job with 'num' worker threads will be used. The 'num_jobs' attribute will be set to the actual number of jobs allocated. If more than one job is requested but the Parallel class can't do it, it gets reset to 1. Wrapping interfaces that care should check the value of 'num_jobs' after initialization. iN(tNonetjobtexplicit_stack_sizetdefault_stack_sizetParalleltnum_jobst NameErrortSerial(Rtnumt taskmastert stack_size((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyRGs      cCsdS(N(R (((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pytdscCs4|jƒz|jjƒWd|ƒ|jƒXdS(spRun the jobs. postfunc() will be invoked after the jobs has run. It will be invoked even if the jobs are interrupted by a keyboard interrupt (well, in fact by a signal such as either SIGINT, SIGTERM or SIGHUP). The execution of postfunc() is protected against keyboard interrupts and is guaranteed to run to completion.N(t_setup_sig_handlerR tstartt_reset_sig_handler(Rtpostfunc((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pytrunds cCs |jjƒS(s6Returns whether the jobs were interrupted by a signal.(R R(R((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pytwere_interruptedtscCsy|tjƒd„}tjtj|ƒ|_tjtj|ƒ|_ytjtj|ƒ|_Wnt k rtnXdS(s…Setup an interrupt handler so that SCons can shutdown cleanly in various conditions: a) SIGINT: Keyboard interrupt b) SIGTERM: kill or system shutdown c) SIGHUP: Controlling shell exiting We handle all of these cases by stopping the taskmaster. It turns out that it very difficult to stop the build process by throwing asynchronously an exception such as KeyboardInterrupt. For example, the python Condition variables (threading.Condition) and queue's do not seem to asynchronous-exception-safe. It would require adding a whole bunch of try/finally block and except KeyboardInterrupt all over the place. Note also that we have to be careful to handle the case when SCons forks before executing another process. In that case, we want the child to exit immediately. cSsFtjƒ|kr5|jjjƒ|jjjƒn tjdƒdS(Ni(tostgetpidR RtstopRRt_exit(tsignumtstackRt parentpid((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pythandlersN( RRtsignaltSIGINTt old_siginttSIGTERMt old_sigtermtSIGHUPt old_sighuptAttributeError(RR$((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyRxs cCs^tjtj|jƒtjtj|jƒytjtj|jƒWntk rYnXdS(sfRestore the signal handlers to their previous state (before the call to _setup_sig_handler().N(R%R&R'R(R)R*R+R,(R((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyR›s  (RR t__doc__RRRRR(((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyR Bs    #RcBs eZdZd„Zd„ZRS(s÷This class is used to execute tasks in series, and is more efficient than Parallel, but is only appropriate for non-parallel builds. Only one instance of this class should be in existence at a time. This class is not thread safe. cCs||_tƒ|_dS(sŽCreate a new serial job given a taskmaster. The taskmaster's next_task() method should return the next task that needs to be executed, or None if there are no more tasks. The taskmaster's executed() method will be called for each task when it is successfully executed or failed() will be called if it failed to execute (e.g. execute() raised an exception).N(RRR(RR((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyR®s cCsÜxÈtrÊ|jjƒ}|dkr(Pny'|jƒ|jƒrN|jƒnWna|jƒr›y#tj j |j ddt ƒ‚Wq¥|j ƒq¥Xn |j ƒ|jƒn X|jƒ|jƒqW|jjƒdS(sîStart the job. This will begin pulling tasks from the taskmaster and executing them, and return when there are no more tasks. If a task fails to execute (i.e. execute() raises an exception), then the job will stop.iterrstrN(RRt next_taskR tpreparet needs_executetexecuteRtSConstErrorst BuildErrorttargetst interrupt_msgt exception_settfailedtexecutedt postprocesstcleanup(Rttask((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyRºs(        (RR R-RR(((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyR¦s tWorkercBs eZdZd„Zd„ZRS(sÙA worker thread waits on a task to be posted to its request queue, dequeues the task, executes it, and posts a tuple including the task and a boolean indicating whether the task executed successfully. cCsFtjj|ƒ|jdƒ||_||_||_|jƒdS(Ni(t threadingtThreadRt setDaemont requestQueuet resultsQueueRR(RRBRCR((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyRìs     cCs¢x›tr|jjƒ}|dkr(Pny<|jƒrYtjj|jddt ƒ‚n|j ƒWn|j ƒt }nXt}|j j||fƒqWdS(NiR.(RRBtgetR RR3R4R5R6R7R2R8RRCtput(RR=tok((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyRôs      (RR R-RR(((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyR>çs t ThreadPoolcBs;eZdZd„Zd„Zd„Zd„Zd„ZRS(sCThis class is responsible for spawning and managing worker threads.c Cs0tjdƒ|_tjdƒ|_ytj|dƒ}Wn‡tk r‰}tdk rÅd|j d}t j j t j j |ƒqÅn<tk rÄ}dt|ƒ}t j j t j j |ƒnXg|_x<t|ƒD].}t|j|j|ƒ}|jj|ƒqÛWdtƒkr,tj|ƒndS(sÑCreate the request and reply queues, and 'num' worker threads. One must specify the stack size of the worker threads. The stack size is specified in kilobytes. iisASetting stack size is unsupported by this version of Python: sSetting stack size failed: t prev_sizeN(tqueuetQueueRBRCR?RR,R R targsR3tWarningstwarntStackSizeWarningt ValueErrortstrtworkerstrangeR>tappendtlocals( RRRRRHtetmsgt_tworker((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyRs$  cCs|jj|ƒdS(sPut task into request queue.N(RBRE(RR=((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyRE-scCs |jjƒS(s8Remove and return a result tuple from the results queue.(RCRD(R((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyRD1scCs|jj|tfƒdS(N(RCRER(RR=((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pytpreparation_failed5scCsRx!|jD]}|jjdƒq Wx|jD]}|jdƒq.Wg|_dS(s} Shuts down the thread pool, giving each worker thread a chance to shut down gracefully. gð?N(RQRBRER tjoin(RRWRX((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyR<8s (RR R-RRERDRYR<(((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyRG s     RcBs eZdZd„Zd„ZRS(sºThis class is used to execute tasks in parallel, and is somewhat less efficient than Serial, but is appropriate for parallel builds. This class is thread safe. cCs:||_tƒ|_t|||jƒ|_||_dS(s°Create a new parallel job given a taskmaster. The taskmaster's next_task() method should return the next task that needs to be executed, or None if there are no more tasks. The taskmaster's executed() method will be called for each task when it is successfully executed or failed() will be called if the task failed to execute (i.e. execute() raised an exception). Note: calls to taskmaster are serialized, but calls to execute() on distinct tasks are not serialized, because that is the whole point of parallel jobs: they can execute multiple tasks simultaneously. N(RRRRGttptmaxjobs(RRRR((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyR\s  cCsšd}xstr{x¥||jkr¶|jjƒ}|dkr@Pny|jƒWn%|jƒ|jƒ|jƒqX|j ƒrŸ|j j |ƒ|d}q|j ƒ|jƒqW| rÉ| rÉPnx¬trw|j j ƒ\}}|d}|r|j ƒnP|jƒrJy#tjj|jddtƒ‚WqJ|jƒqJXn|jƒ|jƒ|j jjƒrÌPqÌqÌWq W|j jƒ|jjƒdS(súStart the job. This will begin pulling tasks from the taskmaster and executing them, and return when there are no more tasks. If a task fails to execute (i.e. execute() raises an exception), then the job will stop.iiR.N(RR\RR/R R0R8R9R;R1R[RER:RDRR3R4R5R6R7RCtemptyR<(RtjobsR=RF((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyRqsH                (RR R-RR(((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyRUs (R-t __revision__t SCons.compatR3RR%t SCons.ErrorsR R RR7tobjectRR RRIR?t ImportErrorR@R>RGR(((sY/home/als/proj/qrscanner/ext/qrscanner/zxing/scons/scons-local-2.0.0.final.0/SCons/Job.pyts&     d;  $J