Improved buffer-allocator
git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@71 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* buffer_allocator.cpp - namespace bufferAllocator providing routines for own
|
||||
* optimized memory-management for audio-buffers
|
||||
*
|
||||
* Copyright (c) 2005 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2005-2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -66,7 +66,7 @@ inline bool operator<( const bufDesc & _bd1, const bufDesc & _bd2 )
|
||||
return( _bd1.timesUsed < _bd2.timesUsed );
|
||||
}
|
||||
|
||||
#ifdef QT4
|
||||
#ifndef QT3
|
||||
|
||||
inline bool operator==( const bufDesc & _bd1, const bufDesc & _bd2 )
|
||||
{
|
||||
@@ -86,7 +86,9 @@ inline bool operator!=( const bufDesc & _bd1, const bufDesc & _bd2 )
|
||||
static vlist<bufDesc> s_buffers;
|
||||
typedef vlist<bufDesc>::iterator bufIt;
|
||||
|
||||
QMutex s_buffersMutex;
|
||||
static int s_freeBufs = 0;
|
||||
static bool s_autoCleanupDisabled = FALSE;
|
||||
static QMutex s_buffersMutex;
|
||||
|
||||
|
||||
const int BUFFER_ALIGN = 16;
|
||||
@@ -112,13 +114,16 @@ void bufferAllocator::cleanUp( Uint16 _level )
|
||||
|
||||
const Sint16 todo = tMin<Sint16>( s_buffers.size() - _level,
|
||||
bufsToRemove.size() );
|
||||
|
||||
// now cleanup the first n elements of sorted array
|
||||
for( Sint16 i = 0; i < todo; ++i )
|
||||
{
|
||||
delete[] bufsToRemove[i].origPtr;
|
||||
s_buffers.erase( qFind( s_buffers.begin(), s_buffers.end(),
|
||||
bufsToRemove[i] ) );
|
||||
--s_freeBufs;
|
||||
}
|
||||
|
||||
#ifdef LMMS_DEBUG
|
||||
//printf( "cleaned up %d buffers\n", todo );
|
||||
#endif
|
||||
@@ -138,17 +143,23 @@ void bufferAllocator::free( void * _buf )
|
||||
{
|
||||
++( *it ).timesUsed;
|
||||
( *it ).free = TRUE;
|
||||
++s_freeBufs;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// do clean-up if neccessary
|
||||
static Uint16 CLEANUP_LEVEL = static_cast<Uint16>( 512 / ( logf(
|
||||
static const Uint32 CLEANUP_LEVEL = static_cast<Uint32>( 768 / ( logf(
|
||||
mixer::inst()->framesPerAudioBuffer() ) /
|
||||
logf( 2 ) ) );
|
||||
if( s_buffers.size() > CLEANUP_LEVEL )
|
||||
static int count = 0;
|
||||
// only cleanup every 10th time, because otherwise there's a lot of
|
||||
// overhead e.g. when freeing a lot of single buffers
|
||||
if( s_autoCleanupDisabled == FALSE &&
|
||||
s_buffers.size() > CLEANUP_LEVEL && ++count > 10 )
|
||||
{
|
||||
cleanUp( CLEANUP_LEVEL );
|
||||
count = 0;
|
||||
}
|
||||
|
||||
s_buffersMutex.unlock();
|
||||
@@ -161,26 +172,37 @@ void * bufferAllocator::allocBytes( Uint32 _bytes )
|
||||
{
|
||||
QMutexLocker ml( &s_buffersMutex );
|
||||
|
||||
bufIt free_buf = s_buffers.end();
|
||||
|
||||
// look whether there's a buffer matching to the one wanted and
|
||||
// find out the most used one (higher chances for being in CPU-cache)
|
||||
for( bufIt it = s_buffers.begin(); it != s_buffers.end(); ++it )
|
||||
// there's a low probability that we find a matching buffer, if there're
|
||||
// less than 2 bufs available, so do not search - this speeds up
|
||||
// processes like pattern-freezing because this way we do not have to
|
||||
// search for a free buffer in an array, containing several
|
||||
// 10.000 buffers
|
||||
if( s_freeBufs > s_buffers.size() / 10 )
|
||||
{
|
||||
if( ( *it ).free && ( *it ).bytes == _bytes )
|
||||
bufIt free_buf = s_buffers.end();
|
||||
|
||||
// look whether there's a buffer matching to the one wanted and
|
||||
// find out the most used one (higher chances for being in CPU-
|
||||
// cache)
|
||||
for( bufIt it = s_buffers.begin(); it != s_buffers.end(); ++it )
|
||||
{
|
||||
if( free_buf == s_buffers.end() ||
|
||||
( *it ).timesUsed > ( *free_buf ).timesUsed )
|
||||
if( ( *it ).free && ( *it ).bytes == _bytes )
|
||||
{
|
||||
free_buf = it;
|
||||
if( free_buf == s_buffers.end() ||
|
||||
( *it ).timesUsed >
|
||||
( *free_buf ).timesUsed )
|
||||
{
|
||||
free_buf = it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( free_buf != s_buffers.end() )
|
||||
{
|
||||
( *free_buf ).free = FALSE;
|
||||
return( ( *free_buf ).buf );
|
||||
if( free_buf != s_buffers.end() )
|
||||
{
|
||||
--s_freeBufs;
|
||||
( *free_buf ).free = FALSE;
|
||||
return( ( *free_buf ).buf );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -195,3 +217,9 @@ void * bufferAllocator::allocBytes( Uint32 _bytes )
|
||||
|
||||
|
||||
|
||||
|
||||
void bufferAllocator::disableAutoCleanup( bool _disabled )
|
||||
{
|
||||
s_autoCleanupDisabled = _disabled;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "tooltip.h"
|
||||
#include "bb_editor.h"
|
||||
#include "string_pair_drag.h"
|
||||
#include "buffer_allocator.h"
|
||||
|
||||
|
||||
QPixmap * pattern::s_stepBtnOn = NULL;
|
||||
@@ -1145,7 +1146,8 @@ void pattern::updateBBTrack( void )
|
||||
|
||||
patternFreezeStatusDialog::patternFreezeStatusDialog( QThread * _thread ) :
|
||||
QDialog(),
|
||||
m_freezeThread( _thread )
|
||||
m_freezeThread( _thread ),
|
||||
m_progress( 0 )
|
||||
{
|
||||
setWindowTitle( tr( "Freezing pattern..." ) );
|
||||
#if QT_VERSION >= 0x030200
|
||||
@@ -1249,6 +1251,7 @@ patternFreezeThread::patternFreezeThread( pattern * _pattern ) :
|
||||
QThread(),
|
||||
m_pattern( _pattern )
|
||||
{
|
||||
// create status-dialog
|
||||
m_statusDlg = new patternFreezeStatusDialog( this );
|
||||
QObject::connect( m_statusDlg, SIGNAL( aborted() ),
|
||||
m_pattern, SLOT( abortFreeze() ) );
|
||||
@@ -1269,6 +1272,8 @@ patternFreezeThread::~patternFreezeThread()
|
||||
|
||||
void patternFreezeThread::run( void )
|
||||
{
|
||||
bufferAllocator::disableAutoCleanup( TRUE );
|
||||
|
||||
// create and install audio-sample-recorder
|
||||
bool b;
|
||||
// we cannot create local copy, because at a later stage
|
||||
@@ -1288,10 +1293,10 @@ void patternFreezeThread::run( void )
|
||||
ppp.setCurrentFrame( 0 );
|
||||
ppp.m_timeLineUpdate = FALSE;
|
||||
|
||||
// create status-dialog
|
||||
m_pattern->m_freezeAborted = FALSE;
|
||||
m_pattern->m_freezing = TRUE;
|
||||
|
||||
|
||||
// now render everything
|
||||
while( ppp < m_pattern->length() &&
|
||||
m_pattern->m_freezeAborted == FALSE )
|
||||
@@ -1300,6 +1305,7 @@ void patternFreezeThread::run( void )
|
||||
m_statusDlg->setProgress( ppp * 100 / m_pattern->length() );
|
||||
}
|
||||
|
||||
|
||||
m_pattern->m_freezing = FALSE;
|
||||
|
||||
// reset song-editor settings
|
||||
@@ -1315,6 +1321,8 @@ void patternFreezeThread::run( void )
|
||||
m_pattern->m_frozenPatternMutex.unlock();
|
||||
}
|
||||
|
||||
bufferAllocator::disableAutoCleanup( FALSE );
|
||||
|
||||
// restore original audio-device
|
||||
mixer::inst()->restoreAudioDevice();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user