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!

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Devl mailing list
Devl@freenetproject.org
https://emu.freenetproject.org/cgi-bin/mailman/listinfo/devl

Reply via email to