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.mmtk.utility.statistics;
014    
015    import org.vmmagic.pragma.*;
016    
017    /**
018     *
019     * This abstract class describes the interface of a generic counter.
020     */
021    @Uninterruptible
022    public abstract class Counter {
023    
024      /****************************************************************************
025       *
026       * Instance variables
027       */
028    
029      /**
030       *
031       */
032      private final String name;
033      private final boolean start;
034      private final boolean mergephases;
035    
036      /**
037       * Allow for counters whose values are too complex to be simply printed out.
038       */
039      protected boolean complex = false;
040    
041      /****************************************************************************
042       *
043       * Initialization
044       */
045    
046      /**
047       * Constructor
048       *
049       * @param name The name to be associated with this counter
050       */
051      Counter(String name) {
052        this(name, true, false);
053      }
054    
055      /**
056       * Constructor
057       *
058       * @param name The name to be associated with this counter
059       * @param start True if this counter is to be implicitly started
060       * when <code>startAll()</code> is called (otherwise the counter
061       * must be explicitly started).
062       */
063      Counter(String name, boolean start) {
064        this(name, start, false);
065      }
066    
067      /**
068       * Constructor
069       *
070       * @param name The name to be associated with this counter
071       * @param start  True if this counter is to be implicitly started
072       * when <code>startAll()</code> is called (otherwise the counter
073       * must be explicitly started).
074       * @param mergephases True if this counter does not separately
075       * report GC and Mutator phases.
076       */
077      Counter(String name, boolean start, boolean mergephases) {
078        this.name = name;
079        this.start = start;
080        this.mergephases = mergephases;
081        Stats.newCounter(this);
082      }
083    
084      /****************************************************************************
085       *
086       * Counter control methods: start, stop, print etc
087       */
088    
089      /**
090       * Start this counter
091       */
092      abstract void start();
093    
094      /**
095       * Stop this counter
096       */
097      abstract void stop();
098    
099      /**
100       * The phase has changed (from GC to mutator or mutator to GC).
101       * Take action with respect to the last phase if necessary.
102       *
103       * @param oldPhase The last phase
104       */
105      abstract void phaseChange(int oldPhase);
106    
107      /**
108       * Print the value of this counter for the given phase
109       *
110       * @param phase The phase to be printed
111       */
112      abstract void printCount(int phase);
113    
114      /**
115       * Print the current total for this counter
116       */
117      abstract void printTotal();
118    
119      /**
120       * Print the current total for either the mutator or GC phase
121       *
122       * @param mutator {@code true} if the total for the mutator phases is to be
123       * printed (otherwise the total for the GC phases will be printed).
124       */
125      abstract void printTotal(boolean mutator);
126    
127      /**
128       * Print the current minimum value for either the mutator or GC phase
129       *
130       * @param mutator {@code true} if the minimum for the mutator phase is to be
131       * printed (otherwise the minimum for the GC phase will be printed).
132       */
133      abstract void printMin(boolean mutator);
134    
135      /**
136       * Print the current maximum value for either the mutator or GC phase
137       *
138       * @param mutator {@code true} if the maximum for the mutator phase is to be
139       * printed (otherwise the maximum for the GC phase will be printed).
140       */
141      abstract void printMax(boolean mutator);
142    
143      /**
144       * Print statistics for the most recent phase
145       */
146      public void printLast() {
147        if (Stats.phase > 0) printCount(Stats.phase - 1);
148      }
149    
150    
151      /****************************************************************************
152       *
153       * Accessor methods
154       */
155    
156      /**
157       * Return the name of this counter
158       * @return The name of this counter
159       */
160      String getName() { return name; }
161    
162      /**
163       * Return the (option) suffix to be used when reporting this counter
164       * @return The suffix
165       */
166      String getColumnSuffix() { return ""; }
167    
168      /**
169       * Return {@code true} if this counter is implicitly started when
170       * <code>startAll()</code> is called.
171       * @return {@code true} if this counter is implicitly started when
172       *         <code>startAll()</code> is called.
173       */
174      boolean getStart() { return start; }
175    
176      /**
177       * Return true if this counter will merge stats for GC and mutator phases.
178       * @return True if this counter will merge stats for GC and mutator phases.
179       */
180      boolean mergePhases() { return mergephases; }
181    
182      boolean isComplex() { return complex; }
183    }