Difference between revisions of "Scheduler"
(12 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
{{LSL Header}} | {{LSL Header}} | ||
== Scheduler == | == Scheduler == | ||
A lot of scripters (myself included) have a lot of trouble managing multiple events using LSL's single timer capability. For this reason I wrote myself a simple scheduling engine, it's as efficient as I can really make it given LSL's limitations, and unfortunately [[Mono]] is unlikely to speed it up significantly. | A lot of scripters ([[User:Haravikk Mistral|myself]] included) have a lot of trouble managing multiple events using LSL's single timer capability. For this reason I wrote myself a simple scheduling engine, it's as efficient as I can really make it given LSL's limitations, and unfortunately [[Mono]] is unlikely to speed it up significantly. | ||
When making use of this script template/library you should consider your requirements carefully, as it is not advisable to schedule a lot of rapid events. If however you want to trigger events with around 10 seconds or more between them then you should be just fine using this library. | When making use of this script template/library you should consider your requirements carefully, as it is not advisable to schedule a lot of rapid events. If however you want to trigger events with around 10 seconds or more between them then you should be just fine using this library. | ||
Line 13: | Line 13: | ||
The following code segment should be entered at the top of your script. You may rename the variables themselves as you see fit, but make sure to rename them in the rest of the script! | The following code segment should be entered at the top of your script. You may rename the variables themselves as you see fit, but make sure to rename them in the rest of the script! | ||
< | <source lang="lsl2">list events = []; | ||
// PARAMS: | // PARAMS: | ||
// id - the unique id you associate with your event, use of global variables is recommended here | // id - the unique, positive id you associate with your event, use of global variables is recommended here. | ||
// time - the time at which you want the event to try and execute | // time - the time at which you want the event to try and execute. | ||
// data - a piece of data you want passed to your handler when the event executes. | |||
scheduleEvent(integer id, integer time, string data) { | scheduleEvent(integer id, integer time, string data) { | ||
events = llListSort((events = []) + events + [time, id, data], 3, TRUE); | events = llListSort((events = []) + events + [time, id, data], 3, TRUE); | ||
setTimer(); | setTimer(FALSE); | ||
} | } | ||
// This function sets the timer correctly for the next scheduled event, or de-activates the timer | // This function sets the timer correctly for the next scheduled event, or de-activates the timer | ||
// if there are no event remaining | // if there are no event remaining | ||
setTimer() { | integer setTimer(integer executing) { | ||
if ((events != []) > 0) { // Are there any list items? | if ((events != []) > 0) { // Are there any list items? | ||
integer time | integer time = llList2Integer(events, 0); | ||
float t = (float)(time - llGetUnixTime()); | float t = (float)(time - llGetUnixTime()); | ||
if (t <= 0.0) t = 0.01; | if (t <= 0.0) { | ||
if (executing) return TRUE; | |||
else t = 0.01; | |||
} | |||
llSetTimerEvent(t); | llSetTimerEvent(t); | ||
} else llSetTimerEvent(0.0); | } else { llSetTimerEvent(0.0); } | ||
return FALSE; | |||
} | } | ||
Line 48: | Line 46: | ||
//} else if (id == 2) llOwnerSay(data); | //} else if (id == 2) llOwnerSay(data); | ||
} | } | ||
</ | </source> | ||
== Timer event == | == Timer event == | ||
Enter this timer event into your script. It is important that you do not edit it unless you know what you are doing! During normal use you should only have to modify the contents of the handleEvent() function. | Enter this timer event into your script. It is important that you do not edit it unless you know what you are doing! During normal use you should only have to modify the contents of the handleEvent() function. | ||
< | <source lang="lsl2">timer() { | ||
// Clear timer or it might fire again before we're done | // Clear timer or it might fire again before we're done | ||
llSetTimerEvent(0.0); | llSetTimerEvent(0.0); | ||
// Fire the event | do { | ||
// Fire the event | |||
handleEvent(llList2Integer(events, 1), llList2String(events, 2)); | |||
// Get rid of the first item as we've executed it | |||
integer l = events != []; | |||
if (l > 0) { | |||
if (l > 3) | |||
events = llList2List((events = []) + events, 3, -1); | |||
else events = []; | |||
} | |||
setTimer(); | // Prepare the timer for the next event | ||
}</ | } while (setTimer(TRUE)); | ||
}</source> | |||
== Example == | == Example == | ||
This example simply has two events, 10 seconds apart. The first says "Half-way there" and the second says "Done". | This example simply has two events, 10 seconds apart. The first says "Half-way there" and the second says "Done". | ||
< | <source lang="lsl2">list events = []; | ||
// PARAMS: | // PARAMS: | ||
// id - the unique id you associate with your event, use of global variables is recommended here | // id - the unique, positive id you associate with your event, use of global variables is recommended here. | ||
// time - the time at which you want the event to try and execute | // time - the time at which you want the event to try and execute. | ||
// data - a piece of data you want passed to your handler when the event executes. | |||
scheduleEvent(integer id, integer time, string data) { | scheduleEvent(integer id, integer time, string data) { | ||
events = llListSort((events = []) + events + [time, id, data], 3, TRUE); | events = llListSort((events = []) + events + [time, id, data], 3, TRUE); | ||
setTimer(); | setTimer(FALSE); | ||
} | } | ||
// This function sets the timer correctly for the next scheduled event, or de-activates the timer | // This function sets the timer correctly for the next scheduled event, or de-activates the timer | ||
// if there are no event remaining | // if there are no event remaining | ||
setTimer() { | integer setTimer(integer executing) { | ||
if ((events != []) > 0) { // Are there any list items? | if ((events != []) > 0) { // Are there any list items? | ||
integer time | integer time = llList2Integer(events, 0); | ||
float t = (float)(time - llGetUnixTime()); | float t = (float)(time - llGetUnixTime()); | ||
if (t <= 0.0) t = 0.01; | if (t <= 0.0) { | ||
if (executing) return TRUE; | |||
else t = 0.01; | |||
} | |||
llSetTimerEvent(t); | llSetTimerEvent(t); | ||
} else llSetTimerEvent(0.0); | } else { llSetTimerEvent(0.0); } | ||
return FALSE; | |||
} | } | ||
Line 120: | Line 118: | ||
llSetTimerEvent(0.0); | llSetTimerEvent(0.0); | ||
// Fire the event | do { | ||
// Fire the event | |||
handleEvent(llList2Integer(events, 1), llList2String(events, 2)); | |||
// Get rid of the first item as we've executed it | |||
integer l = events != []; | |||
if (l > 0) { | |||
if (l > 3) | |||
events = llList2List((events = []) + events, 3, -1); | |||
else events = []; | |||
} | |||
// Prepare the timer for the next event | |||
setTimer(); | } while (setTimer(TRUE)); | ||
} | } | ||
}</ | }</source> |
Latest revision as of 04:38, 16 December 2015
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
Scheduler
A lot of scripters (myself included) have a lot of trouble managing multiple events using LSL's single timer capability. For this reason I wrote myself a simple scheduling engine, it's as efficient as I can really make it given LSL's limitations, and unfortunately Mono is unlikely to speed it up significantly.
When making use of this script template/library you should consider your requirements carefully, as it is not advisable to schedule a lot of rapid events. If however you want to trigger events with around 10 seconds or more between them then you should be just fine using this library.
Please see the example at the bottom of this page on how to use this library.
Notes
This scheduling system is primarily intended for use in scheduling single unique events. If you wish to repeatedly trigger an event at a set interval then you should still use an ordinary timer event, using another script as required. You can use this script for recurring events if you really want, by having your event schedule itself again. This should only be done if the events are relatively infrequent, as LSL list operations are not particularly efficient.
Global variables and functions
The following code segment should be entered at the top of your script. You may rename the variables themselves as you see fit, but make sure to rename them in the rest of the script!
list events = [];
// PARAMS:
// id - the unique, positive id you associate with your event, use of global variables is recommended here.
// time - the time at which you want the event to try and execute.
// data - a piece of data you want passed to your handler when the event executes.
scheduleEvent(integer id, integer time, string data) {
events = llListSort((events = []) + events + [time, id, data], 3, TRUE);
setTimer(FALSE);
}
// This function sets the timer correctly for the next scheduled event, or de-activates the timer
// if there are no event remaining
integer setTimer(integer executing) {
if ((events != []) > 0) { // Are there any list items?
integer time = llList2Integer(events, 0);
float t = (float)(time - llGetUnixTime());
if (t <= 0.0) {
if (executing) return TRUE;
else t = 0.01;
}
llSetTimerEvent(t);
} else { llSetTimerEvent(0.0); }
return FALSE;
}
// Place your event handling code in here
handleEvent(integer id, string data) {
//if (id == 1) {
// llOwnerSay(data);
// scheduleEvent(2, llGetUnixTime() + 10, "Done");
//} else if (id == 2) llOwnerSay(data);
}
Timer event
Enter this timer event into your script. It is important that you do not edit it unless you know what you are doing! During normal use you should only have to modify the contents of the handleEvent() function.
timer() {
// Clear timer or it might fire again before we're done
llSetTimerEvent(0.0);
do {
// Fire the event
handleEvent(llList2Integer(events, 1), llList2String(events, 2));
// Get rid of the first item as we've executed it
integer l = events != [];
if (l > 0) {
if (l > 3)
events = llList2List((events = []) + events, 3, -1);
else events = [];
}
// Prepare the timer for the next event
} while (setTimer(TRUE));
}
Example
This example simply has two events, 10 seconds apart. The first says "Half-way there" and the second says "Done".
list events = [];
// PARAMS:
// id - the unique, positive id you associate with your event, use of global variables is recommended here.
// time - the time at which you want the event to try and execute.
// data - a piece of data you want passed to your handler when the event executes.
scheduleEvent(integer id, integer time, string data) {
events = llListSort((events = []) + events + [time, id, data], 3, TRUE);
setTimer(FALSE);
}
// This function sets the timer correctly for the next scheduled event, or de-activates the timer
// if there are no event remaining
integer setTimer(integer executing) {
if ((events != []) > 0) { // Are there any list items?
integer time = llList2Integer(events, 0);
float t = (float)(time - llGetUnixTime());
if (t <= 0.0) {
if (executing) return TRUE;
else t = 0.01;
}
llSetTimerEvent(t);
} else { llSetTimerEvent(0.0); }
return FALSE;
}
// Place your event handling code in here
handleEvent(integer id, string data) {
if (id == 1) {
llOwnerSay(data);
scheduleEvent(2, llGetUnixTime() + 10, "Done");
} else if (id == 2) llOwnerSay(data);
}
default {
state_entry() {
scheduleEvent(1, llGetUnixTime() + 10, "Half-way there");
}
timer() {
// Clear timer or it might fire again before we're done
llSetTimerEvent(0.0);
do {
// Fire the event
handleEvent(llList2Integer(events, 1), llList2String(events, 2));
// Get rid of the first item as we've executed it
integer l = events != [];
if (l > 0) {
if (l > 3)
events = llList2List((events = []) + events, 3, -1);
else events = [];
}
// Prepare the timer for the next event
} while (setTimer(TRUE));
}
}