/*
 * 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.locks.LockSupport;

/**
 * Sleeping strategy that initially spins, then uses a Thread.yield(), and
 * eventually sleep (<code>LockSupport.parkNanos(1)</code>) for the minimum
 * number of nanos the OS and JVM will allow while the
 * {@link com.lmax.disruptor.EventProcessor}s are waiting on a barrier.
 * <p>
 * This strategy is a good compromise between performance and CPU resource.
 * Latency spikes can occur after quiet periods.
 */
public final class SleepingWaitStrategy implements WaitStrategy
{
    private static final int DEFAULT_RETRIES = 200;

    private final int retries;

    public SleepingWaitStrategy()
    {
        this(DEFAULT_RETRIES);
    }

    public SleepingWaitStrategy(int retries)
    {
        this.retries = retries;
    }

    @Override
    public long waitFor(
        final long sequence, Sequence cursor, final Sequence dependentSequence, final SequenceBarrier barrier)
        throws AlertException, InterruptedException
    {
        long availableSequence;
        int counter = retries;

        while ((availableSequence = dependentSequence.get()) < sequence)
        {
            counter = applyWaitMethod(barrier, counter);
        }

        return availableSequence;
    }

    @Override
    public void signalAllWhenBlocking()
    {
    }

    private int applyWaitMethod(final SequenceBarrier barrier, int counter)
        throws AlertException
    {
        barrier.checkAlert();

        if (counter > 100)
        {
            --counter;
        }
        else if (counter > 0)
        {
            --counter;
            Thread.yield();
        }
        else
        {
            LockSupport.parkNanos(100L);
        }

        return counter;
    }

    public static void main(String[] args) throws AlertException
    {
        final SequenceBarrier sequenceBarrier = new SequenceBarrier()
        {

            @Override
            public long waitFor(long sequence) throws AlertException, InterruptedException, TimeoutException
            {
                return 0;
            }

            @Override
            public long getCursor()
            {
                return 0;
            }

            @Override
            public boolean isAlerted()
            {
                return false;
            }

            @Override
            public void alert()
            {

            }

            @Override
            public void clearAlert()
            {

            }

            @Override
            public void checkAlert() throws AlertException
            {

            }
        };

        final SleepingWaitStrategy sleepingWaitStrategy = new SleepingWaitStrategy();
        for (;;)
        {
            sleepingWaitStrategy.applyWaitMethod(sequenceBarrier, 0);
        }
    }
}

@@ -1199,37 +1199,124 @@
 00;%0A
-%0A    private final int retrie
+    private static final long DEFAULT_SLEEP = 100;%0A%0A    private final int retries;%0A    private final long sleepTimeN
 s;%0A%0A
@@ -1383,16 +1383,31 @@
 _RETRIES
+, DEFAULT_SLEEP
 );%0A    %7D
@@ -1475,25 +1475,179 @@
 this
-.retries = retrie
+(retries, DEFAULT_SLEEP);%0A    %7D%0A%0A    public SleepingWaitStrategy(int retries, long sleepTimeNs)%0A    %7B%0A        this.retries = retries;%0A        this.sleepTimeNs = sleepTimeN
 s;%0A 
@@ -1831,38 +1831,16 @@
 xception
-, InterruptedException
 %0A    %7B%0A 
@@ -2583,1073 +2583,7 @@
    %7D
-%0A%0A    public static void main(String%5B%5D args) throws AlertException%0A    %7B%0A        final SequenceBarrier sequenceBarrier = new SequenceBarrier()%0A        %7B%0A%0A            @Override%0A            public long waitFor(long sequence) throws AlertException, InterruptedException, TimeoutException%0A            %7B%0A                return 0;%0A            %7D%0A%0A            @Override%0A            public long getCursor()%0A            %7B%0A                return 0;%0A            %7D%0A%0A            @Override%0A            public boolean isAlerted()%0A            %7B%0A                return false;%0A            %7D%0A%0A            @Override%0A            public void alert()%0A            %7B%0A%0A            %7D%0A%0A            @Override%0A            public void clearAlert()%0A            %7B%0A%0A            %7D%0A%0A            @Override%0A            public void checkAlert() throws AlertException%0A            %7B%0A%0A            %7D%0A        %7D;%0A%0A        final SleepingWaitStrategy sleepingWaitStrategy = new SleepingWaitStrategy();%0A        for (;;)%0A        %7B%0A            sleepingWaitStrategy.applyWaitMethod(sequenceBarrier, 0);%0A        %7D%0A    %7D
 %0A%7D%0A

Make sleep time a construction parameter, #219.