package se.l4.vibe.probes; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * Abstract implementation of {@link Sampler}. * * @author Andreas Holstenson * * @param <T> */ public abstract class AbstractSampler<T> implements Sampler<T> { private static final SampleListener[] EMPTY = new SampleListener[0]; private final Lock listenerLock; protected volatile SampleListener<T>[] listeners; public AbstractSampler() { listenerLock = new ReentrantLock(); listeners = EMPTY; } @Override public void addListener(SampleListener<T> listener) { listenerLock.lock(); try { SampleListener<T>[] listeners = this.listeners; SampleListener<T>[] newListeners = new SampleListener[listeners.length + 1]; System.arraycopy(listeners, 0, newListeners, 0, listeners.length); newListeners[listeners.length] = listener; this.listeners = newListeners; } finally { listenerLock.unlock(); } } @Override public void removeListener(SampleListener<T> listener) { listenerLock.lock(); try { SampleListener<T>[] listeners = this.listeners; int index = -1; for(int i=0, n=listeners.length; i<n; i++) { if(listeners[i] == listener) { index = i; break; } } if(index == -1) { // No such listener, just return return; } SampleListener<T>[] newListeners = new SampleListener[listeners.length - 1]; System.arraycopy(listeners, 0, newListeners, 0, index); if(index < listeners.length - 1) { System.arraycopy(listeners, index + 1, newListeners, index, listeners.length- index - 1); } this.listeners = newListeners; } finally { listenerLock.unlock(); } } protected Entry<T> createEntry(long time, T value) { return new EntryImpl<T>(time, value); } public static class EntryImpl<T> implements Sampler.Entry<T> { private final long time; private final T value; public EntryImpl(long time, T value) { this.time = time; this.value = value; } @Override public long getTime() { return time; } @Override public T getValue() { return value; } @Override public String toString() { return "Entry{time=" + time + ", value=" + value + "}"; } } }