One piece that is currently missing is a discussion of which lightweight
concurrency model we're going to use for the asynchronous operations.
I've had ongoing back-channel conversations with various people, but I
need to congeal them. Pitch in your own 2 cents.
Also, any reactions to the distinction that async ops return status
objects while sync ops return integer error codes? Sync opcodes could
have 2 signatures, one with an integer return type (int error code) and
one with a PMC return type (status object).
Allison
> Also, any reactions to the distinction that async ops return status
> objects while sync ops return integer error codes? Sync opcodes could
> have 2 signatures, one with an integer return type (int error code) and
> one with a PMC return type (status object).
PMCs do have integer values too; perhaps unifying them to return always PMCs
and then checking the intval would do.
-- c
What's the relative cost of creating a PMC vs passing one in?
I assume passing one in is significantly faster.
If so, then perhaps speed-sensitive ops that are likely to be used in
loops can be given the PMC to (re)use.
Tim.
I/O Stream Opcodes
I really don't like opcodes, when dealing with I/O.
1) opcodes are needed for native int or float - these are nicely JITtable
2) opcodes with PMCs usually call a vtable function that provides necessary
virtualization/abstraction:
set S0, P0[10] # VTABLE_get_string_keyed_int
If a particular PMC doesn't support the vtable function an exception is
thrown.
Now compare this with an I/O opcode:
read S0, P0, 10 # PIO_reads(... P0 ...)
If P0 isn't a ParrotIO opcode, this segfaults. See t/pmc/io_1.pir. While we
could of course check, what type P0 is, such a check would be needed for
every IO opcode. (And see below)
3) opcodes don't work with inheritance, unless a vtable (or method) is
provided.
subclass P1, 'Array', 'MyArray'
new P0, 'MyArray'
set S0, P0[10] # VTABLE_get_string_keyed_int
The vtable still works, and possibly calls a '__get_string_keyed_int' method,
if the 'MyArray' class provides one.
But:
subclass P1, 'ParrotIO', ['HTTP'; 'Daemon'; 'ClientConn']
...
read S0, P0, 10 # P0 be a ClientConn now
Given this, we would have to modify the mentioned check, to also deal with
subclasses of 'ParrotIO'. And worse, the IO opcode would need some knowledge
about the subclassed ParrotIO to extract the raw PIO structure to carry on
with the IO PIO_reads function call. This either violates encapsulation or
would need another interface to deal with it.
4) Then we should call a method from the opcode?
op read(out STR, invar PMC, in INT) {
STRING *meth = Parrot_find_method_with_cache(...)
if !(meth) {
# error handling
}
$1 = Parrot_run_meth_fromc_args(...);
# or alternatively
# emulate set_args
# emulate get_results
pc = VTABLE_invoke(...)
...
}
That is, we'd re-implement the 'callmethodcc' opcode for every IO opcode,
without any further improvement. Just the opposite. We would add code
duplication, and we'd possibly add a Continuation barrier by adding this
indirection.
5) I/O layers
When we look at ParrotIO as an object with methods, the layering boils down to
simple inheritance. Adding a layer is just a subclass operations, where some
methods are overridden. All the extra code that deals with layers is likely
unnecessary then. Or IOW the I/O layer models mimicks some class
functionality, which should better be done by existing class code.
6) Sockets
Currently the socket API is part of the PIO virtual function table. This is
suboptimal, as the socket API is exposed to non-socket PIOs as well.
ParrotSocket isa ParrotIO
BufferedIO isa ParrotIO
...
or some such would be a better choice. The Perl5 equivalences are probably a
good model for this.
> Allison
my 2c,
leo
Are you referring to the Parrot side API, the actual implementation, or
both? As for the implementation side, my gut feeling is that this is
going to need to be highly platform specific. For example, on Linux
using POSIX aio (assuming a new enough kernel) is probably going to
incur much less over head then either clone(2) or POSIX threads. As a
point of reference I believe Linux::AIO uses clone(2) but it predates
the POSIX aio layer.
-J
--
> Now compare this with an I/O opcode:
>
> read S0, P0, 10 # PIO_reads(... P0 ...)
>
> If P0 isn't a ParrotIO opcode, this segfaults. See t/pmc/io_1.pir. While we
> could of course check, what type P0 is, such a check would be needed for
> every IO opcode. (And see below)
I don't buy this argument. If the cost for checking the type of P0 is greater
than the cost of doing IO, that's a big problem and not with the interface.
-- c
A wasn't talking about costs at all. I'm talking about unneeded code
duplication, sanity and inheritance. In fact, the proposed method interface
will be slower (currently) - I really don't care.
leo