Non-blocking IO

Hi there,

I have a separate program that runs on the command line. When the program starts, it waits for input from std::cin and then gives a response. After the response, the program goes back to waiting for more cin.

I want to send this program some input (a string) from an oF app in a way that won’t block the oF app. Right now if I do something like ofSystem(“otherApp”) the oF app will just hang indefinitely while it waits for ofSystem to return. Ideally my oF app would be able to send and receive to and from this external program, while still doing it’s own thing. I guess the first step is to figure out how to actually send the other program input after starting it. The second step would be getting the result back somehow.

What’s the best way to do this? Should I spawn a separate thread and then pipe things in and out from there? I was looking into the pstreams library, but it seems that it wouldn’t solve this blocking issue.

Thanks in advance for the help!

If you need to send data back and forth, but not necessarily get responses for each message, why not set up a simple tcp connection between the two?

or you can use OSC protocol?

The outside application is non-oF and I was hoping not to modify it if at all possible. Surely there is a way to launch a separate application from within a threadedFunction? Is it trivial to set up a tcp or osc connection without the aid of oF?

In my tests it seems to just hang. Working off of the threadExample…

void threadedFunction(){
  if(isThreadRunning()){
    if(lock()){
      msg = ofSystem("outsideProgram"); //everything dies here
      unlock();
    }
  }
}

If you want to launch the other app and have the ofSystem cal return immediately, you can add an & after the program name. I.e. ofSystem(“outsideProgram &”);

Cheers!
Theo

@theo Yes I had tried that but it still seemed to hang.

I got this sort of working by sending the stdout of my oF app into the external app with a named pipe.

On terminal I can do:

mkfifo newPipe
path/to/cmdLineApp < newPipe

In another shell:

path/to/ofApp.app/Contents/MacOS/ofApp > newPipe

What I’m not sure about is how to pipe the other app’s output back into oF.

I was thinking I might be able to do something like

path/to/cmdLineApp < newPipe | path/to/ofApp.app/Contents/MacOS/ofApp

And then in my oF app do:

vector<string> lines;

void ofApp::update(){
  if(cin.rdbuf()->in_avail()){
    string str;
    getline(cin, str);
    lines.push_back(str);
  }
}

But in_avail() doesn’t ever seem to return true. What’s the preferred way to get cin in oF? If I don’t check to make sure there is something in cin, it will also block my app.

OK, think I got this sorted. I found an example of a nonblocking cin that seems to be what I need. I modified it a bit and put it up here for anyone interested.

The real good stuff is in this little bash snippet:

$ mkfifo /tmp/textPipe
$ </tmp/textPipe externalApp | ~/Desktop/of_v0.9.2_osx_release/apps/myApps/outIn/bin/outInDebug.app/Contents/MacOS/outInDebug > /tmp/textPipe    

Once my oF app is launched whatever I send to cout will get sent via textPipe to cin in my external app. Similarly, whatever my external app sends to cout my oF app will receive via regular pipe in cin.

Sort of janky but it works!