/** Custom initialization method, called by the enclosing actor, during its initialization. */ public synchronized void initialize() { operationalSourcePorts = new HashSet<IOPort>(); operationalSourcePorts.addAll(this.sourcePortList()); if (isInput() && getContainer() instanceof MessageBuffer) { MessageBuffer _msgBfr = (MessageBuffer) getContainer(); if (_msgBfr.acceptInputPort(this)) { Receiver[][] receivers = getReceivers(); for (int i = 0; i < receivers.length; i++) { Receiver[] receivers2 = receivers[i]; for (int j = 0; j < receivers2.length; j++) { Receiver receiver = receivers2[j]; if (receiver instanceof MessageProvider) { ((MessageProvider) receiver).setMessageBuffer(_msgBfr); } } } } else { setMessageBuffer(null); } } // first need to find a way to register the port statistics // as children of the actor statistics statistics.reset(); StatisticsServiceFactory.getService().registerStatistics(statistics); }
/** * Send a token to all connected receivers. Tokens are in general immutable, so each receiver is * given a reference to the same token and no clones are made. The transfer is accomplished by * calling getRemoteReceivers() to determine the number of channels with valid receivers and then * calling send() on the appropriate channels. It would probably be faster to call put() directly * on the receivers. If there are no destination receivers, then nothing is sent. If the port is * not connected to anything, or receivers have not been created in the remote port, then just * return. * * <p>Some of this method is read-synchronized on the workspace. Since it is possible for a thread * to block while executing a put, it is important that the thread does not hold read access on * the workspace when it is blocked. Thus this method releases read access on the workspace before * calling put. * * @param token The token to send * @exception IllegalActionException If the token to be sent cannot be converted to the type of * this port * @exception NoRoomException If a send to one of the channels throws it. */ public void broadcast(Token token) throws IllegalActionException, NoRoomException { if (logger.isTraceEnabled()) { logger.trace("broadcast() - entry : " + token); } statistics.acceptSentMessage(null); Receiver[][] farReceivers; // ptolemy debug listener stuff etc if (_debugging) { _debug("broadcast " + token); } try { _workspace.getReadAccess(); _checkType(token); farReceivers = getRemoteReceivers(); if (farReceivers == null) { return; } } finally { _workspace.doneReading(); } // NOTE: This does not call send() here, because send() // repeats the above on each call. for (int i = 0; i < farReceivers.length; i++) { if (farReceivers[i] == null) continue; putAtFarReceivers(token, farReceivers[i]); } if (logger.isTraceEnabled()) { logger.trace("broadcast() - exit"); } }
/** * Get a token from the specified channel. If the channel has a group with more than one receiver * (something that is possible if this is a transparent port), then this method calls get() on all * receivers, but returns only the first non-null token returned by these calls. Normally this * method is not used on transparent ports. If there is no token to return, then throw an * exception. * * <p>Some of this method is read-synchronized on the workspace. Since it is possible for a thread * to block while executing a get, it is important that the thread does not hold read access on * the workspace when it is blocked. Thus this method releases read access on the workspace before * calling get(). * * @param channelIndex The channel index. * @return A token from the specified channel. * @exception NoTokenException If there is no token. * @exception IllegalActionException If there is no director, and hence no receivers have been * created, if the port is not an input port, or if the channel index is out of range. */ public Token get(int channelIndex) throws NoTokenException, IllegalActionException { if (logger.isTraceEnabled()) { logger.trace("get() - entry : channel : " + channelIndex); } Receiver[][] localReceivers; try { _workspace.getReadAccess(); // Note that the getReceivers() method might throw an // IllegalActionException if there's no director. localReceivers = getReceivers(); if (channelIndex >= localReceivers.length) { if (!isInput()) { throw new IllegalActionException(this, "Port is not an input port!"); } else { throw new IllegalActionException( this, "Channel index " + channelIndex + " is out of range, because width is only " + getWidth() + "."); } } if (localReceivers[channelIndex] == null) { throw new NoTokenException(this, "No receiver at index: " + channelIndex + "."); } } finally { _workspace.doneReading(); } Token token = null; for (int j = 0; j < localReceivers[channelIndex].length; j++) { Token localToken = localReceivers[channelIndex][j].get(); if (token == null) { token = localToken; } } if (token == null) { throw new NoTokenException(this, "No token to return."); } if (_debugging) { _debug("get from channel " + channelIndex + ": " + token); } token = convertTokenForMe(token); statistics.acceptReceivedMessage(null); if (logger.isTraceEnabled()) { logger.trace("get() - exit - result : " + token); } return token; }
/** * Send a token to the specified channel, checking the type and converting the token if necessary. * If the port is not connected to anything, or receivers have not been created in the remote * port, or the channel index is out of range, or the port is not an output port, then just * silently return. This behavior makes it easy to leave output ports unconnected when you are not * interested in the output. If the type of the specified token is the type of this port, or the * token can be converted to that type losslessly, the token is sent to all receivers connected to * the specified channel. Otherwise, IllegalActionException is thrown. Before putting the token * into the destination receivers, this method also checks the type of the remote input port, and * converts the token if necessary. The conversion is done by calling the convert() method of the * type of the remote input port. * * <p>Some of this method is read-synchronized on the workspace. Since it is possible for a thread * to block while executing a put, it is important that the thread does not hold read access on * the workspace when it is blocked. Thus this method releases read access on the workspace before * calling put. * * @param channelIndex The index of the channel, from 0 to width-1. * @param token The token to send. * @exception IllegalActionException If the token to be sent cannot be converted to the type of * this port, or if the token is null. * @exception NoRoomException If there is no room in the receiver. */ public void send(int channelIndex, Token token) throws IllegalActionException, NoRoomException { if (logger.isTraceEnabled()) { logger.trace( "{} - send() - entry : channel : {} token : {}", new Object[] {this.getFullName(), channelIndex, token}); } if (token == null) { throw new IllegalActionException(this, "Cannot send a null token."); } if (!(PasserelleToken.POISON_PILL == token)) { statistics.acceptSentMessage(null); } Receiver[][] farReceivers; if (_debugging) { _debug("send to channel " + channelIndex + ": " + token); } if (isDebugged()) { event(new IOPortEvent(this, IOPortEvent.SEND, IOPortEvent.ALLCHANNELS, true, token)); } try { try { _workspace.getReadAccess(); _checkType(token); // Note that the getRemoteReceivers() method doesn't throw // any non-runtime exception. farReceivers = getRemoteReceivers(); if (farReceivers == null || farReceivers.length <= channelIndex || farReceivers[channelIndex] == null) { return; } } finally { _workspace.doneReading(); } putAtFarReceivers(token, farReceivers[channelIndex]); } catch (ArrayIndexOutOfBoundsException ex) { // NOTE: This may occur if the channel index is out of range. // This is allowed, just do nothing. } logger.trace("{} - send() - exit", this.getFullName()); }
/** * Send a token to the specified channel, checking the type and converting the token if necessary. * If the port is not connected to anything, or receivers have not been created in the remote * port, or the channel index is out of range, or the port is not an output port, then just * silently return. This behavior makes it easy to leave output ports unconnected when you are not * interested in the output. If the type of the specified token is the type of this port, or the * token can be converted to that type losslessly, the token is sent to all receivers connected to * the specified channel. Otherwise, IllegalActionException is thrown. Before putting the token * into the destination receivers, this method also checks the type of the remote input port, and * converts the token if necessary. The conversion is done by calling the convert() method of the * type of the remote input port. * * <p>Some of this method is read-synchronized on the workspace. Since it is possible for a thread * to block while executing a put, it is important that the thread does not hold read access on * the workspace when it is blocked. Thus this method releases read access on the workspace before * calling put. * * @param channelIndex The index of the channel, from 0 to width-1. * @param token The token to send. * @exception IllegalActionException If the token to be sent cannot be converted to the type of * this port, or if the token is null. * @exception NoRoomException If there is no room in the receiver. */ public void send(int channelIndex, Token token) throws IllegalActionException, NoRoomException { if (logger.isTraceEnabled()) { logger.trace("send() - entry : channel : " + channelIndex + " token : " + token); } if (token == null) { throw new IllegalActionException(this, "Cannot send a null token."); } statistics.acceptSentMessage(null); Receiver[][] farReceivers; if (_debugging) { _debug("send to channel " + channelIndex + ": " + token); } try { try { _workspace.getReadAccess(); _checkType(token); // Note that the getRemoteReceivers() method doesn't throw // any non-runtime exception. farReceivers = getRemoteReceivers(); if (farReceivers == null || farReceivers.length <= channelIndex || farReceivers[channelIndex] == null) { return; } } finally { _workspace.doneReading(); } putAtFarReceivers(token, farReceivers[channelIndex]); } catch (ArrayIndexOutOfBoundsException ex) { // NOTE: This may occur if the channel index is out of range. // This is allowed, just do nothing. } if (logger.isTraceEnabled()) { logger.trace("send() - exit"); } }
/** * Send a token to all connected receivers. Tokens are in general immutable, so each receiver is * given a reference to the same token and no clones are made. The transfer is accomplished by * calling getRemoteReceivers() to determine the number of channels with valid receivers and then * calling send() on the appropriate channels. It would probably be faster to call put() directly * on the receivers. If there are no destination receivers, then nothing is sent. If the port is * not connected to anything, or receivers have not been created in the remote port, then just * return. * * <p>Some of this method is read-synchronized on the workspace. Since it is possible for a thread * to block while executing a put, it is important that the thread does not hold read access on * the workspace when it is blocked. Thus this method releases read access on the workspace before * calling put. * * @param token The token to send * @exception IllegalActionException If the token to be sent cannot be converted to the type of * this port * @exception NoRoomException If a send to one of the channels throws it. */ public void broadcast(Token token) throws IllegalActionException, NoRoomException { logger.trace("{} - broadcast() - entry : {} ", this.getFullName(), token); if (!(PasserelleToken.POISON_PILL == token)) { statistics.acceptSentMessage(null); } Receiver[][] farReceivers; // ptolemy debug listener stuff etc if (_debugging) { _debug("broadcast " + token); } if (isDebugged()) { event(new IOPortEvent(this, IOPortEvent.SEND, IOPortEvent.ALLCHANNELS, true, token)); } try { _workspace.getReadAccess(); _checkType(token); farReceivers = getRemoteReceivers(); if (farReceivers == null) { return; } } finally { _workspace.doneReading(); } // NOTE: This does not call send() here, because send() // repeats the above on each call. for (int i = 0; i < farReceivers.length; i++) { if (farReceivers[i] == null) continue; putAtFarReceivers(token, farReceivers[i]); } logger.trace("{} - broadcast() - exit", this.getFullName()); }