I've been doing some prepping and I put together some quick and very dirty prototypes yesterday and think I have a plan about how to make this work. My plan involves a few changes to PDD22, so I want to get some feedback about all that before I do anything.
1) I don't want to have an asynchronous version of the "open" opcode. 2) We're going to need to open streams in either synchronous or asynchronous mode. I'm proposing we use an "n" mode flag for non-blocking and a "b" flag for blocking. This way we can use existing methods "read" and "write", etc to do what we want. 3) Add an "is_async" method to stream objects to return whether the stream was opened async or not 4) We can call a non-asynchronous opcode with an asynchronous stream, and vice-versa, though the PDD suggests that we cannot (or should not). 4a) Calling a non-blocking op with a synchronous stream performs the synchronous operation, calls the callback immediately, and returns a status object that already reads "complete". Relatedly, this kind of behavior is how we will simulate AIO on systems that don't support it. 4b) Calling a blocking op on an async stream launches the request but doesn't return a status object to track it. Launch it and forget it. 5) We're going to create an IO polling mechanism to keep track of requests. The polling mechanism will be polled from the scheduler, in addition to being polled manually. When a request is completed, the associated callback Task is scheduled. The PDD doesn't disagree with this, it just doesn't mention any implementation details like this. I'd also very much like to hear some feedback about how people expect to actually USE this system from PIR. Here are some examples that I am envisioning, but I want to hear if other people think they are useful: $P0 = open "filename", "nr" # open in "non-blocking" mode $P1 = read $P0, 10, $P2 # read with a callback ($P2) and a request status object ($P1) check: unless $P1 goto check # block until the operation completes $S0 = $P1.'return_value'() # Get the string $P0 = open "filename", "br" # open in "blocking" mode $P1 = read $P0, 10, $P2 # the stream is blocking. Do the read, call the callback, return a "complete" status object check: unless $P1 goto check # Already complete, basically does nothing $S0 = $P1.'return_value'() # Get the string $P0 = open "filename", "nw" # open in "non-blocking" mode $P1 = write $P0, "hello", $P2 # Write with a callback and a status object check: unless $P1 goto check $I0 = $P1.'return_value'() # get number of bytes written Also, some error handling: $P0 = open "filename", "nr" # open in "non-blocking" mode $P1 = read $P0, 10, $P2 # read with a callback ($P2) and a request status object ($P1) check: unless $P1 goto check # block until the operation completes $P1.'throw'() # Throw exception if there's an error, nothing otherwise Or, $P0 = open "filename", "nr" # open in "non-blocking" mode $P1 = read $P0, 10, $P2 # read with a callback ($P2) and a request status object ($P1) check: unless $P1 goto check # block until the operation completes $I0 = $P1.'status'() # -1 = error, 0 = pending, 1 = success if $I0 == 1 goto success $S0 = $P1.'error'() # get the error message string say $S0 success: Also, the callback functions will take a single parameter, the status object. In this way we don't need to poll the request status, we can let the callback tell us when it's done: .sub iocallback .param pmc iostatus $I0 = iostatus.'status'() ... # do something with the status result here. .end So, I would really like to get some feedback here, to make sure I am looking at this in a reasonable way, and that it's meeting the needs of the potential users. --Andrew Whitworth _______________________________________________ http://lists.parrot.org/mailman/listinfo/parrot-dev
