assert !actor.equals(LocalActor.self()) : "Can't \"call\" self - deadlock guaranteed";
if (m.getFrom() == null || LocalActor.isInstance(m.getFrom(), TempActor.class))
m.setFrom(from());
final Actor currentActor;
final boolean tmpActor = m.getFrom() instanceof TempActorRef;
if (tmpActor)
currentActor = (Actor) ((TempActorRef) m.getFrom()).getImpl();
else
currentActor = Actor.currentActor();
assert currentActor != null;
final Object watch = currentActor.watch(actor);
if (m.getId() == null)
m.setId(watch);
final Object id = m.getId();
final SelectiveReceiveHelper<Object> helper = new SelectiveReceiveHelper<Object>(currentActor) {
@Override
protected void handleLifecycleMessage(LifecycleMessage m) {
if (m instanceof ExitMessage) {
final ExitMessage exit = (ExitMessage) m;
if (Objects.equals(exit.getActor(), actor) && exit.getWatch() == watch)
throw Exceptions.rethrow(exit.getCause());
}
super.handleLifecycleMessage(m);
}
};
try {
actor.sendSync(m);
final ResponseMessage response = (ResponseMessage) helper.receive(timeout, unit, new MessageProcessor<Object, Object>() {
@Override
public Object process(Object m) throws SuspendExecution, InterruptedException {
return (m instanceof ResponseMessage && id.equals(((ResponseMessage) m).getId())) ? m : null;
}
});
currentActor.unwatch(actor, watch); // no need to unwatch in case of receiver death, so not done in finally block
if (response instanceof ErrorResponseMessage)
throw Exceptions.rethrow(((ErrorResponseMessage) response).getError());
return ((ValueResponseMessage<V>) response).getValue();
} catch (InterruptedException e) {
if (tmpActor)
currentActor.checkThrownIn();
throw e;
} finally {
// if (tmpActor)
// ((TempActor) m.getFrom()).done();
}