Difference between revisions of "Scheduler"

From Second Life Wiki
Jump to navigation Jump to search
 
(11 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!


<lsl>list events = [];
<source lang="lsl2">list events = [];
integer nextEvent = 0;
string nextData = "";


// 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   = llList2Integer(events, 0);
         integer time = llList2Integer(events, 0);
         integer id    = llList2Integer(events, 1);
         float t = (float)(time - llGetUnixTime());
 
         if (t <= 0.0) {
         if (id != nextEvent) {
             if (executing) return TRUE;
             nextEvent = id;
             else t = 0.01;
             nextData = llList2String(events, 2);
         }
         }
        float t = (float)(time - llGetUnixTime());
        if (t <= 0.0) t = 0.01;
         llSetTimerEvent(t);
         llSetTimerEvent(t);
     } else llSetTimerEvent(0.0);
     } else { llSetTimerEvent(0.0); }
    return FALSE;
}
}


Line 50: Line 46:
     //} else if (id == 2) llOwnerSay(data);
     //} else if (id == 2) llOwnerSay(data);
}
}
</lsl>
</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.


<lsl>timer() {
<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 {
    handleEvent(nextEvent, nextData);
        // Fire the event
          
        handleEvent(llList2Integer(events, 1), llList2String(events, 2));
    // Get rid of the first item as we're executing it
    integer l = events != [];
         // Get rid of the first item as we've executed it
    if (l > 0) {
        integer l = events != [];
        if (l > 3)
        if (l > 0) {
            events = llList2List((events = []) + events, 3, -1);
            if (l > 3)
        else events = [];
                events = llList2List((events = []) + events, 3, -1);
    }
            else events = [];
 
        }
    // Prepare the timer for the next event
     setTimer();
        // Prepare the timer for the next event
}</lsl>
     } 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".


<lsl>list events = [];
<source lang="lsl2">list events = [];
integer nextEvent = 0;
string nextData = "";


// 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   = llList2Integer(events, 0);
         integer time = llList2Integer(events, 0);
        integer id    = llList2Integer(events, 1);
 
        nextEvent = id;
        nextData = llList2String(events, 2);


         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 122: Line 118:
         llSetTimerEvent(0.0);
         llSetTimerEvent(0.0);
          
          
         // Fire the event
         do {
        handleEvent(nextEvent, nextData);
            // Fire the event
            handleEvent(llList2Integer(events, 1), llList2String(events, 2));
          
          
        // Get rid of the first item as we're executing it
            // Get rid of the first item as we've executed it
        integer l = events != [];
            integer l = events != [];
        if (l > 0) {
            if (l > 0) {
            if (l > 3)
                if (l > 3)
                events = llList2List((events = []) + events, 3, -1);
                    events = llList2List((events = []) + events, 3, -1);
            else events = [];
                else events = [];
        }
            }


        // Prepare the timer for the next event
            // Prepare the timer for the next event
         setTimer();
         } while (setTimer(TRUE));
     }
     }
}</lsl>
}</source>

Latest revision as of 04:38, 16 December 2015

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));
    }
}