001package components.stopwatch; 002 003import java.lang.management.ManagementFactory; 004import java.lang.management.ThreadMXBean; 005 006/** 007 * {@code Stopwatch} represented with two integers and a boolean, with 008 * implementations of all methods. 009 */ 010public class Stopwatch1 implements Stopwatch { 011 012 /* 013 * Private members -------------------------------------------------------- 014 */ 015 016 /** 017 * The last recorded total time (in nanoseconds). 018 */ 019 private long previousTotal; 020 021 /** 022 * The start time (in nanoseconds). 023 */ 024 private long startTime; 025 026 /** 027 * Records whether {@code this} is running. 028 */ 029 private boolean isRunning; 030 031 /** 032 * The managed bean for the thread system of the Java virtual machine. 033 */ 034 private static final ThreadMXBean BEAN = ManagementFactory.getThreadMXBean(); 035 036 /** 037 * Creator of initial representation. 038 */ 039 private void createNewRep() { 040 this.previousTotal = 0; 041 this.startTime = 0; 042 this.isRunning = false; 043 } 044 045 /* 046 * Constructors ----------------------------------------------------------- 047 */ 048 049 /** 050 * No-argument constructor. 051 */ 052 public Stopwatch1() { 053 assert BEAN.isCurrentThreadCpuTimeSupported() : "Violation of: feature supported"; 054 this.createNewRep(); 055 } 056 057 /* 058 * Standard methods ------------------------------------------------------- 059 */ 060 061 @Override 062 public final Stopwatch newInstance() { 063 try { 064 return this.getClass().getConstructor().newInstance(); 065 } catch (ReflectiveOperationException e) { 066 throw new AssertionError( 067 "Cannot construct object of type " + this.getClass()); 068 } 069 } 070 071 @Override 072 public final void clear() { 073 this.createNewRep(); 074 } 075 076 @Override 077 public final void transferFrom(Stopwatch source) { 078 assert source != null : "Violation of: source is not null"; 079 assert source != this : "Violation of: source is not this"; 080 assert source instanceof Stopwatch1 081 : "Violation of: source is of dynamic type Stopwatch1"; 082 /* 083 * This cast cannot fail since the assert above would have stopped 084 * execution in that case. 085 */ 086 Stopwatch1 localSource = (Stopwatch1) source; 087 this.previousTotal = localSource.previousTotal; 088 this.startTime = localSource.startTime; 089 this.isRunning = localSource.isRunning; 090 localSource.createNewRep(); 091 } 092 093 /* 094 * Kernel methods --------------------------------------------------------- 095 */ 096 097 @Override 098 public final void start() { 099 assert !this.isRunning : "Violation of: not this.running"; 100 this.isRunning = true; 101 this.startTime = BEAN.getCurrentThreadCpuTime(); 102 } 103 104 @Override 105 public final void stop() { 106 assert this.isRunning : "Violation of: this.running"; 107 this.previousTotal += BEAN.getCurrentThreadCpuTime() - this.startTime; 108 this.isRunning = false; 109 } 110 111 @Override 112 public final int elapsed() { 113 final long nSec2mSec = 1000000L; 114 if (this.isRunning) { 115 return (int) ((this.previousTotal - this.startTime 116 + BEAN.getCurrentThreadCpuTime()) / nSec2mSec); 117 } else { 118 return (int) (this.previousTotal / nSec2mSec); 119 } 120 } 121 122 @Override 123 public final boolean isRunning() { 124 return this.isRunning; 125 } 126 127 @Override 128 public final boolean equals(Object obj) { 129 if (obj == this) { 130 return true; 131 } 132 if (obj == null) { 133 return false; 134 } 135 if (!(obj instanceof Stopwatch)) { 136 return false; 137 } 138 Stopwatch s = (Stopwatch) obj; 139 if (this.isRunning() || s.isRunning()) { 140 return false; 141 } 142 if (this.elapsed() != s.elapsed()) { 143 return false; 144 } 145 return true; 146 } 147 148 @Override 149 public final int hashCode() { 150 return this.elapsed(); 151 } 152 153 @Override 154 public final String toString() { 155 StringBuilder str = new StringBuilder( 156 "(" + this.elapsed() + "," + this.isRunning() + ")"); 157 return str.toString(); 158 } 159 160}