Jump to content

Recommended Posts

If anyone's looking for a way to llSleep() their script, but don't want to prevent event queues from mounting up during this time-period, I made a function that you can just plop into your code and use in the same way as llSleep() and it'll get rid of the nastiest part of that function.

It'll also work over midnight time crossings, so you can use it at any time, anywhere, and it'll function exactly as expected, to a very accurate measurement (less than 0.00000001 seconds inaccuracy).

llWait(float wait_time)
{
    
    float start_time = llGetGMTclock();
    
    while(TRUE)
    {
        
        float current_time = llGetGMTclock();
        
        if(current_time >= start_time)
        {
            
            if(current_time - start_time >= wait_time)
                return;
        }
        
        else
        {
            
            if( (86400.0 - start_time) + current_time >= wait_time )
                return;
            
        }
        
    }
    
}

 

Share this post


Link to post
Share on other sites

I normally use states if I want to rest the script for a while and not have an event queue building up.   It's a lot easier on the simulator than running a continuous loop, though I suppose you wouldn't run it for that long.

Something like this:

float fSleepTime;
default {
	state_entry() {
		//do initialisation stuff

		state running;
	}
}

state running{
 state_entry() {
 	//open listeners etc
 }
	//do things
 
 	touch_end(integer num_detected) {
 		state sleeping;
 	}
}

state sleeping{
	 state_entry() {
	 	llSetTimerEvent(fSleepTime);
	 }

	 timer() {
	 	llSetTimerEvent(0.0);
	 	state running;
	 }
}

 

  • Like 2

Share this post


Link to post
Share on other sites
1 hour ago, Innula Zenovka said:

if I want to rest the script for a while and not have an event queue building up.

But OP said "but don't want to prevent event queues from mounting up during this time-period"..

Share this post


Link to post
Share on other sites

I may be wrong but in my book the script is running in an event handler and the event handle will be busy until the loop is finished. Thus it will stop other events while running and the event queue will build up. Virtually this is what the llSleep() does but in so many more words

  • Like 1

Share this post


Link to post
Share on other sites

The script does the same as llSleep.

Just one difference - llSleep uses a cpu time of 0 and this script uses alot of cpu time.

LSL scripts are single threaded - there is no multitasking! While an event handler or a function is executing no events can trigger and so they are queued up.

But the idea of this script is based of the wrong assumption that events will trigger in the background. That is NOT the case.

Share this post


Link to post
Share on other sites

Sorry, I'd misread the OP and thought the idea was to avoid events building up in the event queue.  

As to events building up in the event queue, it seems a bit strange and rather depends on the event.   I've been playing round with this test script:

integer sleeping;
integer counter;
default
{
    state_entry()
    {
       llListen(5, "", llGetOwner(), "");
    }

    touch_start(integer total_number)
    {
      if(!sleeping){
          sleeping = TRUE;
          llOwnerSay("Sleeping now");
           llSleep(10.0);
           sleeping = FALSE;
           llOwnerSay("Woken up");
           llOwnerSay((string)counter);
         
        }
        
        else{
            llOwnerSay("touched"); 
            ++counter; 
        }    
    }
    
    collision_start(integer number_detected){
        llOwnerSay(llGetUsername(llDetectedKey(0))+" collided with me");   
    }
    
    listen(integer channel, string name, key id, string message){
            llOwnerSay(message);   
    }
}

While it's sleeping, the listens stack up, and it repeats all the messages (well, I tested it with 5 messages and it repeated all of them).    However, when I walked into it while it was sleeping, it simply said "innula.zenokva collided with me" once, no matter how many times I walked into it.   And when I touched it while it was asleep, it didn't register any touches at all.

However, when I tried this slightly different version, 

integer sleeping;
integer counter;
default
{
    state_entry()
    {
       llListen(5, "", llGetOwner(), "");
    }

    touch_start(integer total_number)
    {
        llOwnerSay((string)(++counter));
    }
    
    collision_start(integer number_detected){
        llOwnerSay(llGetUsername(llDetectedKey(0))+" collided with me");   
    }
    
    listen(integer channel, string name, key id, string message){
            llOwnerSay(message);
             llOwnerSay("Sleeping now");
           llSleep(10.0);
           sleeping = FALSE;
           llOwnerSay("Woken up");   
    }
}

it still stacked up all the listen events (so if I said "boo" to it 3 times while it was asleep, it said "boo  Sleeping now" and went back to sleep for another 10 second for each time I said "boo" while it was asleep.    It registered one touch this way, no matter how many times I touched it.

So Its behaviour seems to depend on the type of event.

Personally, I never find it necessary to sleep a script for more than a second, and usually only for 0.2 seconds or so.    If I find myself wanting to sleep the script for any longer than that, I treat it as a sign I'm doing something wrong, and then I can always find a better way to do it.

  • Like 1

Share this post


Link to post
Share on other sites
1 hour ago, Innula Zenovka said:

[ .... ]

Personally, I never find it necessary to sleep a script for more than a second, and usually only for 0.2 seconds or so.    If I find myself wanting to sleep the script for any longer than that, I treat it as a sign I'm doing something wrong, and then I can always find a better way to do it.

----------------------------

I agree, which is why I didn't even consider mentioning llSleep as an option when I posted earlier about ways to run more than one timer in a script.  I'll llSleep a script for 0.2 seconds after it rezzes something, for example, but otherwise use a real timer.

 

Edited by Rolig Loon
The usual typos
  • Like 1

Share this post


Link to post
Share on other sites
2 hours ago, Nova Convair said:

The script does the same as llSleep.

Just one difference - llSleep uses a cpu time of 0 and this script uses alot of cpu time.

LSL scripts are single threaded - there is no multitasking! While an event handler or a function is executing no events can trigger and so they are queued up.

But the idea of this script is based of the wrong assumption that events will trigger in the background. That is NOT the case.

I never said it was multi-threaded, nor was I under that impression. I simply said it was a good way to prevent event queues from being dropped in cases where you would have otherwise used llSleep().

To Innula: I'd tend to agree wholeheartedly, except in cases where you want to confine wait times to a single event or method without having to worry about saving the current data being used in a global variable (i.e. a loop). Also, timers can be hard on the simulator depending on the floated time, so this is a viable alternative for practical purposes. 

 

Share this post


Link to post
Share on other sites
1 minute ago, AlduousMcBurlington said:

I never said it was multi-threaded, nor was I under that impression. I simply said it was a good way to prevent event queues from being dropped in cases where you would have otherwise used llSleep().

To Innula: I'd tend to agree wholeheartedly, except in cases where you want to confine wait times to a single event or method without having to worry about saving the current data being used in a global variable (i.e. a loop). Also, timers can be hard on the simulator depending on the floated time, so this is a viable alternative for practical purposes. 

 

Depends on the use case, but I still think I'd work hard to avoid both extended llSleep calls and attempts to emulate them.  

All I can say is that whenever someone asks me to help fix a script and I find either a long llSleep or a loop involving while (TRUE), the problem is almost invariably to do with that.   I'm not saying that long sleeps or potentially infinite loops are automatically going to break a script, but they are so likely to break something that I'm scared of using them and will work hard to find a safer alternative. 

Share this post


Link to post
Share on other sites
17 minutes ago, Innula Zenovka said:

Depends on the use case, but I still think I'd work hard to avoid both extended llSleep calls and attempts to emulate them.  

All I can say is that whenever someone asks me to help fix a script and I find either a long llSleep or a loop involving while (TRUE), the problem is almost invariably to do with that.   I'm not saying that long sleeps or potentially infinite loops are automatically going to break a script, but they are so likely to break something that I'm scared of using them and will work hard to find a safer alternative. 

Yes; this was more for a simple way to save time while iterating loops than anything else. For example...

 

default
{

	state_entry()
	{

		integer SE_placeholder = 0;

		while(SE_placeholder < 100)
		{
        	
			DoSomethingTimeSensitive();
			llWait(0.001);
			SE_placeholder += 1;
                                   
		}

	}

}

... especially since timers raise event queues, which can be hard on the sim (at very low values).

Edited by AlduousMcBurlington

Share this post


Link to post
Share on other sites
6 hours ago, Innula Zenovka said:

 However, when I walked into it while it was sleeping, it simply said "innula.zenokva collided with me" once, no matter how many times I walked into it.

Is this perhaps because they were all reported in the one collision event, but you only check the first item?  (That is, you ignored the value of number_detected in the collision event.)

Share this post


Link to post
Share on other sites

I'm surprised no one caught my error; apparently llGetGMTclock() does return a float but it's truncated to the nearest second, making this function unusable lol

 

I'm working on a fix, and if anyone's interested I can reply the corrected function to this thread or make a new post when I'm done.

Share this post


Link to post
Share on other sites
48 minutes ago, Natasja Kiranov said:

Is this perhaps because they were all reported in the one collision event, but you only check the first item?  (That is, you ignored the value of number_detected in the collision event.)

Is that how it works?   If I walk into the object and then walk into it again a second later, surely that's two separate events?   I could well be mistaken, but I think the number_detected parameter is relevant only if two collisions take place at the same time.   Certainly the only time I've ever found it particularly relevant is in sensor events.

 

  • Like 1

Share this post


Link to post
Share on other sites
2 hours ago, Innula Zenovka said:

Is that how it works?   If I walk into the object and then walk into it again a second later, surely that's two separate events?   I could well be mistaken, but I think the number_detected parameter is relevant only if two collisions take place at the same time.   Certainly the only time I've ever found it particularly relevant is in sensor events.

 

Yes, the number_detected is virtually useless in a collision event. If you walk into a collision prim twice, that's interpreted by the script as two separate events.  You register as llDetectedKey(0) both times. Unlike a sensor, which can detect several objects/avatars in the same scan, a collision never detects two events "simultaneously".  I wish I could find the thread, now several years old, in which someone (Strife?  Void?) did an exhaustive test showing that.  Unfortunately, it's buried in unsearchable archives by now.

Edited by Rolig Loon

Share this post


Link to post
Share on other sites

I've been searching the old, old forums via the search tool at  http://forums-archive.secondlife.com/-1/1.html.   Two discoveries.   

First, llSleep and resources (this is something I dimly remembered from years ago). It would appear, according to this discussion, that llSleep is quite resource-intensive, since it seems to be a sort of infinite loop.    That's based on what LL devs apparently said during the course of a presentation.    The video link there to the presentation works, and I've downloaded the file, but since it's an hour and 20 minutes long, I haven't had a chance to listen to it yet, so I know only what the summaries there say.  But the participants in the discussion are people I remember as being very experienced scripters, so I trust their summaries.

While I don't know enough to comment with any certainty about which solution is the least resource-intensive, I think it would be fair to say that llSleep doesn't seem to be without its own resource implications.   It not simply a matter of turning the script off for n seconds.

Second, llSleep and the event queue.   I don't know if this thread is the one @Rolig Loon meant (I had to used a link shortener since the original didn't want to embed) but in it Void seems to be saying that touch and collision events are treated as simultaneous if they occur within 0.1 seconds of each other and also, in the specific context of llSleep,  that they do stack in the event queue while the script is sleeping, but only one touch or collision event per avatar.  So it sounds as if I'd have recorded two touch/collision events had I been testing things with a friend.  

Share this post


Link to post
Share on other sites

That's an interesting link. It's an older thread than the one I was remembering. This one reaches a different conclusion, though.  Void is saying that collision and touch events are simultaneous if they are within 0.1 seconds of each other, but I could swear that I have seen the opposite in a more recent thread.  Maybe in SLU?  For some reason, I can;t seem to search the ancient forums at all now.  My links all redirect to this new forum, so they are useless.  How did you do it, Innula?

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...