* The problem was a race caused by HeartbeatReq sent out, and
the watchee terminated immediately. That caused the RemoteWatcher
peers watching each other without any other watch registered.
It is racy.
* Instead of one-way heartbeats from the side beeing watched I
changed to ping-pong style. That makes the problem go away
and simplifies a lot of things in RemoteWatcher.
- based on a wheel (AtomicReferenceArray) from which atomic
single-linked lists dangle
- no locks
- deterministic tests due to overridable time source
- also bring docs up to date
This means tightening types from Duration to FiniteDuration in several
places; a good thing, since we replace runtime complaints by compile
time errors.
- it’s a completely new-written thing in pure Java, so that “protected”
modifiers actually work and no ghost errors appear wrt. inheriting
from PartialFunction or similar
- it also features integration with the EventFilter
- all closure-based constructs are modeled as inner classes of the
JavaTestKit, where the user needs to override a single method which
will then be executed
- introducing RepointableActorRef, which starts out with an
UnstartedActorCell which can cheaply be created; the Supervise()
message will trigger child.activate() in the supervisor, which means
that the actual creation (now with normal ActorCell) happens exactly
in the right place and with the right semantics. Messages which were
enqueued to the dummy cell are transferred atomically into the
ActorCell (using normal .tell()), so message sends keep working
exactly as they used to
- this enables getting rid of the brittle synchronization around
RoutedActorRef by replacing that one with a RepointableActorRef
subclass which creates RoutedActorCells upon activate(), with the nice
benefit that there is no hurry then to get it right because the new
cell is constructed “on the side”
misc fixes:
- InvalidMessageException is now actually enforced when trying to send
“null”
- Mailboxes may be created without having an ActorCell, which can come
in handy later, because the cell is only needed when this mailbox is
going to be scheduled on some executor
- remove occurrences of Props(), which is equivalent to Props[Nothing],
which is equivalent to «bug»
- add test case which verifies that context.actorOf is still synchronous
- plus all the stuff I have forgotten.
- do not use futures, do not use different executors
- only use Poll token; schedule OR poller.poll in case of no message
available, depending on the sign of the poll timeout
- restructure receive method to avoid PartialFunction.orElse overhead