From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!mx02.eternal-september.org!.POSTED!not-for-mail From: "Alejandro R. Mosteo" Newsgroups: comp.lang.ada Subject: Re: Musings on RxAda Date: Thu, 22 Oct 2015 13:02:46 +0200 Organization: A noiseless patient Spider Message-ID: References: <75f38e30-42ba-4e98-8f36-2218b5167209@googlegroups.com> <1wvo1b25eaa4o$.1y03vu1to6vux$.dlg@40tude.net> <18xpt5oxiz5nw$.klh515586pjp.dlg@40tude.net> <3a82a370-2175-4cf6-90e1-64fb19d794ff@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8Bit Injection-Date: Thu, 22 Oct 2015 11:00:38 +0000 (UTC) Injection-Info: mx02.eternal-september.org; posting-host="826cc6ce18acb660eb2ad190ef62dc45"; logging-data="29578"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18wO4LEfRj9w9Zm9/SWP/6r" User-Agent: KNode/4.14.1 Cancel-Lock: sha1:bTXx/iwrF3LXwKkxESZ4swkbhAU= Xref: news.eternal-september.org comp.lang.ada:28033 Date: 2015-10-22T13:02:46+02:00 List-Id: 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.