p0s's report for last week talks about synchronous FCP calls and IMHO goes in completely the wrong direction:
======= Unfortunately, by logging I discovered yet another semi-architectural issue: The code which deploys events in SubscriptionManager does so via asynchronous FCP-calls. This means that they can arrive out of order at the client. And out-of-order events will trigger the same issue which we had when unit-testing event-notifications for the first time: Events such as creation of Trust objects might arrive before the Identity objects which reference them are created by other events. I am calling this “semi”-architectural because the issue of out-of-order events has been dealt with by implementing a per-client ordered event-queue when I first discovered the issue with unit tests. It merely was forgotten to actually ensure that the sending of the FCP messages to the client has to wait for the send to finish. As I had elaborated in a previous report, there are no synchronous FCP send() functions. I had also argued that this is a lack because many client applications need synchronous calls and have implemented them on their own. Given that I today discovered another reason for implementing them, I started doing so. The existing asynchronous send() function spawns a Thread which processes the send and doesn't wait for it to exit. So the logical way of implementing a synchronous send would be to wait for this thread to complete. Unfortunately, we cannot just join() the thread because it isn't actually a thread but a Runnable, so there is no join. Therefore, I reached the point of having to implement an inter-thread notification mechanism – which is the root of the reason why it took almost the whole day: I had done so previously in Freetalk's wrapper for synchronous FCP calls, and it was rather buggy. So I decided to do it right this time by first reading the whole chapter on Java multithreading in a Java book (http://openbook.galileodesign.de/javainsel5/javainsel09_000.htm). This was a good idea as I learned that the wait()/notify() mechanism which I had used in the past is Java 1.0 style and there is a new mechanism which fits what we are trying to do better: The “Condition” class. One can obtain a Condition object from a Lock object, and the Condition object allows: - one (or more) thread to wait for the condition to become satisfied - one (or more) thread to signal that the condition is satisfied now In our terms, the condition is “the FCP call has finished”. Unfortunately, in my opinion the implementation of Condition is imperfect because the await() functions can wake up spuriously even if the condition is not satisfied, so there still needs to be a separte mechanism (for example a boolean) for telling whether the condition actually is met. Therefore it will wind up to look almost the same as a wait()/notify() mechanism. Nevertheless, it has the bonus of providing an await() function which cannot throw InteruppedException, so there is one less issue to deal with. The resulting synchronous caller looks like this: https://github.com/freenet/fred-staging/commit/b9df63833c297e2eb8673b1f0a2dfc6582a53f75 I've currently only implemented it for plugins which are running in the same node, the implementation of synchronous communication via over-the-network FCP will be completely different and probably more difficult because it is wired in more deeply into the node. As a result of synchronous communication, the bugs which were caused by out-of-order notifications disappeared, so I was right about their cause and can continue debugging the remaining issues on Monday. ======= The stuff on synchronous in-fred notifications is hideous and non-network-transparent. Having said that I haven't read the code, but it sounds hideous. You should have some sort of request/response using an identifier, like the main fred FCP does. Or a sequence number or something. IMHO mechanisms that only work internally should be avoided given that everything else we do with FCP is, if not actually network-transparent, then could easily be made so. But certainly you could provide library code to wait for a single response using a known identifier field; ideally the code for using plugins would be network transparent via an official java library so it could use the hack you're doing if it's internal... in fact, that's wrong: it's a different concept. What we should do is wait for a reply to the specific question we asked (i.e. wait for a message with the correct label), rather than "wait for the function to return" - I mean, what function? Well written code only hogs threads when there is a clear benefit in code simplicity. Feel free to ignore me though, I don't have time to code a proper solution. But there was a strong belief at the conference that we should try to limit the further accumulation of layers of dirty hacks, and try to get rid of some of the existing ones. Especially as the FCP API for WoT is necessarily in flux at the moment. Sorry if this gets in the way of your plans, but I think it should be discussed. Thanks!
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Devl mailing list Devl@freenetproject.org https://emu.freenetproject.org/cgi-bin/mailman/listinfo/devl