예제 #1
0
  /** Report that the manager state has changed. This is called by the manager. */
  public void managerStateChanged(Manager manager) {
    Manager.State newState = manager.getState();

    if (newState != _previousState) {
      report(manager.getState().getDescription());
      _previousState = newState;
    }
  }
예제 #2
0
  /**
   * Put a token on the queue contained in this receiver. If the queue is full, then suspend the
   * calling thread (blocking write) and inform the director of the same. Resume the process on
   * detecting room in the queue. If a termination is requested, then initiate the termination of
   * the calling process by throwing a TerminateProcessException. On detecting a room in the queue,
   * put a token in the queue. Check whether any process is blocked on a read from this receiver. If
   * a process is indeed blocked, then unblock the process, and inform the director of the same.
   *
   * @param token The token to be put in the receiver, or null to not put anything.
   * @exception NoRoomException If during initialization, capacity cannot be increased enough to
   *     accommodate initial tokens.
   */
  public void put(Token token) throws NoRoomException {
    IOPort port = getContainer();
    if (port == null || token == null) {
      return; // Nothing to do.
    }
    Workspace workspace = port.workspace();
    while (!_terminate) {
      int depth = 0;
      try {
        // NOTE: Avoid acquiring read access on the workspace
        // while holding the lock on the director because if
        // some other process is trying to acquire write access,
        // the request for read access will be deferred.
        Nameable container = getContainer().getContainer();
        Manager manager = ((Actor) container).getManager();
        // NOTE: This used to synchronize on this, but since it calls
        // director methods that are synchronized on the director,
        // this can cause deadlock.
        synchronized (_director) {
          // Need to check this again after acquiring the lock.
          // Otherwise, could end up calling wait() below _after_
          // notification has occurred.
          if (_terminate) {
            break;
          }

          // If we are in the initialization phase, then we may have
          // to increase the queue capacity before proceeding. This
          // may be needed to support PublisherPorts that produce
          // initial tokens (or, I suppose, any actor that produces
          // initial tokens during initialize()?).
          if (!super.hasRoom()) {
            if (container instanceof Actor) {
              if (manager.getState().equals(Manager.INITIALIZING)) {
                try {
                  _queue.setCapacity(_queue.getCapacity() + 1);
                } catch (IllegalActionException e) {
                  throw new NoRoomException(
                      getContainer(),
                      "Failed to increase queue capacity enough to accommodate initial tokens");
                }
              }
            }
          }
          // Try to write.
          if (super.hasRoom()) {
            super.put(token);

            // If any thread is blocked on a get(), then it will become
            // unblocked. Notify the director now so that there isn't a
            // spurious deadlock detection.
            if (_readPending != null) {
              _director.threadUnblocked(_readPending, this, PNDirector.READ_BLOCKED);
              _readPending = null;
            }

            // Normally, the _writePending reference will have
            // been cleared by the read that unblocked this write.
            // However, it might be that the director increased the
            // buffer size, which would also have the affect of unblocking
            // this write. Hence, we clear it here if it is set.
            if (_writePending != null) {
              _director.threadUnblocked(_writePending, this, PNDirector.WRITE_BLOCKED);
              _writePending = null;
            }

            break;
          }

          // Wait to try again.
          _writePending = Thread.currentThread();
          _director.threadBlocked(_writePending, this, PNDirector.WRITE_BLOCKED);

          // NOTE: We cannot use workspace.wait(Object) here without
          // introducing a race condition, because we have to release
          // the lock on the _director before calling workspace.wait(_director).
          depth = workspace.releaseReadPermission();
          _director.wait();
        } // release lock on _director before reacquiring read permissions.
      } catch (InterruptedException e) {
        _terminate = true;
      } finally {
        if (depth > 0) {
          workspace.reacquireReadPermission(depth);
        }
      }
    }

    if (_terminate) {
      throw new TerminateProcessException("Process terminated.");
    }
  }
예제 #3
0
 /**
  * Report in debugging statements that the manager state has changed. This method is called if the
  * referenced model is executed in another thread and the manager changes state.
  *
  * @param manager The manager controlling the execution.
  * @see Manager#getState()
  */
 public void managerStateChanged(Manager manager) {
   if (_debugging) {
     _debug("Referenced model manager state: " + manager.getState());
   }
 }