diff --git a/source/modules/rtmempool/list.h b/source/modules/rtmempool/list.h index b842b2548..9df654270 100644 --- a/source/modules/rtmempool/list.h +++ b/source/modules/rtmempool/list.h @@ -86,7 +86,7 @@ struct list_head { #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) -static inline void INIT_LIST_HEAD(struct list_head *list) +static inline void INIT_LIST_HEAD(struct list_head *list) __THROW { list->next = list; list->prev = list; @@ -98,7 +98,7 @@ static inline void INIT_LIST_HEAD(struct list_head *list) * This is only for internal list manipulation where we know * the prev/next entries already! */ -static inline void __list_add(struct list_head *new_, struct list_head *prev, struct list_head *next) +static inline void __list_add(struct list_head *new_, struct list_head *prev, struct list_head *next) __THROW { next->prev = new_; new_->next = next; @@ -114,7 +114,7 @@ static inline void __list_add(struct list_head *new_, struct list_head *prev, st * Insert a new entry after the specified head. * This is good for implementing stacks. */ -static inline void list_add(struct list_head *new_, struct list_head *head) +static inline void list_add(struct list_head *new_, struct list_head *head) __THROW { __list_add(new_, head, head->next); } @@ -127,7 +127,7 @@ static inline void list_add(struct list_head *new_, struct list_head *head) * Insert a new entry before the specified head. * This is useful for implementing queues. */ -static inline void list_add_tail(struct list_head *new_, struct list_head *head) +static inline void list_add_tail(struct list_head *new_, struct list_head *head) __THROW { __list_add(new_, head->prev, head); } @@ -139,7 +139,7 @@ static inline void list_add_tail(struct list_head *new_, struct list_head *head) * This is only for internal list manipulation where we know * the prev/next entries already! */ -static inline void __list_del(struct list_head *prev, struct list_head *next) +static inline void __list_del(struct list_head *prev, struct list_head *next) __THROW { next->prev = prev; prev->next = next; @@ -151,7 +151,7 @@ static inline void __list_del(struct list_head *prev, struct list_head *next) * Note: list_empty on entry does not return true after this, the entry is * in an undefined state. */ -static inline void list_del(struct list_head *entry) +static inline void list_del(struct list_head *entry) __THROW { __list_del(entry->prev, entry->next); entry->next = (struct list_head*)LIST_POISON1; @@ -162,7 +162,7 @@ static inline void list_del(struct list_head *entry) * list_del_init - deletes entry from list and reinitialize it. * @entry: the element to delete from the list. */ -static inline void list_del_init(struct list_head *entry) +static inline void list_del_init(struct list_head *entry) __THROW { __list_del(entry->prev, entry->next); INIT_LIST_HEAD(entry); @@ -173,7 +173,7 @@ static inline void list_del_init(struct list_head *entry) * @list: the entry to move * @head: the head that will precede our entry */ -static inline void list_move(struct list_head *list, struct list_head *head) +static inline void list_move(struct list_head *list, struct list_head *head) __THROW { __list_del(list->prev, list->next); list_add(list, head); @@ -184,7 +184,7 @@ static inline void list_move(struct list_head *list, struct list_head *head) * @list: the entry to move * @head: the head that will follow our entry */ -static inline void list_move_tail(struct list_head *list, struct list_head *head) +static inline void list_move_tail(struct list_head *list, struct list_head *head) __THROW { __list_del(list->prev, list->next); list_add_tail(list, head); @@ -194,7 +194,7 @@ static inline void list_move_tail(struct list_head *list, struct list_head *head * list_empty - tests whether a list is empty * @head: the list to test. */ -static inline int list_empty(const struct list_head *head) +static inline int list_empty(const struct list_head *head) __THROW { return head->next == head; } @@ -211,13 +211,13 @@ static inline int list_empty(const struct list_head *head) * * @head: the list to test. */ -static inline int list_empty_careful(const struct list_head *head) +static inline int list_empty_careful(const struct list_head *head) __THROW { struct list_head *next = head->next; return (next == head) && (next == head->prev); } -static inline void __list_splice(struct list_head *list, struct list_head *head) +static inline void __list_splice(struct list_head *list, struct list_head *head) __THROW { struct list_head *first = list->next; struct list_head *last = list->prev; @@ -230,7 +230,7 @@ static inline void __list_splice(struct list_head *list, struct list_head *head) at->prev = last; } -static inline void __list_splice_tail(struct list_head *list, struct list_head *head) +static inline void __list_splice_tail(struct list_head *list, struct list_head *head) __THROW { struct list_head *first = list->next; struct list_head *last = list->prev; @@ -248,7 +248,7 @@ static inline void __list_splice_tail(struct list_head *list, struct list_head * * @list: the new list to add. * @head: the place to add it in the first list. */ -static inline void list_splice(struct list_head *list, struct list_head *head) +static inline void list_splice(struct list_head *list, struct list_head *head) __THROW { if (!list_empty(list)) __list_splice(list, head); @@ -261,7 +261,7 @@ static inline void list_splice(struct list_head *list, struct list_head *head) * * @list goes to the end (at head->prev) */ -static inline void list_splice_tail(struct list_head *list, struct list_head *head) +static inline void list_splice_tail(struct list_head *list, struct list_head *head) __THROW { if (!list_empty(list)) __list_splice_tail(list, head); @@ -274,7 +274,7 @@ static inline void list_splice_tail(struct list_head *list, struct list_head *he * * The list at @list is reinitialised */ -static inline void list_splice_init(struct list_head *list, struct list_head *head) +static inline void list_splice_init(struct list_head *list, struct list_head *head) __THROW { if (!list_empty(list)) { __list_splice(list, head); @@ -290,7 +290,7 @@ static inline void list_splice_init(struct list_head *list, struct list_head *he * The list at @list is reinitialised * @list goes to the end (at head->prev) */ -static inline void list_splice_tail_init(struct list_head *list, struct list_head *head) +static inline void list_splice_tail_init(struct list_head *list, struct list_head *head) __THROW { if (!list_empty(list)) { __list_splice_tail(list, head); diff --git a/source/utils/CarlaLibCounter.hpp b/source/utils/CarlaLibCounter.hpp index 981cb541b..903f7da26 100644 --- a/source/utils/CarlaLibCounter.hpp +++ b/source/utils/CarlaLibCounter.hpp @@ -1,6 +1,6 @@ /* * Carla library counter - * Copyright (C) 2013 Filipe Coelho + * Copyright (C) 2013-2014 Filipe Coelho * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -27,12 +27,22 @@ class LibCounter { public: - LibCounter() {} + LibCounter() noexcept {} - void* open(const char* const filename) + void* open(const char* const filename) noexcept { CARLA_SAFE_ASSERT_RETURN(filename != nullptr && filename[0] != '\0', nullptr); + // try duplicating filename first, it can throw + const char* dfilename = nullptr; + + try { + dfilename = carla_strdup(filename); + } + catch(...) { + return nullptr; + } + const CarlaMutexLocker sl(fMutex); for (LinkedList::Itenerator it = fLibs.begin(); it.valid(); it.next()) @@ -55,7 +65,7 @@ public: Lib lib; lib.lib = libPtr; - lib.filename = carla_strdup(filename); + lib.filename = dfilename; lib.count = 1; fLibs.append(lib); @@ -63,7 +73,7 @@ public: return libPtr; } - bool close(void* const libPtr) + bool close(void* const libPtr) noexcept { CARLA_SAFE_ASSERT_RETURN(libPtr != nullptr, false); diff --git a/source/utils/LinkedList.hpp b/source/utils/LinkedList.hpp index 4afcbfb75..03b214213 100644 --- a/source/utils/LinkedList.hpp +++ b/source/utils/LinkedList.hpp @@ -46,6 +46,8 @@ typedef struct list_head k_list_head; // Abstract Linked List class // _allocate() and _deallocate are virtual calls provided by subclasses +// NOTE: classes are allowed to throw on creation, but NOT on deletion! + template class AbstractLinkedList { @@ -55,7 +57,7 @@ protected: k_list_head siblings; }; - AbstractLinkedList() + AbstractLinkedList() noexcept : fDataSize(sizeof(Data)), fCount(0) { @@ -63,7 +65,7 @@ protected: } public: - virtual ~AbstractLinkedList() + virtual ~AbstractLinkedList() noexcept { CARLA_SAFE_ASSERT(fCount == 0); } @@ -113,7 +115,7 @@ public: return Itenerator(&fQueue); } - void clear() + void clear() noexcept { if (fCount != 0) { @@ -143,11 +145,18 @@ public: return (fCount == 0); } - bool append(const T& value) + bool append(const T& value) noexcept { if (Data* const data = _allocate()) { - new(data)Data(); + try { + new(data)Data(); + } + catch(...) { + _deallocate(data); + return false; + } + data->value = value; list_add_tail(&data->siblings, &fQueue); ++fCount; @@ -157,11 +166,18 @@ public: return false; } - bool appendAt(const T& value, const Itenerator& it) + bool appendAt(const T& value, const Itenerator& it) noexcept { if (Data* const data = _allocate()) { - new(data)Data(); + try { + new(data)Data(); + } + catch(...) { + _deallocate(data); + return false; + } + data->value = value; list_add_tail(&data->siblings, it.fEntry->next); ++fCount; @@ -171,11 +187,18 @@ public: return false; } - bool insert(const T& value) + bool insert(const T& value) noexcept { if (Data* const data = _allocate()) { - new(data)Data(); + try { + new(data)Data(); + } + catch(...) { + _deallocate(data); + return false; + } + data->value = value; list_add(&data->siblings, &fQueue); ++fCount; @@ -185,11 +208,18 @@ public: return false; } - bool insertAt(const T& value, const Itenerator& it) + bool insertAt(const T& value, const Itenerator& it) noexcept { if (Data* const data = _allocate()) { - new(data)Data(); + try { + new(data)Data(); + } + catch(...) { + _deallocate(data); + return false; + } + data->value = value; list_add(&data->siblings, it.fEntry->prev); ++fCount; @@ -225,7 +255,7 @@ public: return fRetValue; } - T& getAt(const size_t index, const bool removeObj) + T& getAt(const size_t index, const bool removeObj) noexcept { if (fCount == 0 || index >= fCount) return fRetValue; @@ -263,17 +293,17 @@ public: return fRetValue; } - T& getFirst(const bool removeObj = false) + T& getFirst(const bool removeObj = false) noexcept { return _getFirstOrLast(true, removeObj); } - T& getLast(const bool removeObj = false) + T& getLast(const bool removeObj = false) noexcept { return _getFirstOrLast(false, removeObj); } - void remove(Itenerator& it) + void remove(Itenerator& it) noexcept { CARLA_SAFE_ASSERT_RETURN(it.fEntry != nullptr,); @@ -286,7 +316,7 @@ public: _deallocate(it.fData); } - bool removeOne(const T& value) + bool removeOne(const T& value) noexcept { Data* data = nullptr; k_list_head* entry; @@ -312,7 +342,7 @@ public: return (data != nullptr); } - void removeAll(const T& value) + void removeAll(const T& value) noexcept { Data* data; k_list_head* entry; @@ -370,8 +400,8 @@ protected: size_t fCount; k_list_head fQueue; - virtual Data* _allocate() = 0; - virtual void _deallocate(Data*& dataPtr) = 0; + virtual Data* _allocate() noexcept = 0; + virtual void _deallocate(Data*& dataPtr) noexcept = 0; private: mutable T fRetValue; @@ -382,7 +412,7 @@ private: INIT_LIST_HEAD(&fQueue); } - T& _getFirstOrLast(const bool first, const bool removeObj) + T& _getFirstOrLast(const bool first, const bool removeObj) noexcept { if (fCount == 0) return fRetValue; @@ -421,12 +451,12 @@ public: LinkedList() {} private: - typename AbstractLinkedList::Data* _allocate() override + typename AbstractLinkedList::Data* _allocate() noexcept override { return (typename AbstractLinkedList::Data*)std::malloc(this->fDataSize); } - void _deallocate(typename AbstractLinkedList::Data*& dataPtr) override + void _deallocate(typename AbstractLinkedList::Data*& dataPtr) noexcept override { CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr,); diff --git a/source/utils/RtLinkedList.hpp b/source/utils/RtLinkedList.hpp index 3dda1783b..cf8e541e8 100644 --- a/source/utils/RtLinkedList.hpp +++ b/source/utils/RtLinkedList.hpp @@ -37,14 +37,14 @@ public: class Pool { public: - Pool(const size_t minPreallocated, const size_t maxPreallocated) + Pool(const size_t minPreallocated, const size_t maxPreallocated) noexcept : fHandle(nullptr), fDataSize(sizeof(typename AbstractLinkedList::Data)) { resize(minPreallocated, maxPreallocated); } - ~Pool() + ~Pool() noexcept { if (fHandle != nullptr) { @@ -53,22 +53,22 @@ public: } } - void* allocate_atomic() const + void* allocate_atomic() const noexcept { return rtsafe_memory_pool_allocate_atomic(fHandle); } - void* allocate_sleepy() const + void* allocate_sleepy() const noexcept { return rtsafe_memory_pool_allocate_sleepy(fHandle); } - void deallocate(void* const dataPtr) const + void deallocate(void* const dataPtr) const noexcept { rtsafe_memory_pool_deallocate(fHandle, dataPtr); } - void resize(const size_t minPreallocated, const size_t maxPreallocated) + void resize(const size_t minPreallocated, const size_t maxPreallocated) noexcept { if (fHandle != nullptr) { @@ -101,43 +101,65 @@ public: RtLinkedList(Pool& memPool) : fMemPool(memPool) {} - void append_sleepy(const T& value) + bool append_sleepy(const T& value) noexcept { if (typename AbstractLinkedList::Data* const data = _allocate_sleepy()) { - new(data)typename AbstractLinkedList::Data(); + try { + new(data)typename AbstractLinkedList::Data(); + } + catch(...) { + _deallocate(data); + return false; + } + data->value = value; list_add_tail(&data->siblings, &this->fQueue); ++(this->fCount); + + return true; } + + return false; } - void insert_sleepy(const T& value) + bool insert_sleepy(const T& value) noexcept { if (typename AbstractLinkedList::Data* const data = _allocate_sleepy()) { - new(data)typename AbstractLinkedList::Data(); + try { + new(data)typename AbstractLinkedList::Data(); + } + catch(...) { + _deallocate(data); + return false; + } + data->value = value; list_add(&data->siblings, &this->fQueue); ++(this->fCount); + + return true; } + + return false; } - void resize(const size_t minPreallocated, const size_t maxPreallocated) + void resize(const size_t minPreallocated, const size_t maxPreallocated) noexcept { this->clear(); fMemPool.resize(minPreallocated, maxPreallocated); } - void spliceAppend(RtLinkedList& list, const bool init = true) + void spliceAppend(RtLinkedList& list, const bool init = true) noexcept { CARLA_SAFE_ASSERT_RETURN(fMemPool == list.fMemPool,); AbstractLinkedList::spliceAppend(list, init); } - void spliceInsert(RtLinkedList& list, const bool init = true) + void spliceInsert(RtLinkedList& list, const bool init = true) noexcept { CARLA_SAFE_ASSERT_RETURN(fMemPool == list.fMemPool,); @@ -147,17 +169,17 @@ public: private: Pool& fMemPool; - typename AbstractLinkedList::Data* _allocate() override + typename AbstractLinkedList::Data* _allocate() noexcept override { return (typename AbstractLinkedList::Data*)fMemPool.allocate_atomic(); } - typename AbstractLinkedList::Data* _allocate_sleepy() + typename AbstractLinkedList::Data* _allocate_sleepy() noexcept { return (typename AbstractLinkedList::Data*)fMemPool.allocate_sleepy(); } - void _deallocate(typename AbstractLinkedList::Data*& dataPtr) override + void _deallocate(typename AbstractLinkedList::Data*& dataPtr) noexcept override { CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr,);