/*
* Copyright 2014 Higher Frequency Trading
*
* http://www.higherfrequencytrading.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.openhft.lang;
import java.util.LinkedList;
import java.util.List;
public class WaitStrategyBuilder {
private int lowerLimit;
private List<WaiterHelper> waiters;
public WaitStrategyBuilder() {
this.waiters = new LinkedList<WaiterHelper>();
this.lowerLimit = 0;
}
// *************************************************************************
//
// *************************************************************************
public WaitStrategyBuilder busyWaiter(int count) {
return waiter(Waiters.BUSY_WAITER,count);
}
public WaitStrategyBuilder yeldWaiter(int count) {
return waiter(Waiters.YELD_WAITER,count);
}
public WaitStrategyBuilder parkWaiter(int count) {
return waiter(Waiters.PARK_WAITER,count);
}
public WaitStrategyBuilder waiter(Waiter waiter,int count) {
this.waiters.add(new WaiterHelper(waiter,this.lowerLimit,count));
this.lowerLimit += count;
return this;
}
public WaitStrategy build() {
switch(this.waiters.size()) {
case 1:
return new WaitStrategy1(this.waiters);
case 2:
return new WaitStrategy2(this.waiters);
case 3:
return new WaitStrategy3(this.waiters);
}
return new WaitStrategyN(this.waiters);
}
// *************************************************************************
//
// *************************************************************************
private class WaiterHelper {
private final Waiter waiter;
private int min;
private int max;
public WaiterHelper(final Waiter waiter) {
this(waiter,-1,-1);
}
public WaiterHelper(final Waiter waiter,int start, int count) {
this.waiter = waiter;
this.min = start;
this.max = start + count;
}
public boolean contains(int value) {
return value >= this.min && value <= this.min;
}
public Waiter waiter() {
return this.waiter;
}
public int min() {
return this.min;
}
public int max() {
return this.max;
}
}
// *************************************************************************
//
// *************************************************************************
private class WaitStrategy1 implements WaitStrategy {
private final Waiter waiter;
public WaitStrategy1(final List<WaiterHelper> waiters) {
this.waiter = waiters.get(0).waiter;
}
@Override
public void await(int counter) {
this.waiter.await();
}
}
private class WaitStrategy2 implements WaitStrategy {
private final int limit;
private final Waiter waiter1;
private final Waiter waiter2;
public WaitStrategy2(final List<WaiterHelper> waiters) {
this.limit = waiters.get(0).max;
this.waiter1 = waiters.get(0).waiter;
this.waiter2 = waiters.get(1).waiter;
}
@Override
public void await(int counter) {
if(counter < this.limit) {
this.waiter1.await();
} else {
this.waiter2.await();
}
}
}
private class WaitStrategy3 implements WaitStrategy {
private final int limit1;
private final int limit2;
private final Waiter waiter1;
private final Waiter waiter2;
private final Waiter waiter3;
public WaitStrategy3(final List<WaiterHelper> waiters) {
this.limit1 = waiters.get(0).max;
this.limit2 = waiters.get(1).max;
this.waiter1 = waiters.get(0).waiter;
this.waiter2 = waiters.get(1).waiter;
this.waiter3 = waiters.get(2).waiter;
}
@Override
public void await(int counter) {
if(counter < this.limit1) {
this.waiter1.await();
} else if(counter < this.limit2) {
this.waiter2.await();
} else {
this.waiter3.await();
}
}
}
private class WaitStrategyN implements WaitStrategy {
final List<WaiterHelper> waiters;
public WaitStrategyN(final List<WaiterHelper> waiters) {
this.waiters = new LinkedList<WaiterHelper>(waiters);
}
@Override
public void await(int counter) {
WaiterHelper wh = null;
for(int i=0;i<this.waiters.size();i++) {
wh = this.waiters.get(i);
if(i == this.waiters.size() - 1 || wh.contains(counter)) {
wh.waiter().await();
break;
}
}
}
}
}