| @@ -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); | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla library counter | |||
| * 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 | |||
| * 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<Lib>::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); | |||
| @@ -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<typename T> | |||
| 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<T>::Data* _allocate() override | |||
| typename AbstractLinkedList<T>::Data* _allocate() noexcept override | |||
| { | |||
| return (typename AbstractLinkedList<T>::Data*)std::malloc(this->fDataSize); | |||
| } | |||
| void _deallocate(typename AbstractLinkedList<T>::Data*& dataPtr) override | |||
| void _deallocate(typename AbstractLinkedList<T>::Data*& dataPtr) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr,); | |||
| @@ -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<T>::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<T>::Data* const data = _allocate_sleepy()) | |||
| { | |||
| new(data)typename AbstractLinkedList<T>::Data(); | |||
| try { | |||
| new(data)typename AbstractLinkedList<T>::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<T>::Data* const data = _allocate_sleepy()) | |||
| { | |||
| new(data)typename AbstractLinkedList<T>::Data(); | |||
| try { | |||
| new(data)typename AbstractLinkedList<T>::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<T>::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<T>::Data* _allocate() override | |||
| typename AbstractLinkedList<T>::Data* _allocate() noexcept override | |||
| { | |||
| return (typename AbstractLinkedList<T>::Data*)fMemPool.allocate_atomic(); | |||
| } | |||
| typename AbstractLinkedList<T>::Data* _allocate_sleepy() | |||
| typename AbstractLinkedList<T>::Data* _allocate_sleepy() noexcept | |||
| { | |||
| return (typename AbstractLinkedList<T>::Data*)fMemPool.allocate_sleepy(); | |||
| } | |||
| void _deallocate(typename AbstractLinkedList<T>::Data*& dataPtr) override | |||
| void _deallocate(typename AbstractLinkedList<T>::Data*& dataPtr) noexcept override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr,); | |||