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 */
013package org.jikesrvm.adaptive.measurements.organizers;
014
015import org.jikesrvm.VM;
016import org.jikesrvm.adaptive.measurements.listeners.Listener;
017import org.jikesrvm.scheduler.Latch;
018import org.jikesrvm.scheduler.SystemThread;
019import org.vmmagic.pragma.Uninterruptible;
020import org.vmmagic.pragma.Unpreemptible;
021import 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
030public 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}