package org.elixir_lang;
import com.ericsson.otp.erlang.*;
import org.apache.commons.lang.NotImplementedException;
/**
* Emulates behavior of the `gen` Module in Erlang
*/
public class Generic {
/**
* Sends a generic message containing {@code request} with the given {@code label} to {@code remoteName} process on
* {@code remoteNode} from {@code localMbox} on {@code localNode}. Unlike, `gen:call`, a monitor is not setup prior
* to the call.
*
* @link https://github.com/erlang/otp/blob/OTP_R16B03-1/lib/stdlib/src/gen.erl#L209
*/
public static OtpErlangObject unmonitoredCall(final OtpMbox localMbox, final OtpNode localNode, final String remoteName, final String remoteNode, final OtpErlangAtom label, final OtpErlangObject request, final int timeout) throws OtpErlangExit, OtpErlangDecodeException {
return unmonitoredCall(
localMbox,
localNode,
new Sender() {
@Override
public void send(OtpErlangObject message) {
localMbox.send(remoteName, remoteNode, message);
}
},
label,
request,
timeout
);
}
public static OtpErlangObject unmonitoredCall(final OtpMbox localMbox, final OtpNode localNode, final OtpErlangPid remotePid, final OtpErlangAtom label, final OtpErlangObject request, final int timeout) throws OtpErlangExit, OtpErlangDecodeException {
return unmonitoredCall(
localMbox,
localNode,
new Sender() {
@Override
public void send(OtpErlangObject message) {
localMbox.send(remotePid, message);
}
},
label,
request,
timeout
);
}
/*
* Private
*/
private static OtpErlangTuple returnAddress(OtpMbox otpMbox, OtpErlangRef otpErlangRef) {
return new OtpErlangTuple(
new OtpErlangObject[]{
otpMbox.self(),
otpErlangRef
}
);
}
private static OtpErlangObject unmonitoredCall(final OtpMbox localMbox, final OtpNode localNode, final Sender sender, final OtpErlangAtom label, final OtpErlangObject request, final int timeout) throws OtpErlangExit, OtpErlangDecodeException {
OtpErlangRef ref = localNode.createRef();
OtpErlangObject message = new OtpErlangTuple(
new OtpErlangObject[]{
label,
returnAddress(localMbox, ref),
request
}
);
sender.send(message);
OtpErlangObject received = localMbox.receive(timeout);
OtpErlangObject response = null;
if (received != null) {
OtpErlangTuple tuple = (OtpErlangTuple) received;
OtpErlangObject first = tuple.elementAt(0);
if (!first.equals(ref)) {
throw new NotImplementedException("Expected ref " + ref + ", but received " + first);
}
response = tuple.elementAt(1);
}
return response;
}
}