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 + -
显示快捷键?