;ò «EFc@sídZdkZdkZdklZdkZdklZlZgZdfd„ƒYZdefd„ƒYZ defd „ƒYZ d „Z d efd „ƒYZ d efd„ƒYZ e ƒadfd„ƒYZd„Zd„ZdS(sThe tasks module provides a simple light-weight alternative to threads. When you have a long-running job you will want to run it in the background, while the user does other things. There are four ways to do this: - Use a new thread for each task. - Use callbacks from an idle handler. - Use a recursive mainloop. - Use this module. Using threads causes a number of problems. Some builds of pygtk/python don't support them, they introduce race conditions, often lead to many subtle bugs, and they require lots of resources (you probably wouldn't want 10,000 threads running at once). In particular, two threads can run at exactly the same time (perhaps on different processors), so you have to be really careful that they don't both try to update the same variable at the same time. This requires lots of messy locking, which is hard to get right. Callbacks work within a single thread. For example, you open a dialog box and then tell the system to call one function if it's closed, and another if the user clicks OK, etc. The function that opened the box then returns, and the system calls one of the given callback functions later. Callbacks only execute one at a time, so you don't have to worry about race conditions. However, they are often very awkward to program with, because you have to save state somewhere and then pass it to the functions when they're called. A recursive mainloop only works with nested tasks (you can create a sub-task, but the main task can't continue until the sub-task has finished). We use these for, eg, rox.alert() boxes since you don't normally want to do anything else until the box is closed, but it is not appropriate for long-running jobs. Tasks use python's generator API to provide a more pleasant interface to callbacks. See the Task class (below) for more information. N(sg(sSets ImmutableSetsBlockercBs2tZdZd„Zd„Zd„Zd„ZRS(sA Blocker object starts life with 'happened = False'. Tasks can ask to be suspended until 'happened = True'. The value is changed by a call to trigger(). Example: kettle_boiled = tasks.Blocker() def make_tea(): print "Get cup" print "Add tea leaves" yield kettle_boiled print "Pour water into cup" print "Brew..." yield tasks.TimeoutBlocker(120) print "Add milk" print "Ready!" tasks.Task(make_tea()) # elsewhere, later... print "Kettle boiled!" kettle_boiled.trigger() You can also yield a list of Blockers. Your function will resume after any one of them is triggered. Use blocker.happened to find out which one(s). Yielding a Blocker that has already happened is the same as yielding None (gives any other Tasks a chance to run, and then continues). cCst|_tƒ|_dS(N(sFalsesselfshappenedsSets_rox_lib_tasks(sself((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys__init__Ns cCs?|iodSnt|_t o tƒnti|ƒdS(s…The event has happened. Note that this cannot be undone; instead, create a new Blocker to handle the next occurance of the event.N(sselfshappenedsTrues _run_queues _schedulesappend(sself((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pystriggerRs   cCs|ii|ƒdS(s˜Called by the schedular when a Task yields this Blocker. If you override this method, be sure to still call this method with Blocker.add_task(self)!N(sselfs_rox_lib_taskssaddstask(sselfstask((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pysadd_task]scCs|ii|ƒdS(sSCalled by the schedular when a Task that was waiting for this blocker is resumed.N(sselfs_rox_lib_taskssremovestask(sselfstask((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys remove_taskcs(s__name__s __module__s__doc__s__init__striggersadd_tasks remove_task(((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pysBlocker.s   s IdleBlockercBstZdZd„ZRS(s›An IdleBlocker blocks until a task starts waiting on it, then immediately triggers. An instance of this class is used internally when a Task yields None.cCsti||ƒ|iƒdS(sAlso calls trigger.N(sBlockersadd_tasksselfstaskstrigger(sselfstask((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pysadd_taskls(s__name__s __module__s__doc__sadd_task(((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys IdleBlockerhs sTimeoutBlockercBs tZdZd„Zd„ZRS(sŠTriggers after a set number of seconds. rox.toplevel_ref/unref are called to prevent the app quitting while a TimeoutBlocker is running.cCs8ti|ƒtiƒtit|dƒ|i ƒdS(s4Trigger after 'timeout' seconds (may be a fraction).ièN( sBlockers__init__sselfsroxs toplevel_refsgobjects timeout_addslongstimeouts_timeout(sselfstimeout((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys__init__us  cCstiƒ|iƒdS(N(sroxstoplevel_unrefsselfstrigger(sself((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys_timeout{s (s__name__s __module__s__doc__s__init__s_timeout(((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pysTimeoutBlockerqs  cCs|iƒtSdS(N(sblockerstriggersFalse(ssrcscondsblocker((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys _io_callbacks s InputBlockercBs5tZdZeZeZd„Zd„Zd„ZRS(s.Triggers when os.read(stream) would not block.cCsti|ƒ||_dS(N(sBlockers__init__sselfsstreams_stream(sselfsstream((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys__init__‡s cCsPti||ƒ|itjo,ti|iti ti Bt |ƒ|_ndS(N( sBlockersadd_tasksselfstasks_tagsNonesgobjects io_add_watchs_streamsIO_INsIO_HUPs _io_callback(sselfstask((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pysadd_task‹scCs<ti||ƒ|i oti|iƒt|_ndS(N( sBlockers remove_tasksselfstasks_rox_lib_taskssgobjects source_removes_tagsNone(sselfstask((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys remove_task‘s ( s__name__s __module__s__doc__sNones_tags_streams__init__sadd_tasks remove_task(((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys InputBlockerƒs   s OutputBlockercBs5tZdZeZeZd„Zd„Zd„ZRS(s/Triggers when os.write(stream) would not block.cCsti|ƒ||_dS(N(sBlockers__init__sselfsstreams_stream(sselfsstream((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys__init__›s cCsPti||ƒ|itjo,ti|iti ti Bt |ƒ|_ndS(N( sBlockersadd_tasksselfstasks_tagsNonesgobjects io_add_watchs_streamsIO_OUTsIO_HUPs _io_callback(sselfstask((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pysadd_taskŸscCs<ti||ƒ|i oti|iƒt|_ndS(N( sBlockers remove_tasksselfstasks_rox_lib_taskssgobjects source_removes_tagsNone(sselfstask((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys remove_task¥s ( s__name__s __module__s__doc__sNones_tags_streams__init__sadd_tasks remove_task(((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys OutputBlocker—s   sTaskcBs,tZdZed„Zd„Zd„ZRS(sLCreate a new Task when you have some long running function to run in the background, but which needs to do work in 'chunks'. Example: from rox import tasks def my_task(start): for x in range(start, start + 5): print "x =", x yield None tasks.Task(my_task(0)) tasks.Task(my_task(10)) rox.mainloop() Yielding None gives up control of the processor to another Task, causing the sequence printed to be interleaved. You can also yield a Blocker (or a list of Blockers) if you want to wait for some particular event before resuming (see the Blocker class for details). cCs>|i|_||_tƒ|_ti|ƒtf|_dS(s®Call iterator.next() from a glib idle function. This function can yield Blocker() objects to suspend processing while waiting for events. name is used only for debugging.N( siteratorsnextsselfsnamesBlockersfinisheds _idle_blockersadd_tasks _rox_blockers(sselfsiteratorsname((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys__init__Ãs    cCsx|iD]}|i|ƒq Wy|iƒ}WnQtj o|iiƒdSn/t j o"t i ƒ|iiƒdSnX|t jo t f}nGt|tƒo |f}nx&|D]}|iot f}PqÃqÃWx|D]}|i|ƒqìW||_dS(N(sselfs _rox_blockerssblockers remove_tasksnexts new_blockerss StopIterationsfinishedstriggers Exceptionsroxsreport_exceptionsNones _idle_blockers isinstancesBlockershappenedsadd_task(sselfsblockers new_blockers((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys_resumeÏs2           cCs'|itjodSnd|iSdS(Ns[Task]s [Task '%s'](sselfsnamesNone(sself((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys__repr__ðs(s__name__s __module__s__doc__sNones__init__s_resumes__repr__(((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pysTask­s  !cCstiƒtitƒdS(N(sroxs toplevel_refsgobjectsidle_adds_handle_run_queue(((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys _scheduleös cCsvtd}|tjo tƒant|iƒ}x|D]}|iƒq:Wtd=tot Snt i ƒt SdS(Ni( s _run_queuesnexts _idle_blockers IdleBlockers ImmutableSets_rox_lib_tasksstasksstasks_resumesTruesroxstoplevel_unrefsFalse(staskssnextstask((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys_handle_run_queueûs    (s__doc__sroxsgobjectsgssetssSets ImmutableSets _run_queuesBlockers IdleBlockersTimeoutBlockers _io_callbacks InputBlockers OutputBlockers _idle_blockersTasks _schedules_handle_run_queue(s ImmutableSets _run_queuesSets InputBlockersgsBlockers _io_callbacksroxs OutputBlockersTasks _schedules_handle_run_queuesTimeoutBlockersgobjects IdleBlocker((sS/mnt/gmirror/ports/devel/py-roxlib/work/rox-lib2-2.0.5/ROX-Lib2/python/rox/tasks.pys?#s  :   I