| !----------------------------------------------------------------------- | |
| ! Priority-Daemons | |
| ! Release 1 | |
| ! Andrew Plotkin (erkyrath@cmu.edu) | |
| ! This file is in the public domain. | |
| ! | |
| ! This is a module which you can include to make the daemons and timers of | |
| ! the Inform libraries behave predictably. They will execute in the order | |
| ! defined by the "daemon_priority" property of each object in the | |
| ! daemon/timer list. Higher priorities go first; if priorities are equal, | |
| ! they execute in the order in which they were started up. The default | |
| ! daemon_priority is zero, but you can assign any numerical value to the | |
| ! property, including negative ones. However, you cannot use an embedded | |
| ! routine which returns a number, as is usual in Inform. This is because it | |
| ! would be very bad if the priority changed in mid-stream; priorities are | |
| ! only checked when a daemon starts up. For the same reason, you should not | |
| ! assign a new value to a priority property. If you must do it, do it while | |
| ! the object's daemon/timer is *not* running. | |
| ! | |
| ! These routines have one restriction that the standard library routines do | |
| ! not: It is illegal to call StartDaemon or StartTimer from inside a daemon | |
| ! or timer routine, if the daemon you're starting has a priority greater | |
| ! than or equal to the calling daemon. It *is* legal to start a | |
| ! daemon/timer of lower priority (and that daemon will be called for the | |
| ! first time that same turn.) It is also legal to call StopDaemon or | |
| ! StopTimer at any time. | |
| ! | |
| ! To use this thing, include this file after you include the Inform | |
| ! "parser" file. Before the "parser" include, drop in these four lines | |
| ! (uncommented): | |
| ! | |
| ! Replace StartDaemon; | |
| ! Replace StartTimer; | |
| ! Replace StopDaemon; | |
| ! Replace StopTimer; | |
| !-------------------------------------------------------------------------- | |
| Property daemon_priority 0; | |
| ! StartDaemonOrTimer inserts the given object in the_timers list, at the | |
| ! position defined by its daemon_priority. That is, the object is inserted | |
| ! after all objects with a greater-or-equal priority, and before all | |
| ! objects with a lesser priority. | |
| ! | |
| ! This is not complicated, just a little ugly. | |
| [ StartDaemonOrTimer obj flag i j; | |
| ! check to make sure it's not already running | |
| for (i=0:i<active_timers:i++) | |
| if (the_timers-->i==obj) | |
| { if (timer_flags->i~=flag) TimerE3(obj); | |
| rfalse; | |
| } | |
| ! find a slot | |
| j = (-1); | |
| for (i=0:i<active_timers:i++) { | |
| if (the_timers-->i ~= 0 | |
| && (the_timers-->i).daemon_priority >= obj.daemon_priority) { | |
| j = i; | |
| } | |
| if (the_timers-->i ~= 0 | |
| && (the_timers-->i).daemon_priority < obj.daemon_priority) { | |
| break; | |
| } | |
| } | |
| ! We must now put obj between j (-1 .. a_t-1) and i (0 .. a_t). Both | |
| ! are objects (not empty spaces.) j has >= priority, i has < priority. | |
| ! If there's a blank space between them, that's perfect. | |
| ! Otherwise we'll have to shift i upwards. | |
| j++; | |
| while (the_timers-->j ~= 0 && j < i) | |
| j++; | |
| if (j < i) { | |
| ! j is open. Use it. | |
| i = j; | |
| } | |
| else { | |
| ! We'll use j, but we have to move i up first. | |
| while (i < active_timers && the_timers-->i ~= 0) | |
| i++; | |
| if (i == active_timers) { | |
| if (active_timers*2 >= MAX_TIMERS) { | |
| TimerE(); | |
| return; | |
| } | |
| active_timers++; | |
| } | |
| while (i > j) { | |
| the_timers-->i = the_timers-->(i-1); | |
| timer_flags->i = timer_flags->(i-1); | |
| i--; | |
| } | |
| } | |
| ! i is now set correctly (in both cases.) | |
| the_timers-->i=obj; timer_flags->i=flag; | |
| ]; | |
| [ StartDaemon obj; | |
| StartDaemonOrTimer(obj,1); | |
| ]; | |
| [ StartTimer obj timer; | |
| if (obj.&time_left==0) TimerE2(obj); | |
| else { | |
| StartDaemonOrTimer(obj,2); | |
| obj.time_left = timer; | |
| } | |
| ]; | |
| ! StopTimer and StopDaemon are exactly the same as in the standard | |
| ! library (from release 8 up to at least release 11.) I include them | |
| ! here just in case you're using a really old (or distant future) | |
| ! library. | |
| [ StopTimer obj i; | |
| for (i=0:i<active_timers:i++) | |
| if (the_timers-->i==obj) jump FoundTSlot2; | |
| rfalse; | |
| .FoundTSlot2; | |
| if (obj.&time_left==0) TimerE2(obj); | |
| the_timers-->i=0; obj.time_left=0; | |
| ]; | |
| [ StopDaemon obj i; | |
| for (i=0:i<active_timers:i++) | |
| if (the_timers-->i==obj) jump FoundTSlot4; | |
| rfalse; | |
| .FoundTSlot4; | |
| the_timers-->i=0; | |
| ]; | |
| ! End of file ------------------------------------------------------------- |
Xet Storage Details
- Size:
- 4.3 kB
- Xet hash:
- 86e8203a9a0e4d9682489d7d4a56c5c855da2f2207ba1ee14904d4cfe09f42fb
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.