io.nextop.wire.Throttle Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-common Show documentation
Show all versions of java-common Show documentation
Platform-agnostic Java core for Nextop
The newest version!
package io.nextop.wire;
import io.nextop.Wire;
import io.nextop.log.NL;
import rx.Scheduler;
import rx.functions.Action0;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.TimeUnit;
/** thread-safe */
// TODO apply shape profiles
public class Throttle implements Wire.Adapter {
private final Object mutex = new Object();
private final Scheduler scheduler;
private final Scheduler.Worker worker;
private List active;
private boolean online = true;
public Throttle(Scheduler scheduler) {
this.scheduler = scheduler;
worker = scheduler.createWorker();
active = new ArrayList(4);
}
public void online() {
synchronized (mutex) {
online = true;
}
}
// closes all active wires
public void offline() {
@Nullable List drop;
synchronized (mutex) {
if (online) {
online = false;
drop = active;
active = new ArrayList(4);
} else {
drop = null;
}
}
if (null != drop) {
for (Wire wire : drop) {
try {
wire.close();
} catch (IOException e) {
NL.nl.handled("wire.throttle", e);
}
}
}
}
final Action0 ONLINE = new Action0() {
@Override
public void call() {
online();
}
};
final Action0 OFFLINE = new Action0() {
@Override
public void call() {
offline();
}
};
public void online(int timeout, TimeUnit timeUnit) {
if (timeout <= 0) {
online();
} else {
worker.schedule(ONLINE, timeout, timeUnit);
}
}
public void offline(int timeout, TimeUnit timeUnit) {
if (timeout <= 0) {
offline();
} else {
worker.schedule(OFFLINE, timeout, timeUnit);
}
}
/** thread-safe */
private void addActive(Wire wire) {
synchronized (mutex) {
active.add(wire);
}
}
/** thread-safe */
private void removeActive(Wire wire) {
synchronized (mutex) {
active.remove(wire);
}
}
/////// Wire.Adapter ///////
@Override
public Wire adapt(Wire wire) throws InterruptedException, NoSuchElementException {
ThrottledWire tw = new ThrottledWire(wire);
addActive(tw);
return tw;
}
final class ThrottledWire implements Wire {
final Wire impl;
ThrottledWire(Wire impl) {
this.impl = impl;
}
void destroy() {
removeActive(this);
}
@Override
public void close() throws IOException {
try {
impl.close();
} finally {
destroy();
}
}
@Override
public void read(byte[] buffer, int offset, int length, int messageBoundary) throws IOException {
try {
impl.read(buffer, offset, length, messageBoundary);
} finally {
destroy();
}
}
@Override
public void skip(long n, int messageBoundary) throws IOException {
try {
impl.skip(n, messageBoundary);
} finally {
destroy();
}
}
@Override
public void write(byte[] buffer, int offset, int length, int messageBoundary) throws IOException {
try {
impl.write(buffer, offset, length, messageBoundary);
} finally {
destroy();
}
}
@Override
public void flush() throws IOException {
try {
impl.flush();
} finally {
destroy();
}
}
}
}