: : Windows can do AIO, but as per usual it's just done differently to the way your average POSIX platform does it.
:
: From what I've read, the WinSock sockets aren't true file descriptors (or something to that effect). Therefore the WinSock library provides its own functions for the AIO. When implementing the select module for python, I guess since sockets were the most common application for which the select() function would be used they decided to use the WinSock functions instead of the File/Pipe functions.
:
File APIs can hanlde AIO too, from what I remember. ReadFileEx and WriteFileEx support it, for sure. You use the same APIs to read/write pipes, but I don't know if they are handled by the AIO stuff and if they are I seem to rememeber it was only available from NT and onwards, and I wanted to support 9x OSes too.
: : Plenty of odds and ends going on in the work towards the next release, which I believe will happen in about a months time. I've only managed a measely three patches so far this release. Stuff of note:-
: : * Loads of discussion about strings, unicode and all that ungliness. Some stuff here got implemented. ICU got chucked for a range of reasons.
:
: What is ICU?
:
International Components for Unicode. Basically, a unicode implementation. However, it had build issues on a lot of platforms Parrot was to run on, and the opinion seemed to be that it did way too much platform specific stuff for what essentially should be a "character twiddling library".
: : * Improvements to register allocation stuff in IMCC.
:
: Don't know what that means.
:
The Parrot Virtual Machine has at its center something a bit like a CPU, but done in software - I guess we could call it a software CPU. Like a hardware processor has registers, so does Parrot. Unlike in hardware, Parrot has 4 types of register (integer, number, string and PMC[1]) and 32 of each of those.
When you're writing a bit of software that's non-trivial, you'll run into the problem that you have more "variables" than you do registers. Thefore you need to do register spilling (saving registers elsewhere). Register allocation is basically the process of working out the best way to do this.
When you write in PASM (Parrot assembly) you have to take care of this yourself, but IMC (Intermediate Code) removes this responsibility from the programmer (and the compiler writer targetting Parrot). IMCC (the intermediate code compiler) thus has to do all of the register allocation stuff. Extremely big blocks of code can make this process exceptionally slow, because the algorithms are non-linear (quadratic order, to my knowledge). Some improvements have been made to the algorithms, but there's still work to be done. I think the big thing to do is to get the algorithm to realise when it's trying to hard and just resort to a simple, unintelligent way of doing register allocation that at least gets the job done in a reasonable amount of time, even if the code is less efficient when executed.
: : Dan Sugalski also made this very scary observation:-
: :
: : --
: : 1) We're going to have MMD for functions soon
: : 2) Function invocation and return continuation invocation's
: : essentially identical
: : 3) Therefore returning from a sub/method can do MMD return based on
: : the return values
:
: Not sure what MMD is or why it's scary.
:
Multi-method dispatch. Sorry, I should use less acronyms. It's basically the idea that imagine I did the following (in a pseudo-language (that accidentally looks very much like C++ (which I don't know (damm, this is starting to look like Lisp

)))):-
void myMethod(int a) { ... }
void myMethod(double a) { ... }
void myMethod(char *a, int b) { ... }
Then when I called the function myMethod, MMD would look at the available method signatures (parameter type list) and find the one that matched what was being passed most closely and then call that method.
: : I guess this is an upshot of using a continuation calling scheme...
:
: If you say so

:
Continuations are strange enough alone without MMD stuff. A continuation is basically a bit like a closure that also closes over the control flow. What the heck does that mean? Well, it took me a while to figure that one out too.

When you take a continuation, you are saving the current lexical state (e.g. all lexical variables - meaning no global variables are involved here) and the call stack at that point. This means that when you invoke the continuation, you essentially end up back where you were where you started with the same lexical state. However, the global context may have changed. For example, the data held in an object you had a lexical reference too may have changed, but you'll still have the reference. Global variables won't be the same.
When you call a function, you need to save some state, from simple things like a return address to all kinds of other stuff. The problem that was realised was that if you wanted to add other stuff to be saved in the future, then you'd probably have to change the calling conventions - a big pain. A continuation is good at saving state and a standard way of doing it, however. So a continuation passing scheme was used.
Basically, you take a continuation, called the return continuation, and pass it to the thing you're calling. When you want to return from the function, you simply invoke the return continuation, and you're back where you were (of course, internally Parrot must be careful you're sent back after the function call itself happened, otherwise you'd end up in an infinite loop - I don't know the gory details of how that bit is handled).
I hope this kind of puts into context what Dan was talking about. I'm not sure I fully understand the real possibilities of this yet, but at least it's not as mind-numbing as serializable continuations, which Parrot will apparently have too.
Jonathan
[1] PMC = Parrot Magic Cookie. It's basically for more complex data types, e.g. arrays, objects, classes, etc. Like objects, they have a vtable.
###
for(74,117,115,116){$::a.=chr};(($_.='qwertyui')&&
(tr/yuiqwert/her anot/))for($::b);for($::c){$_.=$^X;
/(p.{2}l)/;$_=$1}$::b=~/(..)$/;print("$::a$::b $::c hack$1.");