/*
* Copyright 2011 LMAX Ltd.
*
* 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 com.lmax.disruptor;
import java.util.concurrent.atomic.AtomicLong;
/**
* Strategies employed for claiming the sequence of {@link AbstractEntry}s in the {@link RingBuffer} by producers.
*
* The {@link AbstractEntry} index is a the sequence value mod the {@link RingBuffer} capacity.
*/
public interface ClaimStrategy
{
/**
* Claim the next sequence index in the {@link RingBuffer} and increment.
*
* @return the {@link AbstractEntry} index to be used for the producer.
*/
long incrementAndGet();
/**
* Increment by a delta and get the result.
*
* @param delta to increment by.
* @return the result after incrementing.
*/
long incrementAndGet(int delta);
/**
* Set the current sequence value for claiming {@link AbstractEntry} in the {@link RingBuffer}
*
* @param sequence to be set as the current value.
*/
void setSequence(long sequence);
/**
* Indicates the threading policy to be applied for claiming {@link AbstractEntry}s by producers to the {@link RingBuffer}
*/
enum Option
{
/** Makes the {@link RingBuffer} thread safe for claiming {@link AbstractEntry}s by multiple producing threads. */
MULTI_THREADED
{
@Override
public ClaimStrategy newInstance()
{
return new MultiThreadedStrategy();
}
},
/** Optimised {@link RingBuffer} for use by single thread claiming {@link AbstractEntry}s as a producer. */
SINGLE_THREADED
{
@Override
public ClaimStrategy newInstance()
{
return new SingleThreadedStrategy();
}
};
/**
* Used by the {@link RingBuffer} as a polymorphic constructor.
*
* @return a new instance of the ClaimStrategy
*/
abstract ClaimStrategy newInstance();
}
/**
* Strategy to be used when there are multiple producer threads claiming {@link AbstractEntry}s.
*/
static final class MultiThreadedStrategy
implements ClaimStrategy
{
private final AtomicLong sequence = new AtomicLong(RingBuffer.INITIAL_CURSOR_VALUE);
@Override
public long incrementAndGet()
{
return sequence.incrementAndGet();
}
@Override
public long incrementAndGet(final int delta)
{
return sequence.addAndGet(delta);
}
@Override
public void setSequence(final long sequence)
{
this.sequence.set(sequence);
}
}
/**
* Optimised strategy can be used when there is a single producer thread claiming {@link AbstractEntry}s.
*/
static final class SingleThreadedStrategy
implements ClaimStrategy
{
private long sequence = RingBuffer.INITIAL_CURSOR_VALUE;
@Override
public long incrementAndGet()
{
return ++sequence;
}
@Override
public long incrementAndGet(final int delta)
{
sequence += delta;
return sequence;
}
@Override
public void setSequence(final long sequence)
{
this.sequence = sequence;
}
}
}