Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

DoEvents like command?

Paradox Dimsum
Registered User
Join date: 9 Apr 2006
Posts: 3
07-04-2006 01:04
So I am scripting see.. :) I have a use for a Do..While.. and was curious if there was any way to get around the fact that while inside a Do..While no other 'event' is handled.

I have run into this in many places throughout my exploration of what's possible with scripts. For one it's very hard to communicate between scripts that need blocking, run a command and wait for a return of sorts... so a state w/ a timer is often used to handle this. However there are still some good uses for Do..While.

So... Is there any command or better methodology to get LSL to process other event's in the 'message queue' like a vb doevents command would do?

Without this any loop would prevent any other action from occurring and that's troubling.

Thanks in advance.


eg.

integer Running=FALSE;
integer TimeCount=0;


StartTimer()
{
Running=TRUE;
llOwnerSay("Timer Started";);
llSetTimerEvent(1.0);
do
{
TimeCount++;
} while ((Running == TRUE) && (TimeCount < 1000));
if (Running) llOwnerSay("Timer never fired, I reached 1000";);

}



default
{
state_entry()
{
llSay(0, "Init";);
}

touch_start(integer total_number)
{
StartTimer();
}

timer()
{
Running=FALSE;
llOwnerSay("Total Ticks " + (string)TimeCount);
llSetTimerEvent(0);

}

}
_____________________
--
Ryan Pavely
Director Research And Development
Net Access Corporation
Aodhan McDunnough
Gearhead
Join date: 29 Mar 2006
Posts: 1,518
07-04-2006 02:01
First thing I do is rethink my approach to the script. Since we know in already how scripts behave (no events while something is executing) we should approach the design with this in mind. If it means splitting the program functions among several scripts then do it.

LSL is not a true multi-tasking event-driven environment.
Bitzer Balderdash
Dazed and Confused
Join date: 21 Dec 2005
Posts: 246
07-04-2006 02:10
In short, no.

LSL is single threaded. Events triggered will queue up until the current event handler is finished.

So, there is simply no way to do what you are trying there. The counter will always finish.
Rolly Mandelbrot
Registered User
Join date: 17 Apr 2006
Posts: 4
07-07-2006 12:11
The following is a (not recommended) way of emulating what you asked. Hope it helps.
Note: rethinking is the win ... I've noticed a lot of scripts are written as though LSL was a procedural language ... think 'event driven state machine' as a far more accurate paradigm
than 'linearly procedural' ... hope this helps increase your LSL skills

CODE

// this is a hack to emulate interrupting a looped task
// NOTE: emphasis on 'hack' I'd recommend doing this only when nothing else will do

// Note most of this is written for clarity (I hope) not for production

// the objective is to emulate writing a loop (eg. do ... while that can be
// interrupted by some other event

// here we set up a design pattern for running a task until either it is done
// or tthe interrupting event occurs (in this case a timer)

// timer support
float allowedTime = 5.0;

startInterruptingEvent() {
llSetTimerEvent(allowedTime);
}

// our task is just to count from 0 to some other value
integer count = 0;
integer stopCount = 60; /// change this to 10 to see task finish before timer

integer taskNotDone() {
if (count < stopCount) {
return TRUE;
}
return FALSE;
}

doTask() {
count++;
}

// loop emulation ... this, by the way, is the 'hack' ... we need some event to occur
// that will emulate start next iteration ... we are essentially using the event
// queue ... each time we get a changed colour we perform one iteration of loop
// changed colour was an arbitrary choice
doNextIteration() {
// essentially don't do anything but stick a changed colour event on event queue
llSetColor(llGetColor(ALL_SIDES), ALL_SIDES);

// btw this leads us to the discovery of the delay we get when changing a colour
// between the time we say to change it and the moment we are notified the change
// has occurred (a SWAG suggests .2 sec)
}

default {
touch_start(integer total_number) {
startInterruptingEvent();
doNextIteration();
}

changed(integer change) {
if (change && CHANGED_COLOR) {
if (taskNotDone()) {
doTask(); // do one iteration
doNextIteration();
} else {
state taskFinished;
}
}
}

timer() {
// in this case I'm using the time to stop loop ... if we wanted to just
// continue after performing other task I would put that task here
// instead of this state change
state timeFinished;
}
}

state taskFinished {
state_entry() {
llOwnerSay("Finished task before time up");
}
}

state timeFinished {
state_entry() {
llOwnerSay("Times up!!! .. did not complete task");
}
}