comp.lang.ada
 help / color / mirror / Atom feed
From: "Alejandro R.  Mosteo" <alejandro@mosteo.com>
Subject: Re: Musings on RxAda
Date: Thu, 22 Oct 2015 13:02:46 +0200
Date: 2015-10-22T13:02:46+02:00	[thread overview]
Message-ID: <n0afkm$ssa$1@dont-email.me> (raw)
In-Reply-To: d3f6518f-78be-42aa-bac4-3cd7b1bf3248@googlegroups.com

Hadrien Grasland wrote:

> Le mercredi 21 octobre 2015 21:35:26 UTC+2, Dmitry A. Kazakov a écrit :
>> On Wed, 21 Oct 2015 12:09:58 -0700 (PDT), Hadrien Grasland wrote:
>> 
>> > So you would essentially store a pipeline of data and operations in
>> > some container, then perform all of them on the same thread when the
>> > output of the pipeline is requested ?
>> 
>> I don't know your requirements. In a FIFO scenario, yes, the publisher
>> pushes the object. The subscriber pulls it out. In a blackboard scenario
>> (non-blocking) the publisher pushes the object and the subscribers scan
>> the blackboard for updates.
>> 
>> Of course in a modern typed language like Ada you would not mess with
>> "data and operations." There are objects for that. The type of the object
>> determines the operations.
>> 
>> > This seems much more complex to implement to me, since your operation
>> > queue needs to be able to store data of any type and operation function
>> > pointers, all in a type-safe way. As far as I can tell, you cannot use
>> > streams for that because a stream requires you to know what you are
>> > reading from it.
>> 
>> That is because you are trying to think about it in terms of C. Ada is
>> not C, luckily. It is quite straightforward to marshal T'Class objects
>> with a dispatching operation Do_It. And yes, it is as much easy to
>> marshal handles to reference-counted objects if objects are expected
>> large (and you have shared memory).
>> 
>> --
>> Regards,
>> Dmitry A. Kazakov
>> http://www.dmitry-kazakov.de
> 
> Ah, I see. I agree that an object oriented solution could indeed solve
> this serialization problem well !

Thank you for your musings, both of you. I guess we would all need to have a 
firmer grasp of ReactiveX semantics for more accurate speculation.

Anyway, to not leave it here, I can precise that indeed the observable-
subscriber relationship is 1:n. As I understand it, the decoupling may 
happen at every observable (but it's not mandatory). 

I omitted a piece of information that I see now is fundamental here. When an 
Observable has a new piece of data (or when you override an Operator), it 
will call the onNext(datum) method of its subscribers. So there is a push 
mechanism. Indeed there are also operators to deal with "backpressure" (too 
fast data emission by an observable).

This means that if your operation is fast it needs not to be asynchronous, 
but it could be if desired and there are also operators to force it. For 
example (sorry about the pseudocode, not Java nor Ada):

Observable.fromClickEvents(SomeButton)
    .onWorkerThread()  -- To ensure we are not blocking the GUI thread
    .count(during => one_second) -- This could be any costly operation
    .onGuiThread()               -- Switch back to GUI thread
    .subscribe(count -> SomeTextLabel.setText(count));

This would count clicks on a button and output the count every second in a 
GUI field.

What I see interesting of this methodology is that it basically hides (in 
theory, of course then you read about nightmare histories) the explicit 
definition of tasks, problems with race conditions and data integrity, 
because these aspects are within the implementation of the base Observable, 
Operator and Subscriber objects, and the user sees only a pipeline of data 
being transformed that can jump from thread to thread as needed, and without 
blocking any other threads (as long as synchronization is not needed, I 
guess). This, in languages which such poor high-level concurrency built-in 
mechanisms like C++ or Java, is a blessing.

The power of the setup comes with the huge number of predefined operators 
that exist in the library. It's the closer to "chaining blocks" in something 
like Simulink I've experienced in code. But then, I stress, the syntax of 
Java 8 is mandatory or else you get a nightmare of boilerplate code also, 
which is what worries me about an Ada implementation.

I have a vague notion in my head that, in Ada, by using generics one could 
have all the boilerplate in instantiations and keep the chain definition 
terse (which is the goal) and with type safety. But still the function 
bodies would have to go elsewhere (unlike in the last line of the example 
above).

I see a parallelism on how the new syntax in Ada 2012 for looping over 
containers cuts down on boilerplate enormously, enabling having the actual 
loop body code in the loop. And if you look at any example on how to achieve 
this for your own types, there is indeed quite the boilerplate, but you do 
it once to spare it from your library users.


  reply	other threads:[~2015-10-22 11:02 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-14 14:30 Musings on RxAda Alejandro R.  Mosteo
2015-10-15 14:40 ` brbarkstrom
2015-10-21 11:45 ` Hadrien Grasland
2015-10-21 12:12 ` Hadrien Grasland
2015-10-21 13:35   ` Dmitry A. Kazakov
2015-10-21 16:18     ` Hadrien Grasland
2015-10-21 16:47       ` Dmitry A. Kazakov
2015-10-21 19:09         ` Hadrien Grasland
2015-10-21 19:35           ` Dmitry A. Kazakov
2015-10-21 21:04             ` Hadrien Grasland
2015-10-22 11:02               ` Alejandro R.  Mosteo [this message]
2015-10-22 12:33                 ` Dmitry A. Kazakov
2015-10-22 16:41                   ` Alejandro R.  Mosteo
2015-11-19 13:14 ` Jacob Sparre Andersen
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox