mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-10 23:57:25 -05:00
126 - Significant improvement in processor and memory utilization. Refactors all USB tuner sample processing with a new USBTransferProcessor class. LibUSB transfer timeout processing is now consolidated under the TunerManager and tuners register with this singleton to auto-start or auto-stop USB bulk transfer processing. Resolves long-standing issue impacting multi-tuner use where the second and subsequent tuners may have been routinely starved for LibUSB processing time under heavy-loading. All tuner buffer threaded processing is now handled as runnables in the scheduled thread pool, eliminating tuner-dedicated processing threads. Added tuner buffer size management to prevent memory blow-out when down-stream processing is either lagging or impacted by java garbage collection operations. Both tuners and individual DDC channels now have bounded sample buffer queues that automatically enter and exit overflow mode when predefined max/reset thresholds are met. When any queue goes into overflow mode, sample buffers are simply dropped in favor of preserving program/memory stability.
This commit is contained in:
127
src/sample/OverflowableTransferQueue.java
Normal file
127
src/sample/OverflowableTransferQueue.java
Normal file
@@ -0,0 +1,127 @@
|
||||
/*******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2017 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 sample;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class OverflowableTransferQueue<E>
|
||||
{
|
||||
public enum State {NORMAL, OVERFLOW};
|
||||
private Listener<State> mStateListener;
|
||||
|
||||
private LinkedTransferQueue<E> mQueue = new LinkedTransferQueue<E>();
|
||||
private AtomicInteger mCounter = new AtomicInteger();
|
||||
private int mMaximumSize;
|
||||
private int mResetThreshold;
|
||||
private boolean mOverflow = false;
|
||||
|
||||
/**
|
||||
* Concurrent transfer queue that couples a higher-throughput linked transfer queue with an atomic integer for
|
||||
* monitoring queue size. When the queue size exceeds maximum size (overflow), all inbound elements are ignored
|
||||
* until the queue size is reduced to or below the reset threshold.
|
||||
*
|
||||
* @param maximumSize of the queue. Overflow state will occur once queue size exceeds this value.
|
||||
* @param resetThreshold for resetting overflow state to normal, once queue size is at or below this value.
|
||||
*/
|
||||
public OverflowableTransferQueue(int maximumSize, int resetThreshold)
|
||||
{
|
||||
mMaximumSize = maximumSize;
|
||||
mResetThreshold = resetThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the element to the queue if able to do so without exceeding maximum queue size. Otherwise, ignores
|
||||
* the element.
|
||||
*/
|
||||
public void offer(E e)
|
||||
{
|
||||
if(!mOverflow)
|
||||
{
|
||||
if(mCounter.get() > mMaximumSize)
|
||||
{
|
||||
setOverflow(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
mQueue.offer(e);
|
||||
mCounter.incrementAndGet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves elements from the queue into the collection up to the maximum number of elements specified
|
||||
*/
|
||||
public int drainTo(Collection<? super E> collection, int maxElements)
|
||||
{
|
||||
int drainCount = mQueue.drainTo(collection, maxElements);
|
||||
|
||||
if(drainCount > 0)
|
||||
{
|
||||
mCounter.addAndGet(-drainCount);
|
||||
}
|
||||
|
||||
return drainCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a listener to receive state change events
|
||||
*/
|
||||
public void setStateListener(Listener<State> listener)
|
||||
{
|
||||
mStateListener = listener;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Current state of the queue, normal or overflow
|
||||
*/
|
||||
public State getState()
|
||||
{
|
||||
return mOverflow ? State.OVERFLOW : State.NORMAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the overflow state
|
||||
*/
|
||||
private void setOverflow(boolean overflow)
|
||||
{
|
||||
mOverflow = overflow;
|
||||
|
||||
if(mStateListener != null)
|
||||
{
|
||||
mStateListener.receive(getState());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all elements from the queue and resets the internal counter to 0
|
||||
*/
|
||||
public void clear()
|
||||
{
|
||||
synchronized(mQueue)
|
||||
{
|
||||
mQueue.clear();
|
||||
mCounter.set(0);
|
||||
mOverflow = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user