otpmbox.java

来自「OTP是开放电信平台的简称」· Java 代码 · 共 652 行 · 第 1/2 页

JAVA
652
字号
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. *  * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' *  *     $Id$ */package com.ericsson.otp.erlang;/** * <p> Provides a simple mechanism for exchanging messages with Erlang * processes or other instances of this class.</p> * * <p> Each mailbox is associated with a unique {@link OtpErlangPid * pid} that contains information necessary for delivery of messages. * When sending messages to named processes or mailboxes, the sender * pid is made available to the recipient of the message. When sending * messages to other mailboxes, the recipient can only respond if the * sender includes the pid as part of the message contents. The sender * can determine his own pid by calling {@link #self self()}. </p> * * <p> Mailboxes can be named, either at creation or later. Messages * can be sent to named mailboxes and named Erlang processes without * knowing the {@link OtpErlangPid pid} that identifies the mailbox. * This is neccessary in order to set up initial communication between * parts of an application. Each mailbox can have at most one name. * </p> * * <p> Since this class was intended for communication with Erlang, * all of the send methods take {@link OtpErlangObject * OtpErlangObject} arguments. However this class can also be used to * transmit arbitrary Java objects (as long as they implement one of * java.io.Serializable or java.io.Externalizable) by encapsulating * the object in a {@link OtpErlangBinary OtpErlangBinary}. </p> * * <p> Messages to remote nodes are externalized for transmission, and * as a result the recipient receives a <b>copy</b> of the original * Java object. To ensure consistent behaviour when messages are sent * between local mailboxes, such messages are cloned before delivery. * </p> * * <p> Additionally, mailboxes can be linked in much the same way as * Erlang processes. If a link is active when a mailbox is {@link * #close closed}, any linked Erlang processes or OtpMboxes will be * sent an exit signal. As well, exit signals will be (eventually) * sent if a mailbox goes out of scope and its {@link #finalize * finalize()} method called. However due to the nature of * finalization (i.e. Java makes no guarantees about when {@link * #finalize finalize()} will be called) it is recommended that you * always explicitly close mailboxes if you are using links instead of * relying on finalization to notify other parties in a timely manner. * </p> * * When retrieving messages from a mailbox that has received an exit * signal, an {@link OtpErlangExit OtpErlangExit} exception will be * raised. Note that the exception is queued in the mailbox along with * other messages, and will not be raised until it reaches the head of * the queue and is about to be retrieved. </p> * **/public class OtpMbox {  OtpNode home;  OtpErlangPid self;  GenericQueue queue;  String name;  Links links;  // package constructor: called by OtpNode:createMbox(name)  // to create a named mbox  OtpMbox(OtpNode home, OtpErlangPid self, String name) {    this.self = self;    this.home = home;    this.name = name;    this.queue = new GenericQueue();    this.links = new Links(10);  }  // package constructor: called by OtpNode:createMbox()   // to create an anonymous  OtpMbox(OtpNode home, OtpErlangPid self) {    this(home,self,null);  }    /**   * <p> Get the identifying {@link OtpErlangPid pid} associated with   * this mailbox.</p>   *   * <p> The {@link OtpErlangPid pid} associated with this mailbox   * uniquely identifies the mailbox and can be used to address the   * mailbox. You can send the {@link OtpErlangPid pid} to a remote   * communicating part so that he can know where to send his   * response. </p>   *      * @return the self pid for this mailbox.   **/  public OtpErlangPid self() {    return self;  }  /**   * <p> Register or remove a name for this mailbox. Registering a   * name for a mailbox enables others to send messages without   * knowing the {@link OtpErlangPid pid} of the mailbox. A mailbox   * can have at most one name; if the mailbox already had a name,   * calling this method will supercede that name. </p>   *   * @param name the name to register for the mailbox. Specify null to   * unregister the existing name from this mailbox.   *   * @return true if the name was available, or false otherwise.   **/  public synchronized boolean registerName(String name) {    return home.registerName(name,this);  }  /**   * Get the registered name of this mailbox.   *   * @return the registered name of this mailbox, or null if the   * mailbox had no registerd name.   **/  public String getName() {    return this.name;  }  /**    * Block until a message arrives for this mailbox.   *   * @return an {@link OtpErlangObject OtpErlangObject} representing   * the body of the next message waiting in this mailbox.   *   * @exception OtpErlangDecodeException if the message can not be   * decoded.   *   * @exception OtpErlangExit if a linked {@link OtpErlangPid pid} has   * exited or has sent an exit signal to this mailbox.   **/  public OtpErlangObject receive()     throws OtpErlangExit, OtpErlangDecodeException {    try {      return receiveMsg().getMsg();    }    catch (OtpErlangExit e) {      throw e;    }    catch (OtpErlangDecodeException f) {      throw f;    }  }    /**   * Wait for a message to arrive for this mailbox.   *   * @param timeout the time, in milliseconds, to wait for a message   * before returning null.   *   * @return an {@link OtpErlangObject OtpErlangObject} representing   * the body of the next message waiting in this mailbox.   *   * @exception OtpErlangDecodeException if the message can not be   * decoded.   *   * @exception OtpErlangExit if a linked {@link OtpErlangPid pid} has   * exited or has sent an exit signal to this mailbox.   **/  public OtpErlangObject receive(long timeout)     throws OtpErlangExit, OtpErlangDecodeException {    try {      OtpMsg m = receiveMsg(timeout);      if (m != null) return m.getMsg();    }    catch (OtpErlangExit e) {      throw e;    }    catch (OtpErlangDecodeException f) {      throw f;    }    catch (InterruptedException g) { }    return null;  }  /**   * Block until a message arrives for this mailbox.   *   * @return a byte array representing the still-encoded body of the   * next message waiting in this mailbox.   *   * @exception OtpErlangExit if a linked {@link OtpErlangPid pid} has   * exited or has sent an exit signal to this mailbox.   *   **/  public OtpInputStream receiveBuf()     throws OtpErlangExit {    return receiveMsg().getMsgBuf();  }  /**   * Wait for a message to arrive for this mailbox.   *   * @param timeout the time, in milliseconds, to wait for a message   * before returning null.   *   * @return a byte array representing the still-encoded body of the   * next message waiting in this mailbox.   *   * @exception OtpErlangExit if a linked {@link OtpErlangPid pid} has   * exited or has sent an exit signal to this mailbox.   *   * @exception InterruptedException if no message if the method   * times out before a message becomes available.   **/  public OtpInputStream receiveBuf(long timeout)     throws InterruptedException, OtpErlangExit {    OtpMsg m = receiveMsg(timeout);    if (m != null) return m.getMsgBuf();    return null;  }  /**   * Block until a message arrives for this mailbox.   *   * @return an {@link OtpMsg OtpMsg} containing the header   * information as well as the body of the next message waiting in   * this mailbox.   *   * @exception OtpErlangExit if a linked {@link OtpErlangPid pid} has   * exited or has sent an exit signal to this mailbox.   *   **/  public OtpMsg receiveMsg()     throws OtpErlangExit {    OtpMsg m = (OtpMsg)(queue.get());    switch (m.type()) {    case OtpMsg.exitTag:    case OtpMsg.exit2Tag:      try {	OtpErlangObject o = m.getMsg();	throw new OtpErlangExit(o,m.getSenderPid());      }      catch (OtpErlangDecodeException e) {	throw new OtpErlangExit("unknown",m.getSenderPid());      }          default:      return m;    }  }  /**   * Wait for a message to arrive for this mailbox.   *   * @param timeout the time, in milliseconds, to wait for a message.   *   * @return an {@link OtpMsg OtpMsg} containing the header   * information as well as the body of the next message waiting in   * this mailbox.   *   * @exception OtpErlangExit if a linked {@link OtpErlangPid pid} has   * exited or has sent an exit signal to this mailbox.   *   * @exception InterruptedException if no message if the method   * times out before a message becomes available.   **/  public OtpMsg receiveMsg(long timeout)    throws InterruptedException, OtpErlangExit {    OtpMsg m = (OtpMsg)(queue.get(timeout));    if (m == null) return null;          switch (m.type()) {    case OtpMsg.exitTag:    case OtpMsg.exit2Tag:      try {	OtpErlangObject o = m.getMsg();	throw new OtpErlangExit(o,m.getSenderPid());      }      catch (OtpErlangDecodeException e) {	throw new OtpErlangExit("unknown",m.getSenderPid());      }          default:      return m;    }  }  /**   * Send a message to a remote {@link OtpErlangPid pid}, representing   * either another {@link OtpMbox mailbox} or an Erlang process.   *   * @param to the {@link OtpErlangPid pid} identifying the intended   * recipient of the message.   *   * @param msg the body of the message to send.   *   **/  public void send(OtpErlangPid to, OtpErlangObject msg) {    try {      String node = to.node();      if (node.equals(home.node())) {	home.deliver(new OtpMsg(to,(OtpErlangObject)(msg.clone())));      }      else {	OtpCookedConnection conn = home.getConnection(node);	if (conn == null) return;	conn.send(self,to,msg);      }    }    catch (Exception e) { }  }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?