mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
#1178 removes synchronization on channel processing manager's source event handler to enable more fine-grained channel start/stop event processing. This was causing the channel start and stop events to occur sequentially. Adds stream processing with coordinated heartbeat. (#1185)
Co-authored-by: Dennis Sheirer <dsheirer@github.com>
This commit is contained in:
@@ -1,247 +0,0 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.source.tuner.channel;
|
||||
|
||||
import io.github.dsheirer.buffer.INativeBuffer;
|
||||
import io.github.dsheirer.buffer.NativeBufferPoisonPill;
|
||||
import io.github.dsheirer.dsp.filter.cic.PrimeCicDecimationFilter;
|
||||
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
||||
import io.github.dsheirer.dsp.mixer.ComplexMixer;
|
||||
import io.github.dsheirer.dsp.mixer.ComplexMixerFactory;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.complex.ComplexSamples;
|
||||
import io.github.dsheirer.sample.complex.ComplexSamplesRepackager;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
import io.github.dsheirer.util.Dispatcher;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Complex sample source that provides a frequency-translated and decimated sample buffer stream. Uses a
|
||||
* CIC decimation filter that requires the decimation rate to be an integer multiple. Sample buffer processing
|
||||
* occurs on a scheduled runnable thread.
|
||||
*/
|
||||
public class CICTunerChannelSource<T extends INativeBuffer> extends TunerChannelSource implements Listener<T>
|
||||
{
|
||||
//Maximum number of filled buffers for the blocking queue
|
||||
private static final int BUFFER_MAX_CAPACITY = 300;
|
||||
|
||||
//Threshold for resetting buffer overflow condition
|
||||
private static final int BUFFER_OVERFLOW_RESET_THRESHOLD = 100;
|
||||
|
||||
//Samples repackager is set to 2048 (a power of 2) to align with channel processing chain requirements.
|
||||
private final ComplexSamplesRepackager mSamplesRepackager = new ComplexSamplesRepackager(1024);
|
||||
private Dispatcher<T> mBufferDispatcher;
|
||||
private ComplexMixer mFrequencyCorrectionMixer;
|
||||
private PrimeCicDecimationFilter mIDecimationFilter;
|
||||
private PrimeCicDecimationFilter mQDecimationFilter;
|
||||
private double mChannelSampleRate;
|
||||
private long mChannelFrequencyCorrection = 0;
|
||||
private long mTunerFrequency;
|
||||
private Listener<ComplexSamples> mListener;
|
||||
|
||||
/**
|
||||
* Constructs a frequency translating and CIC decimating channel source.
|
||||
*
|
||||
* @param producerSourceEventListener to receive sample stream start/stop requests
|
||||
* @param tunerChannel that details the desired channel frequency and bandwidth
|
||||
* @param sampleRate of the incoming sample stream
|
||||
* @param channelSpecification for the requested channel.
|
||||
* @throws FilterDesignException if a final cleanup filter cannot be designed using the remez filter
|
||||
* designer and the filter parameters.
|
||||
*/
|
||||
public CICTunerChannelSource(Listener<SourceEvent> producerSourceEventListener, TunerChannel tunerChannel,
|
||||
double sampleRate, ChannelSpecification channelSpecification) throws FilterDesignException
|
||||
{
|
||||
super(producerSourceEventListener, tunerChannel);
|
||||
|
||||
int decimation = (int)(sampleRate / channelSpecification.getMinimumSampleRate());
|
||||
|
||||
mIDecimationFilter = new PrimeCicDecimationFilter(sampleRate, decimation, channelSpecification.getPassFrequency(),
|
||||
channelSpecification.getStopFrequency());
|
||||
mQDecimationFilter = new PrimeCicDecimationFilter(sampleRate, decimation, channelSpecification.getPassFrequency(),
|
||||
channelSpecification.getStopFrequency());
|
||||
|
||||
mBufferDispatcher = new Dispatcher(BUFFER_MAX_CAPACITY, "sdrtrunk cic channel " +
|
||||
tunerChannel.getFrequency(), new NativeBufferPoisonPill());
|
||||
mBufferDispatcher.setListener(new NativeBufferProcessor());
|
||||
|
||||
//Setup the frequency mixer to the current source frequency
|
||||
mChannelSampleRate = sampleRate / (double)decimation;
|
||||
mTunerFrequency = tunerChannel.getFrequency();
|
||||
long frequencyOffset = mTunerFrequency - getTunerChannel().getFrequency();
|
||||
|
||||
mFrequencyCorrectionMixer = ComplexMixerFactory.getMixer(frequencyOffset, sampleRate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
{
|
||||
super.start();
|
||||
mBufferDispatcher.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
super.stop();
|
||||
mBufferDispatcher.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Primary interface for receiving incoming complex sample buffers to be frequency translated and decimated.
|
||||
*/
|
||||
@Override
|
||||
public void receive(T complexSamples)
|
||||
{
|
||||
mBufferDispatcher.receive(complexSamples);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets/updates the center frequency for the sample streaming being sent from the producer.
|
||||
*
|
||||
* @param frequency in hertz
|
||||
*/
|
||||
@Override
|
||||
public void setFrequency(long frequency)
|
||||
{
|
||||
mTunerFrequency = frequency;
|
||||
updateMixerFrequencyOffset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Current frequency correction being applied to the channel sample stream
|
||||
*
|
||||
* @return correction in hertz
|
||||
*/
|
||||
public long getFrequencyCorrection()
|
||||
{
|
||||
return mChannelFrequencyCorrection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the frequency correction value and broadcasts the change to the registered downstream listener.
|
||||
*
|
||||
* @param correction current frequency correction value.
|
||||
*/
|
||||
public void setFrequencyCorrection(long correction)
|
||||
{
|
||||
mChannelFrequencyCorrection = correction;
|
||||
updateMixerFrequencyOffset();
|
||||
broadcastConsumerSourceEvent(SourceEvent.frequencyCorrectionChange(mChannelFrequencyCorrection));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the local mixer frequency offset from the tuned frequency,
|
||||
* channel's requested frequency, and channel frequency correction.
|
||||
*/
|
||||
private void updateMixerFrequencyOffset()
|
||||
{
|
||||
long offset = mTunerFrequency - getTunerChannel().getFrequency() - mChannelFrequencyCorrection;
|
||||
mFrequencyCorrectionMixer.setFrequency(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sample rate of the incoming sample stream from the producer
|
||||
*
|
||||
* @param sampleRate in hertz
|
||||
*/
|
||||
@Override
|
||||
protected void setSampleRate(double sampleRate)
|
||||
{
|
||||
//Not implemented. Sample rate changes are not permitted once sample stream starts
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the frequency correction for the outbound sample stream to the consumer
|
||||
*
|
||||
* @param correction in hertz
|
||||
*/
|
||||
@Override
|
||||
protected void setChannelFrequencyCorrection(long correction)
|
||||
{
|
||||
mChannelFrequencyCorrection = correction;
|
||||
broadcastConsumerSourceEvent(SourceEvent.channelFrequencyCorrectionChange(correction));
|
||||
updateMixerFrequencyOffset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Frequency correction value currently being applied to the outbound sample stream
|
||||
*/
|
||||
@Override
|
||||
public long getChannelFrequencyCorrection()
|
||||
{
|
||||
return mChannelFrequencyCorrection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the listener to receive the complex buffer sample output from this channel
|
||||
*
|
||||
* @param listener to receive complex buffers
|
||||
*/
|
||||
@Override
|
||||
public void setListener(Listener<ComplexSamples> listener)
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getSampleRate()
|
||||
{
|
||||
return mChannelSampleRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes native buffers received from the dispatcher and sends to the registered listener
|
||||
*/
|
||||
public class NativeBufferProcessor implements Listener<T>
|
||||
{
|
||||
@Override
|
||||
public void receive(T nativeBuffer)
|
||||
{
|
||||
getHeartbeatManager().broadcast();
|
||||
|
||||
if(mListener != null)
|
||||
{
|
||||
Iterator<ComplexSamples> iterator = nativeBuffer.iterator();
|
||||
|
||||
while(iterator.hasNext())
|
||||
{
|
||||
ComplexSamples basebanded = mFrequencyCorrectionMixer.mix(iterator.next());
|
||||
float[] i = mIDecimationFilter.decimate(basebanded.i());
|
||||
float[] q = mQDecimationFilter.decimate(basebanded.q());
|
||||
|
||||
List<ComplexSamples> repackaged = mSamplesRepackager.process(i, q);
|
||||
|
||||
for(ComplexSamples samples: repackaged)
|
||||
{
|
||||
mListener.receive(samples);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,7 @@ public class HalfBandTunerChannelSource<T extends INativeBuffer> extends TunerCh
|
||||
private long mChannelFrequencyCorrection = 0;
|
||||
private long mTunerFrequency;
|
||||
private Listener<ComplexSamples> mListener;
|
||||
private StreamProcessorWithHeartbeat<ComplexSamples> mStreamHeartbeatProcessor;
|
||||
|
||||
/**
|
||||
* Constructs a frequency translating and CIC decimating channel source.
|
||||
@@ -70,6 +71,8 @@ public class HalfBandTunerChannelSource<T extends INativeBuffer> extends TunerCh
|
||||
{
|
||||
super(producerSourceEventListener, tunerChannel);
|
||||
|
||||
mStreamHeartbeatProcessor = new StreamProcessorWithHeartbeat<>(getHeartbeatManager(), HEARTBEAT_INTERVAL_MS);
|
||||
|
||||
int desiredDecimation = (int)(sampleRate / channelSpecification.getMinimumSampleRate());
|
||||
int decimation = DecimationFilterFactory.getDecimationRate(desiredDecimation);
|
||||
|
||||
@@ -91,6 +94,7 @@ public class HalfBandTunerChannelSource<T extends INativeBuffer> extends TunerCh
|
||||
public void start()
|
||||
{
|
||||
super.start();
|
||||
mStreamHeartbeatProcessor.start();
|
||||
mBufferDispatcher.start();
|
||||
}
|
||||
|
||||
@@ -99,6 +103,7 @@ public class HalfBandTunerChannelSource<T extends INativeBuffer> extends TunerCh
|
||||
{
|
||||
super.stop();
|
||||
mBufferDispatcher.stop();
|
||||
mStreamHeartbeatProcessor.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -200,13 +205,7 @@ public class HalfBandTunerChannelSource<T extends INativeBuffer> extends TunerCh
|
||||
@Override
|
||||
public void setListener(Listener<ComplexSamples> listener)
|
||||
{
|
||||
if(listener == null)
|
||||
{
|
||||
//Wait for the native buffer processor thread to die before we nullify the listener
|
||||
stop();
|
||||
}
|
||||
|
||||
mListener = listener;
|
||||
mStreamHeartbeatProcessor.setListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -223,21 +222,14 @@ public class HalfBandTunerChannelSource<T extends INativeBuffer> extends TunerCh
|
||||
@Override
|
||||
public void receive(T nativeBuffer)
|
||||
{
|
||||
getHeartbeatManager().broadcast();
|
||||
Iterator<ComplexSamples> iterator = nativeBuffer.iterator();
|
||||
|
||||
Listener<ComplexSamples> listener = mListener;
|
||||
|
||||
if(listener != null)
|
||||
while(iterator.hasNext())
|
||||
{
|
||||
Iterator<ComplexSamples> iterator = nativeBuffer.iterator();
|
||||
|
||||
while(iterator.hasNext())
|
||||
{
|
||||
ComplexSamples basebanded = mFrequencyCorrectionMixer.mix(iterator.next());
|
||||
float[] i = mIDecimationFilter.decimateReal(basebanded.i());
|
||||
float[] q = mQDecimationFilter.decimateReal(basebanded.q());
|
||||
listener.receive(new ComplexSamples(i, q));
|
||||
}
|
||||
ComplexSamples basebanded = mFrequencyCorrectionMixer.mix(iterator.next());
|
||||
float[] i = mIDecimationFilter.decimateReal(basebanded.i());
|
||||
float[] q = mQDecimationFilter.decimateReal(basebanded.q());
|
||||
mStreamHeartbeatProcessor.receive(new ComplexSamples(i, q));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class PassThroughChannelSource extends TunerChannelSource implements ISou
|
||||
private final static Logger mLog = LoggerFactory.getLogger(PassThroughChannelSource.class);
|
||||
private TunerController mTunerController;
|
||||
private Dispatcher<INativeBuffer> mBufferDispatcher;
|
||||
private Listener<ComplexSamples> mComplexSamplesListener;
|
||||
private StreamProcessorWithHeartbeat<ComplexSamples> mStreamHeartbeatProcessor;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
@@ -59,12 +59,14 @@ public class PassThroughChannelSource extends TunerChannelSource implements ISou
|
||||
mBufferDispatcher = new Dispatcher<>(500, "sdrtrunk pass-through channel " +
|
||||
tunerChannel.getFrequency(), new NativeBufferPoisonPill());
|
||||
mBufferDispatcher.setListener(new BufferProcessor());
|
||||
mStreamHeartbeatProcessor = new StreamProcessorWithHeartbeat<>(getHeartbeatManager(), HEARTBEAT_INTERVAL_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
{
|
||||
super.start();
|
||||
mStreamHeartbeatProcessor.stop();
|
||||
mBufferDispatcher.start();
|
||||
}
|
||||
|
||||
@@ -73,6 +75,7 @@ public class PassThroughChannelSource extends TunerChannelSource implements ISou
|
||||
{
|
||||
super.stop();
|
||||
mBufferDispatcher.stop();
|
||||
mStreamHeartbeatProcessor.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,9 +103,9 @@ public class PassThroughChannelSource extends TunerChannelSource implements ISou
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListener(Listener<ComplexSamples> complexSamplesListener)
|
||||
public void setListener(Listener<ComplexSamples> listener)
|
||||
{
|
||||
mComplexSamplesListener = complexSamplesListener;
|
||||
mStreamHeartbeatProcessor.setListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,16 +125,11 @@ public class PassThroughChannelSource extends TunerChannelSource implements ISou
|
||||
@Override
|
||||
public void receive(INativeBuffer nativeBuffer)
|
||||
{
|
||||
getHeartbeatManager().broadcast();
|
||||
Iterator<ComplexSamples> iterator = nativeBuffer.iterator();
|
||||
|
||||
if(mComplexSamplesListener != null)
|
||||
while(iterator.hasNext())
|
||||
{
|
||||
Iterator<ComplexSamples> iterator = nativeBuffer.iterator();
|
||||
|
||||
while(iterator.hasNext())
|
||||
{
|
||||
mComplexSamplesListener.receive(iterator.next());
|
||||
}
|
||||
mStreamHeartbeatProcessor.receive(iterator.next());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.channel;
|
||||
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.source.heartbeat.HeartbeatManager;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Thread-safe implementation that coordinates the flow of data/buffer stream processing with a parallel, periodic
|
||||
* heartbeat using an internal locking mechanism to coordinate the two activities. This class is intended to be used
|
||||
* by TunerChannelSource implementations to coordinate the flow of sample buffers produced on a dispatch thread with a
|
||||
* scheduled timer driven heartbeat mechanism, to ensure the downstream listener receives either samples or a
|
||||
* heartbeat, but not both at the same time.
|
||||
*
|
||||
* Samples are processed as they arrive and are immediately followed by a heartbeat. A separate scheduled timer runs
|
||||
* on a periodic schedule to optionally fire a heartbeat, independent of the sample stream rate. The scheduled
|
||||
* heartbeat is optional and will skip a heartbeat interval if this processor is currently dispatching a sample buffer.
|
||||
* Sample stream processing will block until a currently running scheduled heartbeat timer event completes, when these
|
||||
* two events occur at the same time.
|
||||
*/
|
||||
public class StreamProcessorWithHeartbeat<T> implements Listener<T>
|
||||
{
|
||||
private ReentrantLock mLock = new ReentrantLock();
|
||||
private HeartbeatManager mHeartbeatManager;
|
||||
private long mHeartbeatInterval;
|
||||
private Listener<T> mListener;
|
||||
private ScheduledFuture<?> mHeartbeatTimerFuture;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param heartbeatManager that will be invoked by an internal scheduled timer
|
||||
* @param heartbeatInterval in milliseconds
|
||||
*/
|
||||
public StreamProcessorWithHeartbeat(HeartbeatManager heartbeatManager, long heartbeatInterval)
|
||||
{
|
||||
mHeartbeatManager = heartbeatManager;
|
||||
mHeartbeatInterval = heartbeatInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the heartbeat timer
|
||||
*/
|
||||
public void start()
|
||||
{
|
||||
if(mHeartbeatTimerFuture == null)
|
||||
{
|
||||
mHeartbeatTimerFuture = ThreadPool.SCHEDULED.scheduleAtFixedRate(() -> fireOptionalHeartbeat(),
|
||||
mHeartbeatInterval, mHeartbeatInterval, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the heartbeat timer
|
||||
*/
|
||||
public void stop()
|
||||
{
|
||||
if(mHeartbeatTimerFuture != null)
|
||||
{
|
||||
mHeartbeatTimerFuture.cancel(true);
|
||||
mHeartbeatTimerFuture = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally fires a heartbeat if we're not currently processing a native buffer
|
||||
*/
|
||||
private void fireOptionalHeartbeat()
|
||||
{
|
||||
//Acquire lock only if it's not already locked, otherwise ignore heartbeat for this timer interval.
|
||||
if(mLock.tryLock())
|
||||
{
|
||||
try
|
||||
{
|
||||
mHeartbeatManager.broadcast();
|
||||
}
|
||||
finally
|
||||
{
|
||||
mLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive(T data)
|
||||
{
|
||||
mLock.lock();
|
||||
|
||||
try
|
||||
{
|
||||
mHeartbeatManager.broadcast();
|
||||
|
||||
Listener<T> listener = mListener;
|
||||
|
||||
if(listener != null)
|
||||
{
|
||||
listener.receive(data);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
mLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the listener to receive data/buffers for the defined generic type that are distributed to this processor.
|
||||
* @param listener to register or null to deregister an existing listener
|
||||
*/
|
||||
public void setListener(Listener<T> listener)
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
}
|
||||
@@ -31,12 +31,11 @@ import org.slf4j.LoggerFactory;
|
||||
public abstract class TunerChannelSource extends ComplexSource implements ISourceEventProcessor
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(TunerChannelSource.class);
|
||||
private static final long BUFFER_PROCESSOR_RUN_INTERVAL_MILLISECONDS = 50;
|
||||
protected static final long HEARTBEAT_INTERVAL_MS = 100;
|
||||
private SourceEventListenerToProcessorAdapter mConsumerSourceEventListenerAdapter;
|
||||
protected TunerChannel mTunerChannel;
|
||||
private Listener<SourceEvent> mProducerSourceEventListener;
|
||||
private Listener<SourceEvent> mConsumerSourceEventListener;
|
||||
// private ScheduledIntervalProcessor mScheduledIntervalProcessor = new ScheduledIntervalProcessor();
|
||||
|
||||
/**
|
||||
* Tuner Channel Source is a Digital Drop Channel (DDC) abstract class that defines the minimum functionality
|
||||
@@ -245,95 +244,4 @@ public abstract class TunerChannelSource extends ComplexSource implements ISourc
|
||||
{
|
||||
mConsumerSourceEventListener = null;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Processor to periodically invoke buffer sample processing on an interval timer. At each interval this processor
|
||||
// * sends a heartbeat to the registered consumer and then commands the sub-class implementation to process any
|
||||
// * queued buffers and distribute complex buffer sample(s) to the registered consumer.
|
||||
// */
|
||||
// public class ScheduledIntervalProcessor implements Runnable
|
||||
// {
|
||||
// private ScheduledFuture<?> mScheduledFuture;
|
||||
// private boolean mStopped = false;
|
||||
//
|
||||
// /**
|
||||
// * Commands this processor to do a shutdown at the end of this or the next iteration. Once successfully
|
||||
// * shutdown, it will invoke the performDisposal() method to cleanup this instance.
|
||||
// */
|
||||
// public void stop()
|
||||
// {
|
||||
// mStopped = true;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Starts buffer processing on a fixed interval using a scheduled thread pool
|
||||
// */
|
||||
// public void start()
|
||||
// {
|
||||
// if(mScheduledFuture == null)
|
||||
// {
|
||||
// mScheduledFuture = ThreadPool.SCHEDULED.scheduleAtFixedRate(this, 0,
|
||||
// BUFFER_PROCESSOR_RUN_INTERVAL_MILLISECONDS, TimeUnit.MILLISECONDS);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Implementation of the Runnable interface to periodically send a heartbeat and then process buffer samples.
|
||||
// */
|
||||
// @Override
|
||||
// public void run()
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// if(!mStopped)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// getHeartbeatManager().broadcast();
|
||||
// }
|
||||
// catch(Throwable t)
|
||||
// {
|
||||
// mLog.error("Error while sending heartbeat", t);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if(!mStopped)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// processSamples();
|
||||
// }
|
||||
// catch(Throwable t)
|
||||
// {
|
||||
// mLog.error("Error while processing samples", t);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if(mStopped)
|
||||
// {
|
||||
// if(mScheduledFuture != null)
|
||||
// {
|
||||
// //Set may-interrupt to false so that we can complete this iteration
|
||||
// mScheduledFuture.cancel(false);
|
||||
// }
|
||||
//
|
||||
// mScheduledFuture = null;
|
||||
//
|
||||
// try
|
||||
// {
|
||||
// getHeartbeatManager().broadcast();
|
||||
// performDisposal();
|
||||
// }
|
||||
// catch(Throwable t)
|
||||
// {
|
||||
// mLog.error("Error during final shutdown processing of samples", t);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// catch(Throwable t)
|
||||
// {
|
||||
// mLog.error("Error during heartbeat processing", t);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user