On 2021-01-11 21:35, Shark8 wrote:
> On Monday, January 11, 2021 at 8:32:25 AM UTC-7, Dmitry A. Kazakov wrote:
>> On 2021-01-11 15:59, Shark8 wrote:
>>> On Thursday, December 24, 2020 at 6:30:59 AM UTC-7, Dmitry A. Kazakov wrote:
>>>> On 2020-12-24 13:02, Maxim Reznik wrote:
>>>>> I forked a older (Garlic) GNAT DSA implementation and found it quite hackable. :)
>>>>> My idea is to implement a WebSocket/WebRTC transport and compile it by GNAT-LLVM to WebAssembly to have distributed Ada applications in a browser. I have a working proof of concept demo already :)
>>>>>
>>>>>
https://github.com/reznikmm/garlic/tree/web_socket
>>>> My question is how to proceed without GLADE/Garlic etc. I have DSA
>>>> implemented, e.g. System.RPC. I need GNAT to accept it as such.
>>> What do you mean by this?
>>> How is GNAT "not accepting" it?
>> It does not invoke the provided DSA implementation for remote calls.
> This is a dumb question, but did you remember to recompile the run-time library?
No. Why should I?
Do you mean that other implementations rebuild all RTL? That is a mess.
Is it possible to fool GNAT using linker instead of breaking everything?
>>> More, you mentioned the possibility of using a set of tagged-types, "like Storage_Pool", elsethread; is this how you implemented them, or a suggestion for a new standard interface?
>> It was a suggestion. The current way is System.RPC see ARM E.5. It seems
>> that merely replacing it is not enough for GNAT.
> Given "The package System.RPC is a language-defined interface to the PCS" it seems like that there are two readings:
> (1) System.RPC defines the forms with which remote-calls are done, and/or
> (2) implements the actual communications.
> As it is written, I would think that #1 is the proper interpretation, if this is the case than recompiling System.RPC is "mucking about with the interface" and not much else.
My understanding is that the Do_RPC gets called with the parameters of
the call written into the Params stream including the target function
name. Then you do communication with the remote host associated with the
Partition parameter. The communication basically reads the Params stream
and sends read stuff to the other side. Then you sit and wait for the
remote host to respond. If the response was success, you write its
payload into the Result stream. If the response indicates remote
exception you re-raise it locally.
BTW, there is a lot of overhead there. The design support streams being
actual communication streams. But for that, the partition would be set
into the stream prior calling to the first Write. Furthermore, it is to
tightly coupled. There is no indications where parameters start and end
in the stream. The remote host needs to be able to say "cut that, I do
not receive this call anyway", "I cannot parse parameters for this
function" etc.
>>>> In a more distant perspective I need a work-around of stream attributes.
>>>> They are non-portable, so there must an option to replace them for DSA
>>>> and/or provide a non-stream parameter marshaling when the transport is a
>>>> higher-level protocol, e.g. CANopen, EtherCAT, ASN.1, AMQP etc. For
>>>> these you must map Ada types into the types defined by the protocol.
>>> I have some ideas on how this could be achieved.
>>> I'll make a note for my To-Do list on Byron, but I was thinking that a good method to achieve this for an OS (WRT ASN.1) would be to have at the base a SOM-like system with the base meta-object having a serialize/deserialize pair of methods (with one parameter being the encoding scheme)...
>> The problem is that
>>
>> 1. They must doubly dispatch on the object type and on the container
>> type, since there could be any number of containers = encoding/decoding
>> schema.
> Why?
> You could have the encoding/decoding method as a parameter.
A scalar value is not enough. For one you need to enumerate all possible
methods to build a case statement on them, which you cannot do as
implementation must be located in different libraries.
Then you need some context to encode/decode referential types. Imagine a
parameter containing an access type, e.g. a node of a linked list. You
cannot deep-copy everything with an infinite recursion on top.
>> 2. They must support chunking. E.g. deserialize cannot be a function.
> Why?
Because it will block waiting all data read. So you will need an extra
task for each transfer in order to accumulate all chuncks.
>> This will get you a whole bunch of nasty problems with partial
>> serialization and indefinite types. [I do not see these resolved without
>> properly done constructors and co-routines.]
> I don't see why the partial-serialization is a problem: if you have some type's value to serialize, you're already constrained.
> If you're reading from a stream to initialize/reconstruct a type-value, then you're doing X'Stream'Input, right?
Remember, it does not block. So when you call X'Stream'Input you may get
0 stream elements read at any point. E.g. you read a 4-octet Integer.
You get only two octets, because the other two are not here. You cannot
return Integer, it is not yet constructed. You cannot wait, because you
are in the callback from the reader task. You must remember the state of
partial deserialization and pass control back to the reader. This is
what a co-routines are.