001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.adaptive.measurements.organizers;
014    
015    import org.jikesrvm.VM;
016    import org.jikesrvm.adaptive.measurements.listeners.Listener;
017    import org.jikesrvm.scheduler.Latch;
018    import org.jikesrvm.scheduler.SystemThread;
019    import org.vmmagic.pragma.Uninterruptible;
020    import org.vmmagic.pragma.Unpreemptible;
021    import org.vmmagic.pragma.NonMoving;
022    
023    /**
024     * An Organizer acts an an intermediary between the low level
025     * online measurements and the controller.  An organizer may perform
026     * simple or complex tasks, but it is always simply following the
027     * instructions given by the controller.
028     */
029    @NonMoving
030    public abstract class Organizer extends SystemThread {
031    
032      /** Constructor */
033      public Organizer() {
034        super("Organizer");
035      }
036    
037      /**
038       * The listener associated with this organizer.
039       * May be {@code null} if the organizer has no associated listener.
040       */
041      protected Listener listener;
042    
043      /** A latch used for activate/passivate. */
044      private final Latch latch = new Latch(false);
045    
046      /**
047       * Called when thread is scheduled.
048       */
049      @Override
050      public void run() {
051        initialize();
052        while (true) {
053          passivate(); // wait until externally scheduled to run
054          try {
055            thresholdReached();       // we've been scheduled; do our job!
056            if (listener != null) listener.reset();
057          } catch (Exception e) {
058            e.printStackTrace();
059            if (VM.ErrorsFatal) VM.sysFail("Exception in organizer " + this);
060          }
061        }
062      }
063    
064      /**
065       * Last opportunity to say something.
066       */
067      public void report() {}
068    
069      /**
070       * Method that is called when the sampling threshold is reached
071       */
072      abstract void thresholdReached();
073    
074      /**
075       * Organizer specific setup.
076       * A good place to install and activate any listeners.
077       */
078      protected abstract void initialize();
079    
080      /*
081       * Can access the thread queue without locking because
082       * Only listener and organizer operate on the thread queue and the
083       * listener uses its own protocol to ensure that exactly 1
084       * thread will attempt to activate the organizer.
085       */
086      @Unpreemptible
087      private void passivate() {
088        if (listener != null) {
089          if (VM.VerifyAssertions) VM._assert(!listener.isActive());
090          listener.activate();
091        }
092        latch.waitAndCloseWithHandshake();
093      }
094    
095      /**
096       * Called to activate the organizer thread (i.e. schedule it for execution).
097       */
098      @Uninterruptible
099      public void activate() {
100        if (listener != null) {
101          if (VM.VerifyAssertions) VM._assert(listener.isActive());
102          listener.passivate();
103        }
104        latch.openNoHandshake();
105      }
106    }