Add LocklessAllocator and use it in LocklessList (#2998)

This commit is contained in:
Javier Serrano Polo
2016-09-04 00:13:45 +00:00
committed by GitHub
parent f14cb687de
commit 5f54995188
7 changed files with 294 additions and 7 deletions

View File

@@ -6,20 +6,40 @@
#include <QtCore/QAtomicInt>
#if QT_VERSION >= 0x050000 && QT_VERSION <= 0x050300
#if QT_VERSION < 0x050300
class AtomicInt : public QAtomicInt
{
public:
AtomicInt(int value=0) : QAtomicInt(value) {};
AtomicInt( int value = 0 ) :
QAtomicInt( value )
{
}
int fetchAndAndOrdered( int valueToAnd )
{
int value;
do
{
value = (int)*this;
}
while( !testAndSetOrdered( value, value & valueToAnd ) );
return value;
}
#if QT_VERSION >= 0x050000 && QT_VERSION < 0x050300
operator int() const
{
return loadAcquire();
}
#endif
operator int() const {return loadAcquire();}
};
#else
typedef QAtomicInt AtomicInt;
#endif // QT_VERSION >= 0x050000 && QT_VERSION <= 0x050300
#endif // QT_VERSION < 0x050300
#endif

View File

@@ -0,0 +1,83 @@
/*
* LocklessAllocator.h - allocator with lockless alloc and free
*
* Copyright (c) 2016 Javier Serrano Polo <javier@jasp.net>
*
* This file is part of LMMS - http://lmms.io
*
* 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 2 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 (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef LOCKLESS_ALLOCATOR_H
#define LOCKLESS_ALLOCATOR_H
#include <stddef.h>
#include "AtomicInt.h"
class LocklessAllocator
{
public:
LocklessAllocator( size_t nmemb, size_t size );
virtual ~LocklessAllocator();
void * alloc();
void free( void * ptr );
private:
char * m_pool;
size_t m_capacity;
size_t m_elementSize;
AtomicInt * m_freeState;
size_t m_freeStateSets;
AtomicInt m_available;
AtomicInt m_startIndex;
} ;
template<typename T>
class LocklessAllocatorT : private LocklessAllocator
{
public:
LocklessAllocatorT( size_t nmemb ) :
LocklessAllocator( nmemb, sizeof( T ) )
{
}
virtual ~LocklessAllocatorT()
{
}
T * alloc()
{
return (T *)LocklessAllocator::alloc();
}
void free( T * ptr )
{
LocklessAllocator::free( ptr );
}
} ;
#endif

View File

@@ -27,6 +27,8 @@
#include <QAtomicPointer>
#include "LocklessAllocator.h"
template<typename T>
class LocklessList
{
@@ -37,9 +39,19 @@ public:
Element * next;
} ;
LocklessList( size_t size )
{
m_allocator = new LocklessAllocatorT<Element>( size );
}
~LocklessList()
{
delete m_allocator;
}
void push( T value )
{
Element * e = new Element;
Element * e = m_allocator->alloc();
e->value = value;
do
@@ -76,9 +88,15 @@ public:
#endif
}
void free( Element * e )
{
m_allocator->free( e );
}
private:
QAtomicPointer<Element> m_first;
LocklessAllocatorT<Element> * m_allocator;
} ;

View File

@@ -47,6 +47,11 @@ public:
} ;
typedef Types Type;
enum
{
MaxNumber = 1024
} ;
PlayHandle( const Type type, f_cnt_t offset = 0 );
PlayHandle & operator = ( PlayHandle & p )