Browse Source

Rename list to LinkedList, fix const issues

tags/1.9.4
falkTX 11 years ago
parent
commit
02244e31d5
6 changed files with 62 additions and 303 deletions
  1. +2
    -1
      .gitignore
  2. +2
    -2
      source/modules/rtmempool/list.h
  3. +6
    -2
      source/tests/Makefile
  4. +0
    -195
      source/tests/RtList.cpp
  5. +28
    -77
      source/utils/LinkedList.hpp
  6. +24
    -26
      source/utils/RtLinkedList.hpp

+ 2
- 1
.gitignore View File

@@ -75,7 +75,8 @@ source/tests/CarlaString
source/tests/DGL1 source/tests/DGL1
source/tests/DGL2 source/tests/DGL2
source/tests/Print source/tests/Print
source/tests/RtList
source/tests/RtLinkedList
source/tests/RtLinkedListGnu
source/tests/Utils source/tests/Utils
source/tests/Widgets source/tests/Widgets




+ 2
- 2
source/modules/rtmempool/list.h View File

@@ -50,7 +50,7 @@
* *
*/ */
#define container_of(ptr, type, member) ({ \ #define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type, member) );}) (type *)( (char *)__mptr - offsetof(type, member) );})


#define container_of_const(ptr, type, member) ({ \ #define container_of_const(ptr, type, member) ({ \
@@ -304,7 +304,7 @@ static inline void list_splice_tail_init(struct list_head *list, struct list_hea
* @type: the type of the struct this is embedded in. * @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct. * @member: the name of the list_struct within the struct.
*/ */
#if defined(__GNUC__) && ! (defined(BUILD_ANSI_TEST) || defined(QTCREATOR_TEST))
#if defined(__GNUC__) && ! defined(__STRICT_ANSI__)
# define list_entry(ptr, type, member) \ # define list_entry(ptr, type, member) \
container_of(ptr, type, member) container_of(ptr, type, member)
# define list_entry_const(ptr, type, member) \ # define list_entry_const(ptr, type, member) \


+ 6
- 2
source/tests/Makefile View File

@@ -75,9 +75,13 @@ Print: Print.cpp
$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o $@ $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -o $@
# valgrind ./Print # valgrind ./Print


RtList: RtList.cpp ../utils/RtList.hpp ../modules/rtmempool.a
RtLinkedList: RtLinkedList.cpp ../utils/LinkedList.hpp ../utils/RtLinkedList.hpp ../modules/rtmempool.a
$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -lpthread -o $@ $(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) -lpthread -o $@
# valgrind ./RtList
valgrind ./RtLinkedList

RtLinkedListGnu: RtLinkedList.cpp ../utils/LinkedList.hpp ../utils/RtLinkedList.hpp ../modules/rtmempool.a
$(CXX) $^ $(BUILD_CXX_FLAGS) -std=gnu++11 $(LINK_FLAGS) -lpthread -o $@
valgrind ./RtLinkedListGnu


Utils: Utils.cpp Utils: Utils.cpp
$(CXX) $^ $(BUILD_CXX_FLAGS) $(ANSI_CXX_FLAGS) -std=c++11 -Wzero-as-null-pointer-constant $(LINK_FLAGS) -ldl -lpthread -o $@ $(CXX) $^ $(BUILD_CXX_FLAGS) $(ANSI_CXX_FLAGS) -std=c++11 -Wzero-as-null-pointer-constant $(LINK_FLAGS) -ldl -lpthread -o $@


+ 0
- 195
source/tests/RtList.cpp View File

@@ -1,195 +0,0 @@
/*
* Carla Tests
* Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
*
* 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 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.
*
* For a full copy of the GNU General Public License see the doc/GPL.txt file.
*/

#include "RtList.hpp"

#include "CarlaString.hpp"
#include "CarlaMutex.hpp"

const unsigned short MIN_RT_EVENTS = 5;
const unsigned short MAX_RT_EVENTS = 10;

struct MyData {
CarlaString str;
int idStr;

MyData()
: idStr(-1) {}

MyData(int id)
: str(id),
idStr(id) {}
};

struct PostRtEvents {
CarlaMutex mutex;
RtList<MyData>::Pool dataPool;
RtList<MyData> data;
RtList<MyData> dataPendingRT;

PostRtEvents()
: dataPool(MIN_RT_EVENTS, MAX_RT_EVENTS),
data(dataPool),
dataPendingRT(dataPool) {}

~PostRtEvents()
{
clear();
}

void appendRT(const MyData& event)
{
dataPendingRT.append(event);
}

void clear()
{
mutex.lock();
data.clear();
dataPendingRT.clear();
mutex.unlock();
}

void trySplice()
{
if (mutex.tryLock())
{
dataPendingRT.spliceAppend(data);
mutex.unlock();
}
}

} postRtEvents;

void run5Tests()
{
unsigned short k = 0;
MyData allMyData[MAX_RT_EVENTS];

// Make a safe copy of events while clearing them
postRtEvents.mutex.lock();

while (! postRtEvents.data.isEmpty())
{
const MyData& my(postRtEvents.data.getFirst(true));
allMyData[k++] = my;
}

postRtEvents.mutex.unlock();

printf("Post-Rt Event Count: %i\n", k);
assert(k == 5);

// data should be empty now
assert(postRtEvents.data.count() == 0);
assert(postRtEvents.data.isEmpty());
assert(postRtEvents.dataPendingRT.count() == 0);
assert(postRtEvents.dataPendingRT.isEmpty());

// Handle events now
for (unsigned short i=0; i < k; ++i)
{
const MyData& my(allMyData[i]);

printf("Got data: %i %s\n", my.idStr, (const char*)my.str);
}
}

int main()
{
MyData m1(1);
MyData m2(2);
MyData m3(3);
MyData m4(4);
MyData m5(5);

// start
assert(postRtEvents.data.count() == 0);
assert(postRtEvents.data.isEmpty());
assert(postRtEvents.dataPendingRT.count() == 0);
assert(postRtEvents.dataPendingRT.isEmpty());

// single append
postRtEvents.appendRT(m1);
postRtEvents.trySplice();
assert(postRtEvents.data.count() == 1);
assert(postRtEvents.dataPendingRT.count() == 0);

// +3 appends
postRtEvents.appendRT(m2);
postRtEvents.appendRT(m4);
postRtEvents.appendRT(m3);
assert(postRtEvents.data.count() == 1);
assert(postRtEvents.dataPendingRT.count() == 3);
postRtEvents.trySplice();
assert(postRtEvents.data.count() == 4);
assert(postRtEvents.dataPendingRT.count() == 0);

for (RtList<MyData>::Itenerator it = postRtEvents.data.begin(); it.valid(); it.next())
{
MyData& my(*it);

printf("FOR DATA!!!: %i %s\n", my.idStr, (const char*)my.str);

if (my.idStr == 1)
{
// +1 append at
postRtEvents.dataPendingRT.insertAt(m5, it);
assert(postRtEvents.data.count() == 4);
assert(postRtEvents.dataPendingRT.count() == 1);
postRtEvents.trySplice();
assert(postRtEvents.data.count() == 5);
assert(postRtEvents.dataPendingRT.count() == 0);
}
}

run5Tests();

// reset
postRtEvents.clear();
assert(postRtEvents.data.count() == 0);
assert(postRtEvents.data.isEmpty());
assert(postRtEvents.dataPendingRT.count() == 0);
assert(postRtEvents.dataPendingRT.isEmpty());

// test non-rt
const unsigned int CARLA_EVENT_DATA_ATOM = 0x01;
const unsigned int CARLA_EVENT_DATA_MIDI_LL = 0x04;

NonRtList<uint32_t> evIns, evOuts;
evIns.append(CARLA_EVENT_DATA_ATOM);
evOuts.append(CARLA_EVENT_DATA_ATOM);
evOuts.append(CARLA_EVENT_DATA_MIDI_LL);

if (evIns.count() > 0)
{
for (uint32_t j=0, count=evIns.count(); j < count; ++j)
{
const uint32_t& type(evIns.getAt(j));

if (type == CARLA_EVENT_DATA_ATOM)
pass();
else if (type == CARLA_EVENT_DATA_MIDI_LL)
pass();
}
}

evIns.clear();
evOuts.clear();

return 0;
}

source/utils/List.hpp → source/utils/LinkedList.hpp View File

@@ -1,6 +1,6 @@
/* /*
* High-level, templated, C++ doubly-linked list * High-level, templated, C++ doubly-linked list
* Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
@@ -15,8 +15,8 @@
* For a full copy of the GNU General Public License see the doc/GPL.txt file. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
*/ */


#ifndef LIST_HPP_INCLUDED
#define LIST_HPP_INCLUDED
#ifndef LINKED_LIST_HPP_INCLUDED
#define LINKED_LIST_HPP_INCLUDED


#include "CarlaUtils.hpp" #include "CarlaUtils.hpp"


@@ -28,26 +28,26 @@ extern "C" {


// Declare non copyable and prevent heap allocation // Declare non copyable and prevent heap allocation
#ifdef CARLA_PROPER_CPP11_SUPPORT #ifdef CARLA_PROPER_CPP11_SUPPORT
# define LIST_DECLARATIONS(ClassName) \
# define LINKED_LIST_DECLARATIONS(ClassName) \
ClassName(ClassName&) = delete; \ ClassName(ClassName&) = delete; \
ClassName(const ClassName&) = delete; \ ClassName(const ClassName&) = delete; \
ClassName& operator=(const ClassName&) = delete; \ ClassName& operator=(const ClassName&) = delete; \
static void* operator new(size_t) = delete; static void* operator new(size_t) = delete;
#else #else
# define LIST_DECLARATIONS(ClassName) \
ClassName(ClassName&); \
ClassName(const ClassName&); \
# define LINKED_LIST_DECLARATIONS(ClassName) \
ClassName(ClassName&); \
ClassName(const ClassName&); \
ClassName& operator=(const ClassName&); ClassName& operator=(const ClassName&);
#endif #endif


typedef struct list_head k_list_head; typedef struct list_head k_list_head;


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Abstract List class
// Abstract Linked List class
// _allocate() and _deallocate are virtual calls provided by subclasses // _allocate() and _deallocate are virtual calls provided by subclasses


template<typename T> template<typename T>
class AbstractList
class AbstractLinkedList
{ {
protected: protected:
struct Data { struct Data {
@@ -55,26 +55,26 @@ protected:
k_list_head siblings; k_list_head siblings;
}; };


AbstractList()
AbstractLinkedList()
: fDataSize(sizeof(Data)), : fDataSize(sizeof(Data)),
fCount(0) fCount(0)
{ {
_init(); _init();
} }


virtual ~AbstractList()
public:
virtual ~AbstractLinkedList()
{ {
CARLA_ASSERT(fCount == 0); CARLA_ASSERT(fCount == 0);
} }


public:
class Itenerator { class Itenerator {
public: public:
Itenerator(const k_list_head* queue) Itenerator(const k_list_head* queue)
: fEntry(queue->next),
: fData(nullptr),
fEntry(queue->next),
fEntry2(fEntry->next), fEntry2(fEntry->next),
fQueue(queue),
fData(nullptr)
fQueue(queue)
{ {
CARLA_ASSERT(fEntry != nullptr); CARLA_ASSERT(fEntry != nullptr);
CARLA_ASSERT(fEntry2 != nullptr); CARLA_ASSERT(fEntry2 != nullptr);
@@ -99,31 +99,13 @@ public:
return fData->value; return fData->value;
} }


const T& getConstValue()
{
fConstData = list_entry_const(fEntry, Data, siblings);
CARLA_ASSERT(fConstData != nullptr);
return fConstData->value;
}

#if 0
T& operator*() const
{
return getValue();
}
#endif

private: private:
Data* fData;
k_list_head* fEntry; k_list_head* fEntry;
k_list_head* fEntry2; k_list_head* fEntry2;
const k_list_head* const fQueue; const k_list_head* const fQueue;


union {
Data* fData;
const Data* fConstData;
};

friend class AbstractList;
friend class AbstractLinkedList;
}; };


Itenerator begin() const Itenerator begin() const
@@ -151,35 +133,6 @@ public:
_init(); _init();
} }


// temporary fix for some const issue in midi-base.hpp
void clear_const()
{
if (fCount != 0)
{
k_list_head* entry;
k_list_head* entry2;

list_for_each_safe(entry, entry2, &fQueue)
{
if (const Data* data = list_entry_const(entry, Data, siblings))
{
data->~Data();

union CData {
const Data* cdata;
Data* data;
};

CData d;
d.cdata = data;
_deallocate(d.data);
}
}
}

_init();
}

size_t count() const noexcept size_t count() const noexcept
{ {
return fCount; return fCount;
@@ -356,7 +309,7 @@ public:
} }
} }


void spliceAppend(AbstractList& list, const bool init = true)
void spliceAppend(AbstractLinkedList& list, const bool init = true)
{ {
if (init) if (init)
{ {
@@ -371,7 +324,7 @@ public:
} }
} }


void spliceInsert(AbstractList& list, const bool init = true)
void spliceInsert(AbstractLinkedList& list, const bool init = true)
{ {
if (init) if (init)
{ {
@@ -429,27 +382,25 @@ private:
return fRetValue; return fRetValue;
} }


LIST_DECLARATIONS(AbstractList)
LINKED_LIST_DECLARATIONS(AbstractLinkedList)
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// List
// LinkedList


template<typename T> template<typename T>
class List : public AbstractList<T>
class LinkedList : public AbstractLinkedList<T>
{ {
public: public:
List()
{
}
LinkedList() {}


private: private:
typename AbstractList<T>::Data* _allocate() override
typename AbstractLinkedList<T>::Data* _allocate() override
{ {
return (typename AbstractList<T>::Data*)std::malloc(this->fDataSize);
return (typename AbstractLinkedList<T>::Data*)std::malloc(this->fDataSize);
} }


void _deallocate(typename AbstractList<T>::Data*& dataPtr) override
void _deallocate(typename AbstractLinkedList<T>::Data*& dataPtr) override
{ {
CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr,); CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr,);


@@ -457,9 +408,9 @@ private:
dataPtr = nullptr; dataPtr = nullptr;
} }


LIST_DECLARATIONS(List)
LINKED_LIST_DECLARATIONS(LinkedList)
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------


#endif // LIST_HPP_INCLUDED
#endif // LINKED_LIST_HPP_INCLUDED

source/utils/RtList.hpp → source/utils/RtLinkedList.hpp View File

@@ -15,20 +15,20 @@
* For a full copy of the GNU General Public License see the doc/GPL.txt file. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
*/ */


#ifndef RT_LIST_HPP_INCLUDED
#define RT_LIST_HPP_INCLUDED
#ifndef RT_LINKED_LIST_HPP_INCLUDED
#define RT_LINKED_LIST_HPP_INCLUDED


#include "List.hpp"
#include "LinkedList.hpp"


extern "C" { extern "C" {
#include "rtmempool/rtmempool.h" #include "rtmempool/rtmempool.h"
} }


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Realtime safe list
// Realtime safe linkedlist


template<typename T> template<typename T>
class RtList : public AbstractList<T>
class RtLinkedList : public AbstractLinkedList<T>
{ {
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@@ -39,7 +39,7 @@ public:
public: public:
Pool(const size_t minPreallocated, const size_t maxPreallocated) Pool(const size_t minPreallocated, const size_t maxPreallocated)
: fHandle(nullptr), : fHandle(nullptr),
fDataSize(sizeof(typename AbstractList<T>::Data))
fDataSize(sizeof(typename AbstractLinkedList<T>::Data))
{ {
resize(minPreallocated, maxPreallocated); resize(minPreallocated, maxPreallocated);
} }
@@ -96,18 +96,16 @@ public:
}; };


// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Now the actual rt-list code
// Now the actual rt-linkedlist code


RtList(Pool& memPool)
: fMemPool(memPool)
{
}
RtLinkedList(Pool& memPool)
: fMemPool(memPool) {}


void append_sleepy(const T& value) void append_sleepy(const T& value)
{ {
if (typename AbstractList<T>::Data* const data = _allocate_sleepy())
if (typename AbstractLinkedList<T>::Data* const data = _allocate_sleepy())
{ {
new(data)typename AbstractList<T>::Data();
new(data)typename AbstractLinkedList<T>::Data();
data->value = value; data->value = value;
list_add_tail(&data->siblings, &this->fQueue); list_add_tail(&data->siblings, &this->fQueue);
++(this->fCount); ++(this->fCount);
@@ -116,9 +114,9 @@ public:


void insert_sleepy(const T& value) void insert_sleepy(const T& value)
{ {
if (typename AbstractList<T>::Data* const data = _allocate_sleepy())
if (typename AbstractLinkedList<T>::Data* const data = _allocate_sleepy())
{ {
new(data)typename AbstractList<T>::Data();
new(data)typename AbstractLinkedList<T>::Data();
data->value = value; data->value = value;
list_add(&data->siblings, &this->fQueue); list_add(&data->siblings, &this->fQueue);
++(this->fCount); ++(this->fCount);
@@ -132,34 +130,34 @@ public:
fMemPool.resize(minPreallocated, maxPreallocated); fMemPool.resize(minPreallocated, maxPreallocated);
} }


void spliceAppend(RtList& list, const bool init = true)
void spliceAppend(RtLinkedList& list, const bool init = true)
{ {
CARLA_ASSERT(fMemPool == list.fMemPool); CARLA_ASSERT(fMemPool == list.fMemPool);


AbstractList<T>::spliceAppend(list, init);
AbstractLinkedList<T>::spliceAppend(list, init);
} }


void spliceInsert(RtList& list, const bool init = true)
void spliceInsert(RtLinkedList& list, const bool init = true)
{ {
CARLA_ASSERT(fMemPool == list.fMemPool); CARLA_ASSERT(fMemPool == list.fMemPool);


AbstractList<T>::spliceInsert(list, init);
AbstractLinkedList<T>::spliceInsert(list, init);
} }


private: private:
Pool& fMemPool; Pool& fMemPool;


typename AbstractList<T>::Data* _allocate() override
typename AbstractLinkedList<T>::Data* _allocate() override
{ {
return (typename AbstractList<T>::Data*)fMemPool.allocate_atomic();
return (typename AbstractLinkedList<T>::Data*)fMemPool.allocate_atomic();
} }


typename AbstractList<T>::Data* _allocate_sleepy()
typename AbstractLinkedList<T>::Data* _allocate_sleepy()
{ {
return (typename AbstractList<T>::Data*)fMemPool.allocate_sleepy();
return (typename AbstractLinkedList<T>::Data*)fMemPool.allocate_sleepy();
} }


void _deallocate(typename AbstractList<T>::Data*& dataPtr) override
void _deallocate(typename AbstractLinkedList<T>::Data*& dataPtr) override
{ {
CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr,); CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr,);


@@ -167,9 +165,9 @@ private:
dataPtr = nullptr; dataPtr = nullptr;
} }


LIST_DECLARATIONS(RtList)
LINKED_LIST_DECLARATIONS(RtLinkedList)
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------


#endif // RT_LIST_HPP_INCLUDED
#endif // RT_LINKED_LIST_HPP_INCLUDED

Loading…
Cancel
Save