We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProcessing DevelopmentCore,  Processing Development Environment (PDE) › help me finish my requestStrings PApplet extension
Page Index Toggle Pages: 1
help me finish my requestStrings PApplet extension (Read 3422 times)
help me finish my requestStrings PApplet extension
Jun 10th, 2009, 12:53am
 
Hey folks i am a little stuck here.  I have looked at requestImage and how it async loads images.  Then i used that as a template to make a similar requestStrings version of loadStrings i.e async loadStrings.  

All is good and generally i think it works however i cannot get the String[] address back to my test harness.  Any help finishing this off would be excellent...

public String[] requestStrings(String filename) {
           return requestStrings(filename, null);
     }
     
     
     public String[] requestStrings(String filename, String extension) {
           String vessel[] = null;
           AsyncStringsLoader ail =
           new AsyncStringsLoader(filename, extension, vessel);
           ail.start();
           println("requestStrings(String filename, String extension) { vessel ="+vessel+"");
           return vessel;
     }
     
     
     
     public int requestStringsMax = 4;
     volatile int requestStringsCount;
     
     class AsyncStringsLoader extends Thread {
           String filename;
           String extension;
           String vessel[];
           
           public AsyncStringsLoader(String filename, String extension, String vesselIn[]) {
                 this.filename = filename;
                 this.extension = extension;
                 this.vessel = vesselIn;
                 println("AsyncStringsLoader extends Thread vesselIn ="+vesselIn+" this.vessel = "+this.vessel+"");
                 
           }
           
           public void run() {
                 while (requestStringsCount == requestStringsMax) {
                       
                       println("in  AsyncStringsLoader run() WHILELOOP requestStringsCount = " +requestStringsCount+ " filename = " +filename+ "");
                       
                       try {
                             Thread.sleep(10);
                       } catch (InterruptedException e) { }
                 }
                 requestStringsCount++;
                 
                 println("in  AsyncStringsLoader run() requestStringsCount = " +requestStringsCount+ " filename = " +filename+ "");
                 String actual[]= loadStrings(filename);
                 
                 // An error message should have already printed
                 if (actual.length == 0) {
                       println("error occured in AsyncStringsLoader");
                       
                 } else {
                       println("aha!! length = " +actual.length+" string[0] =" +actual[0]+" vessel = "+vessel+" actual = "+actual+"");
                       vessel = actual;
                       println("aha NUM 2!! length = " +actual.length+" string[0] =" +actual[0]+" vessel = "+vessel+" actual = "+actual+"");
                 }
                 requestStringsCount--;
           }
     }
Re: help me finish my requestStrings PApplet extension
Reply #1 - Jun 10th, 2009, 1:34am
 
You cannot do that. Not this way...
You pass the reference of an empty array (ie. null), you cannot allocate a new array (that's what loadStrings() does) and assign it to the parameter of the function (it would change the reference).
You need either to wrap the array in an object, or say your requestStrings acts on an ArrayList instead. It is easy to convert it to array afterward, or just use the ArrayList anyway.
Re: help me finish my requestStrings PApplet extension
Reply #2 - Jun 10th, 2009, 8:40am
 
Something I worked on before, if it helps...

The problem with my version is that you have to know how many lines beforehand.

http://processing.org/discourse/yabb2/num_1227644714.html

You could also try this
Code:
BufferedReader reader = null;
boolean fileIsWaiting = false;

Vector inp = new Vector();

boolean connectFile(String fname) {
try {
reader = createReader(fname);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}


void resumeLoading(Vector target) {

try {
String intext = reader.readLine();

//You could also read a few lines at a time to make it faster

if (intext != null) {
target.add(intext);
} else {
doneWithFile();
}

} catch (Exception e) {
e.printStackTrace();
doneWithFile();
}

}


void doneWithFile() {
try {
reader.close();
println("Done loading modules");
} catch (Exception e) {
e.printStackTrace();
println("Broke down when closing module file");
}
fileIsWaiting = false;
}


void setup() {
size(512,256);
textFont(createFont("Arial",12));

fileIsWaiting = connectFile("file.txt");//open file

frameRate(30);
}


void draw() {
background(0);
if (fileIsWaiting) {
resumeLoading(inp);
}

text("Loaded strings: " + inp.size(), 20, 20);
}
Re: help me finish my requestStrings PApplet extension
Reply #3 - Jun 10th, 2009, 4:54pm
 
PhiLho  wrote on Jun 10th, 2009, 1:34am:
You cannot do that. Not this way...
You pass the reference of an empty array (ie. null), you cannot allocate a new array (that's what loadStrings() does) and assign it to the parameter of the function (it would change the reference).
You need either to wrap the array in an object, or say your requestStrings acts on an ArrayList instead. It is easy to convert it to array afterward, or just use the ArrayList anyway.


Wrapping the array in an object could be a nice way to do it since that object could provide a member function with the means to check if it's finished loading the entire array of strings.

You'd just allocate the object at the start of the function like you were trying to do to begin with, create the thread with a reference to that object and return the object. The thread would load all the strings, assign them to the object and set a flag on the object as complete.

Also, you may want to think about if you should maintain a single thread for async string loading, as programmers may spam your function and cause way too many threads to kick off which incur an expensive start up cost. Creating a job queue to accumulate files and objects to load with a thread that persists in a yielding state is a better solution.

Re: help me finish my requestStrings PApplet extension
Reply #4 - Jun 10th, 2009, 10:37pm
 
hey so this is what i came up with..thanks for the help guys.  It's seems to work but i haven't done rigorous checking yet.

public class RequestStringsHolder{
           
           public String vessel[];
           int loaded;
           
           public RequestStringsHolder() {
                 
                 loaded = -1;
           }
           
           public int getLoaded()
           {
                 return(loaded);
           }
     }
     
     
     public RequestStringsHolder requestStrings(String filename) {
           
           RequestStringsHolder holder = new RequestStringsHolder();
           return requestStrings(filename, null, holder);
     }
     
     
     public RequestStringsHolder requestStrings(String filename, String extension, RequestStringsHolder holder) {
           AsyncStringsLoader ail =
           new AsyncStringsLoader(filename, extension,holder);
           ail.start();
           
           return holder;
     }
     
     
     public int requestStringsMax = 4;
     volatile int requestStringsCount;
     
     class AsyncStringsLoader extends Thread {
           String filename;
           String extension;
           RequestStringsHolder holder;
           
           public AsyncStringsLoader(String filename, String extension, RequestStringsHolder holder) {
                 this.filename = filename;
                 this.extension = extension;
                 this.holder = holder;
                 
           }
           
           public void run() {
                 while (requestStringsCount == requestStringsMax) {
                       
                       
                       try {
                             Thread.sleep(10);
                       } catch (InterruptedException e) { }
                 }
                 requestStringsCount++;
                 
                 holder.vessel = loadStrings(filename);
                 
                 // An error message should have already printed
                 if (holder.vessel.length == 0) {
                       holder.loaded = 0;
                       
                 } else {
                       
                       holder.loaded = 1;
                 }
                 requestStringsCount--;
                 
                 
           }
     }
     
Re: help me finish my requestStrings PApplet extension
Reply #5 - Aug 13th, 2009, 6:06am
 
So now you understand why requestStrings() isn't in the API. Wink

The best method (in terms of a "standard" method) would be to stuff the results into an ArrayList of String objects, though I haven't figured out a good way to signal when an error occurs. You can at least lock the list and only fill it once you have all the strings (e.g. as long as size() == 0, you know they haven't loaded) but there's no way to say size() == -1 or something like that. Though I guess you could make the first String returned be something like "error" (or something more specific than that, since "error" could conceivably be in the text file being read). If you can put null entries in an ArrayList, that'd be a good option too, since loadStrings() doesn't return null lines.
Page Index Toggle Pages: 1