/* * 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 org.f1x.io.disruptor; import java.util.concurrent.atomic.AtomicBoolean; /** * NOTE: This producer cannot share a ByteRing with other producers. */ public abstract class AbstractByteRingProducer implements Runnable { private final AtomicBoolean running = new AtomicBoolean(false); protected final ByteRing ring; protected final int minimumProducerBufferSize; /** * This producer cannot share a ByteRing with other producers. * @param ring ByteRing * @param minimumProducerBufferSize minimum size of allocated buffer */ public AbstractByteRingProducer(ByteRing ring, int minimumProducerBufferSize) { assert minimumProducerBufferSize > 0; assert ring.getCapacity() > minimumProducerBufferSize; this.ring = ring; this.minimumProducerBufferSize = minimumProducerBufferSize; } @Override public void run() { if (!running.compareAndSet(false, true)) { throw new IllegalStateException("Thread is already running"); } long low = 0; int currentCapacity = 0; while (true) { if (currentCapacity < minimumProducerBufferSize) { final int allocSize = getAllocSize(currentCapacity); long high = ring.next(allocSize); //TODO: Batch version that return all available space currentCapacity += allocSize; assert low + currentCapacity == high; } final int bytesProduced = produce (low, currentCapacity); if (bytesProduced > 0) { low+= bytesProduced; ring.publish(low); currentCapacity -= bytesProduced; } } //TODO:running.set(false); } /** * Produce content into the ringBuffer between positions <code>low</code> and <code>high</code>. * @param sequence start sequence * @param maxBytesToProduce maximum number of bytes to produce * @return size of produced content in bytes, greater than zero. */ protected abstract int produce(long sequence, int maxBytesToProduce); /** * Called each time producer's buffer is less than minimum. * @return additional buffer size to allocate */ protected int getAllocSize(int currentCapacity) { return 2*minimumProducerBufferSize; } }