On 2023-02-15 10:54, Niklas Holsti wrote:
> On 2023-02-13 21:48, Dmitry A. Kazakov wrote:
>> On 2023-02-13 17:26, Niklas Holsti wrote:
>>> On 2023-02-13 17:10, Dmitry A. Kazakov wrote:
>>
>>> But why should the RM define two "task" concepts that have exactly
>>> the same properties? Or should co-routines have some different
>>> properties? That was the point of my question, apologies if I was
>>> unclear.
>>
>> Ada has floating-point, fixed-point, universal real implementations of
>> the same concept of real number. Why?
>
> Of course because these implementations have /different/ properties,
> suitable for different uses. They are /not/ the same, and their
> differences are defined in the Ada RM.
The concept here is R, the set of real numbers.
> Perhaps you think that those differences are implicit in the term
> "co-routine", but I don't find it so, sorry.
Clearly co-routine and OS thread have different properties as
implementations of same concept of a "thread of control."
>> Rendezvous is asymmetric client-server. In a callback scenario parties
>> are equivalent. Each can wait for another. With tasks a protected
>> object is usually thrown in to work it around.
>
> Aha, so you are proposing that co-routines would have some other means,
> not protected objects, for symmetric inter-co-routine communication.
When you do blocking I/O you do not [explicitly] communicate with the
system PCI bus or whatever.
> What would that be, perhaps directly shared (unprotected) variables?
Nothing. When you call Ada.Text_IO.Put_Line, you just do that, File_Type
is not shared, not explicitly.
> Then you have to ensure that those co-routines are implicitly mutually
> exclusive, right?
Exclusive to what?
>> 1. To simplify "pipeline" stuff. Each side need not to know what the
>> other side does or each other. They know the pipeline. The programmer
>> should use a call or a timed entry call or a selective accept. I leave
>> that open for now.
>
> By "pipeline", do you mean an order-preserving stream of data from a
> producer to a consumer? If so, a simple protected queue or buffer
> between producer and consumer tasks implements it.
No it does not. I was talking about the pipeline ends, not about the
pipeline itself.
> By leaving the details open, you leave your proposal fuzzy and hard to
> understand.
You need an implementation writing a buffer of n bytes into a FIFO queue?
procedure Write (S : in out FIFO; X : Stream_Element_Array) is
From : Stream_Element_Offset := X'First;
begin
loop
Queue_Immediate (S, X (This..X'Last), From);
exit when From >= X'Last;
Wait_For_Not_Full (S);
From := From + 1;
end loop;
end Write;
The client code calls Write, which appears as a blocking call.
Should I provide another end too? (:-))
>> 2. To allow sharing context of a single OS thread. So the term
>> "co-routine."
>
> I don't think that property is implicit in the term "co-routine",
> because co-routines can exist even without OS threads.
In the same sense how System.Address can exist without a processor? (:-))
> But most importantly, this property cannot be used to /define/ the
> "co-routine" concept in the Ada RM. That definition may of course be
> /chosen/ so as to /allow/ this implementation.
See above. The concept here is thread of control.
> However, this property is already satisfied for "tasks" in those Ada
> systems that implement tasking in the RTS, without using multiple OS
> threads. So the current definition of Ada "tasks" already allows such
> sharing.
It does not support user implementations of tasks coexisting with the
OS-backed tasks. Certainly one possible way would be like it was done
with the access types and storage pools to provide an abstraction layer
for tasks. However, I think that could be a bit extreme.
>> 3. As I said above, the goal is to take plain I/O code (the client)
>> and reuse it with no adjustments with a server/provider/consumer in
>> place of the OS I/O subsystem.
>
> And that server/provider/consumer would be what?
See the pipeline example.
> Ada code in the
> application? Or part of the Ada RTS? Would it have to be aware of all of
> the OS I/O subsystem's services? For example, would it have to know
> about the socket interface to networking?
The library supplied implementation of Send (see Write above) will. The
client will call Send which in the case of non-blocking I/O will yield
in Wait_For_Not_Full above and resume upon a callback or explicitly by
the handler of the socket set. The co-routine case is having the handler
and many callers to Send ran by the same OS thread (or by a much
narrower pool of OS threads).