Sabrina Spice
Registered User
Join date: 20 Sep 2005
Posts: 9
|
10-31-2005 06:37
I need to access some notecard data during a running scriipt, but not reading the complete notecard into lists, cause the notecards with infos stored are getting too long sometimes and exceed the script memeory limitations quickly. What I'm trying to do is to read a notecard line indexed by it's line-number with llGetNotecardLine(string name, integer linenumber), where linenumber is the index I use to acces one line of data when I need it. But this lways fails on the first reading. When I use the function READ_INFO in my example below, the global variables inside this function are empty, I receive data in them from the dataserver event 1st on the secind call to this function. If I insert some llWhisper(0,variable) directly into the dataserver event I can see that data is read and delivered by the dataserver event on the first call to it - but they only are available to the rest of the script / functions after the second call to it. Can't figure out what that is... - a bug ? How do I get the data received from dataserver into my global variables on the first call of a llGetNotecard... - function ? key baseID; key numID; key lineID; string baseline; string dataline; integer numlines;
......
read_info(string cardname, integer num) { numID = llGetNumberOfNotecardLines(cardname); baseID = llGetNotecardLine(cardname, 0); lineID = llGetNotecardLine(cardname, num); llWhisper(0,"Number of Lines: "+(string)numlines); llWhisper(0,"Baseline: "+baseline); llWhisper(0,"Dataline: "+dataline); }
......
dataserver(key query_id, string data) { if (data != EOF) { if (query_id == numID) { numlines = (integer)data; } if (query_id == baseID) { baseline = data; } if (queryID == lineID) { dataline = data; } } }
......
|
Ben Bacon
Registered User
Join date: 14 Jul 2005
Posts: 809
|
10-31-2005 07:35
Hi, Sabrina. The problem is that LSL doesn't wait for llGetNumberOfNotecardLines or llGetNotecardLine to complete before it continues. As an example timeline when SL executes read_info(string cardname, integer num) { numID = llGetNumberOfNotecardLines(cardname); // A baseID = llGetNotecardLine(cardname, 0); // B lineID = llGetNotecardLine(cardname, num); // C llWhisper(0,"Number of Lines: "+(string)numlines); // D llWhisper(0,"Baseline: "+baseline); // E llWhisper(0,"Dataline: "+dataline); // F }
the timeline looks something like - Line A sends a request to the dataserver asking how many lines there are
- The answer has not come back yet, but line B is now sending a request for the first line
- Still, no answers have come back, but we send off a query in line C
- Line D whispers the value of numlines, which has still not been set
- now, maybe, for example, the answer from line B has come back, but because we are still busy in a function the dataserver event cannot be called. The event is put into a queue.
- the answer from line C comes back now, perhaps, bur we're still stuck inside read_info. This event get added to the back of the queue, which now contains 2 items.
- Line E, and then Line F, execute - also displaying uninitialised values
- read_info is finished. as the function exits, SL checks the event queue and finds the 2 notecard line events. it pops the front one off the queue and calls the dataserver event.
- the dataserver event sees that query_id==baseID and assigns data to baseline
- the event exits - SL checks the queue - and findsthe answer to line C, so it calls the dataserver event again, this time with query_id==lineID
- the event completes and exits - SL checks the queue - the queue is empty, so yout script goes idle.
- 1.5 seconds later, the answer from line A, manages to come back. why is it late? why did B and C arrive first? who knows. all kinds of laggy-type stuff might be happening between the sims and the data-server. all we know is that LL do not guarantee in-order responses. SL calls the dataserver event with query_id==numID. only now do you have all three values.
one way around this is to check on the receipt of each item whether or not you have received all items yet, and do whatever you need to if you have. as an example: integer items; // how many items are we waiting for?
key baseID; key numID; key lineID; string baseline; string dataline; integer numlines;
......
read_info(string cardname, integer num) { items = 3; // we want 3 items. let's launch all 3 queries in parallel numID = llGetNumberOfNotecardLines(cardname); baseID = llGetNotecardLine(cardname, 0); lineID = llGetNotecardLine(cardname, num); // the queries are still being handled now - let's just go idle until all 3 answers are returned. }
......
dataserver(key query_id, string data) { if (data != EOF) { if (query_id == numID) numlines = (integer)data; else if (query_id == baseID) baseline = data; else if (queryID == lineID) dataline = data; if (items) { // once we've done this once, never do it again until items is reinitialised --items; // we got an item, so there is one less oustanding if (items==0) { // was this the last one? llWhisper(0,"Number of Lines: "+(string)numlines); llWhisper(0,"Baseline: "+baseline); llWhisper(0,"Dataline: "+dataline); } } } }
......
|