diff options
author | David Robillard <d@drobilla.net> | 2007-10-08 16:30:57 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2007-10-08 16:30:57 +0000 |
commit | 9f975e1e8a7dd0d8d90739829dc07d1188ad51e5 (patch) | |
tree | 2dda260e26488f364aec848262279e6b08c3d99a | |
parent | d9269cb513631751e951c07b32b41a496de0a493 (diff) | |
download | raul-9f975e1e8a7dd0d8d90739829dc07d1188ad51e5.tar.gz raul-9f975e1e8a7dd0d8d90739829dc07d1188ad51e5.tar.bz2 raul-9f975e1e8a7dd0d8d90739829dc07d1188ad51e5.zip |
SharedPtr-ify engine side store.
Fix reattaching to engine.
Fix connection paths.
Remove last dependencies on client (model) library from Serialiser.
Fix Raul::PathTable::find_descendants_end.
git-svn-id: http://svn.drobilla.net/lad/raul@847 a436a847-0d15-0410-975c-d299462d15a1
-rw-r--r-- | raul/List.hpp | 416 | ||||
-rw-r--r-- | raul/ListImpl.hpp | 431 | ||||
-rw-r--r-- | raul/Makefile.am | 1 | ||||
-rw-r--r-- | raul/Path.hpp | 3 | ||||
-rw-r--r-- | raul/TimeSlice.hpp | 11 | ||||
-rw-r--r-- | tests/path_test.cpp | 9 |
6 files changed, 463 insertions, 408 deletions
diff --git a/raul/List.hpp b/raul/List.hpp index a090251..f695421 100644 --- a/raul/List.hpp +++ b/raul/List.hpp @@ -49,28 +49,36 @@ public: public: Node(T elem) : _elem(elem) {} virtual ~Node() {} + + template <typename Y> + Node(const typename List<Y>::Node& copy) + : _elem(copy._elem), _prev(copy._prev), _next(copy._next) + {} - Node* next() const { return _next.get(); } - void next(Node* ln) { _next = ln; } - Node* prev() const { return _prev.get(); } + Node* prev() const { return _prev.get(); } void prev(Node* ln) { _prev = ln; } - T& elem() { return _elem;} - const T& elem() const { return _elem; } + Node* next() const { return _next.get(); } + void next(Node* ln) { _next = ln; } + + T& elem() { return _elem;} + const T& elem() const { return _elem; } private: - T _elem; - AtomicPtr<Node> _next; + T _elem; AtomicPtr<Node> _prev; + AtomicPtr<Node> _next; }; // List - List() : _size(0), _end_iter(this), _const_end_iter(this) + List() + : _size(0), _end_iter(this), _const_end_iter(this) { _end_iter._listnode = NULL; _const_end_iter._listnode = NULL; } + ~List(); void push_back(Node* elem); // realtime safe @@ -97,6 +105,7 @@ public: : _list(i._list), _listnode(i._listnode) {} inline const T& operator*(); + inline const T* operator->(); inline const_iterator& operator++(); inline bool operator!=(const const_iterator& iter) const; inline bool operator!=(const iterator& iter) const; @@ -118,6 +127,7 @@ public: iterator(List<T>* const list); inline T& operator*(); + inline T* operator->(); inline iterator& operator++(); inline bool operator!=(const iterator& iter) const; inline bool operator!=(const const_iterator& iter) const; @@ -152,394 +162,8 @@ private: }; - - -template <typename T> -List<T>::~List<T>() -{ - clear(); -} - - -/** Clear the list, deleting all Nodes contained (but NOT their contents!) - * - * Not realtime safe. - */ -template <typename T> -void -List<T>::clear() -{ - Node* node = _head.get(); - Node* next = NULL; - - while (node) { - next = node->next(); - delete node; - node = next; - } - - _head = 0; - _tail = 0; - _size = 0; -} - - -/** Add an element to the list. - * - * Thread safe (may be called while another thread is reading the list). - * Realtime safe. - */ -template <typename T> -void -List<T>::push_back(Node* const ln) -{ - assert(ln); - - ln->next(NULL); - - if ( ! _head.get()) { // empty - ln->prev(NULL); - _tail = ln; - _head = ln; - } else { - ln->prev(_tail.get()); - _tail.get()->next(ln); - _tail = ln; - } - ++_size; -} - - -/** Add an element to the list. - * - * Thread safe (may be called while another thread is reading the list). - * NOT realtime safe (a Node is allocated). - */ -template <typename T> -void -List<T>::push_back(T& elem) -{ - Node* const ln = new Node(elem); - - assert(ln); - - ln->next(NULL); - - if ( ! _head.get()) { // empty - ln->prev(NULL); - _tail = ln; - _head = ln; - } else { - ln->prev(_tail.get()); - _tail.get()->next(ln); - _tail = ln; - } - ++_size; -} - - -/** Append a list to this list. - * - * This operation is fast ( O(1) ). - * The appended list is not safe to use concurrently with this call. - * - * The appended list will be empty after this call. - * - * Thread safe (may be called while another thread is reading the list). - * Realtime safe. - */ -template <typename T> -void -List<T>::append(List<T>& list) -{ - Node* const my_head = _head.get(); - Node* const my_tail = _tail.get(); - Node* const other_head = list._head.get(); - Node* const other_tail = list._tail.get(); - - // Appending to an empty list - if (my_head == NULL && my_tail == NULL) { - _head = other_head; - _tail = other_tail; - _size = list._size; - } else if (other_head != NULL && other_tail != NULL) { - - other_head->prev(my_tail); - - // FIXME: atomicity an issue? _size < true size is probably fine... - // no gurantee an iteration runs exactly size times though. verify/document this. - // assuming comment above that says tail is writer only, this is fine - my_tail->next(other_head); - _tail = other_tail; - _size += list.size(); - } - - list._head = NULL; - list._tail = NULL; - list._size = 0; -} - - -/** Remove all elements equal to @val from the list. - * - * This function is realtime safe - it is the caller's responsibility to - * delete the returned ListNode, or there will be a leak. - */ -#if 0 -template <typename T> -ListNode<T>* -List<T>::remove(const T val) -{ - // FIXME: atomicity? - ListNode<T>* n = _head; - while (n) { - if (n->elem() == elem) - break; - n = n->next(); - } - if (n) { - if (n == _head) _head = _head->next(); - if (n == _tail) _tail = _tail->prev(); - if (n->prev()) - n->prev()->next(n->next()); - if (n->next()) - n->next()->prev(n->prev()); - --_size; - - if (_size == 0) - _head = _tail = NULL; // FIXME: Shouldn't be necessary - - return n; - } - return NULL; -} -#endif - - -/** Find an element in the list. - * - * This will only return the first element found. If there are duplicated, - * another call to find() will return the next, etc. - */ -template <typename T> -typename List<T>::iterator -List<T>::find(const T& val) -{ - for (iterator i = begin(); i != end(); ++i) - if (*i == val) - return i; - - return end(); -} - - -/** Remove an element from the list using an iterator. - * - * This function is realtime safe - it is the caller's responsibility to - * delete the returned Node, or there will be a leak. - * Thread safe (safe to call while another thread reads the list). - * @a iter is invalid immediately following this call. - */ -template <typename T> -typename List<T>::Node* -List<T>::erase(const iterator iter) -{ - Node* const n = iter._listnode; - - if (n) { - - Node* const prev = n->prev(); - Node* const next = n->next(); - - // Removing the head (or the only element) - if (n == _head.get()) - _head = next; - - // Removing the tail (or the only element) - if (n == _tail.get()) - _tail = _tail.get()->prev(); - - if (prev) - n->prev()->next(next); - - if (next) - n->next()->prev(prev); - - --_size; - } - - return n; -} - - -//// Iterator stuff //// - -template <typename T> -List<T>::iterator::iterator(List<T>* list) -: _list(list), - _listnode(NULL) -{ -} - - -template <typename T> -T& -List<T>::iterator::operator*() -{ - assert(_listnode); - return _listnode->elem(); -} - - -template <typename T> -inline typename List<T>::iterator& -List<T>::iterator::operator++() -{ - assert(_listnode); - _listnode = _listnode->next(); - - return *this; -} - - -template <typename T> -inline bool -List<T>::iterator::operator!=(const iterator& iter) const -{ - return (_listnode != iter._listnode); -} - - -template <typename T> -inline bool -List<T>::iterator::operator!=(const const_iterator& iter) const -{ - return (_listnode != iter._listnode); -} - - -template <typename T> -inline bool -List<T>::iterator::operator==(const iterator& iter) const -{ - return (_listnode == iter._listnode); -} - - -template <typename T> -inline bool -List<T>::iterator::operator==(const const_iterator& iter) const -{ - return (_listnode == iter._listnode); -} - - -template <typename T> -inline typename List<T>::iterator -List<T>::begin() -{ - typename List<T>::iterator iter(this); - - iter._listnode = _head.get(); - - return iter; -} - - -template <typename T> -inline const typename List<T>::iterator -List<T>::end() const -{ - return _end_iter; -} - - - -/// const_iterator stuff /// - - -template <typename T> -List<T>::const_iterator::const_iterator(const List<T>* const list) -: _list(list), - _listnode(NULL) -{ -} - - -template <typename T> -const T& -List<T>::const_iterator::operator*() -{ - assert(_listnode); - return _listnode->elem(); -} - - -template <typename T> -inline typename List<T>::const_iterator& -List<T>::const_iterator::operator++() -{ - assert(_listnode); - _listnode = _listnode->next(); - - return *this; -} - - -template <typename T> -inline bool -List<T>::const_iterator::operator!=(const const_iterator& iter) const -{ - return (_listnode != iter._listnode); -} - - -template <typename T> -inline bool -List<T>::const_iterator::operator!=(const iterator& iter) const -{ - return (_listnode != iter._listnode); -} - - -template <typename T> -inline bool -List<T>::const_iterator::operator==(const const_iterator& iter) const -{ - return (_listnode == iter._listnode); -} - - -template <typename T> -inline bool -List<T>::const_iterator::operator==(const iterator& iter) const -{ - return (_listnode == iter._listnode); -} - -template <typename T> -inline typename List<T>::const_iterator -List<T>::begin() const -{ - typename List<T>::const_iterator iter(this); - iter._listnode = _head.get(); - return iter; -} - -#if 0 -template <typename T> -inline typename List<T>::const_iterator -List<T>::end() const -{ - /*typename List<T>::const_iterator iter(this); - iter._listnode = NULL; - iter._next = NULL; - return iter;*/ - return _const_end_iter; -} -#endif - - } // namespace Raul +#include "ListImpl.hpp" + #endif // RAUL_LIST_HPP diff --git a/raul/ListImpl.hpp b/raul/ListImpl.hpp new file mode 100644 index 0000000..28b8dae --- /dev/null +++ b/raul/ListImpl.hpp @@ -0,0 +1,431 @@ +/* This file is part of Raul. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Raul 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. + * + * Raul 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 details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef RAUL_LIST_IMPL_HPP +#define RAUL_LIST_IMPL_HPP + +namespace Raul { + + +template <typename T> +List<T>::~List<T>() +{ + clear(); +} + + +/** Clear the list, deleting all Nodes contained (but NOT their contents!) + * + * Not realtime safe. + */ +template <typename T> +void +List<T>::clear() +{ + Node* node = _head.get(); + Node* next = NULL; + + while (node) { + next = node->next(); + delete node; + node = next; + } + + _head = 0; + _tail = 0; + _size = 0; +} + + +/** Add an element to the list. + * + * Thread safe (may be called while another thread is reading the list). + * Realtime safe. + */ +template <typename T> +void +List<T>::push_back(Node* const ln) +{ + assert(ln); + + ln->next(NULL); + + if ( ! _head.get()) { // empty + ln->prev(NULL); + _tail = ln; + _head = ln; + } else { + ln->prev(_tail.get()); + _tail.get()->next(ln); + _tail = ln; + } + ++_size; +} + + +/** Add an element to the list. + * + * Thread safe (may be called while another thread is reading the list). + * NOT realtime safe (a Node is allocated). + */ +template <typename T> +void +List<T>::push_back(T& elem) +{ + Node* const ln = new Node(elem); + + assert(ln); + + ln->next(NULL); + + if ( ! _head.get()) { // empty + ln->prev(NULL); + _tail = ln; + _head = ln; + } else { + ln->prev(_tail.get()); + _tail.get()->next(ln); + _tail = ln; + } + ++_size; +} + + +/** Append a list to this list. + * + * This operation is fast ( O(1) ). + * The appended list is not safe to use concurrently with this call. + * + * The appended list will be empty after this call. + * + * Thread safe (may be called while another thread is reading the list). + * Realtime safe. + */ +template <typename T> +void +List<T>::append(List<T>& list) +{ + Node* const my_head = _head.get(); + Node* const my_tail = _tail.get(); + Node* const other_head = list._head.get(); + Node* const other_tail = list._tail.get(); + + // Appending to an empty list + if (my_head == NULL && my_tail == NULL) { + _head = other_head; + _tail = other_tail; + _size = list._size; + } else if (other_head != NULL && other_tail != NULL) { + + other_head->prev(my_tail); + + // FIXME: atomicity an issue? _size < true size is probably fine... + // no gurantee an iteration runs exactly size times though. verify/document this. + // assuming comment above that says tail is writer only, this is fine + my_tail->next(other_head); + _tail = other_tail; + _size += list.size(); + } + + list._head = NULL; + list._tail = NULL; + list._size = 0; +} + + +/** Remove all elements equal to @val from the list. + * + * This function is realtime safe - it is the caller's responsibility to + * delete the returned ListNode, or there will be a leak. + */ +#if 0 +template <typename T> +ListNode<T>* +List<T>::remove(const T val) +{ + // FIXME: atomicity? + ListNode<T>* n = _head; + while (n) { + if (n->elem() == elem) + break; + n = n->next(); + } + if (n) { + if (n == _head) _head = _head->next(); + if (n == _tail) _tail = _tail->prev(); + if (n->prev()) + n->prev()->next(n->next()); + if (n->next()) + n->next()->prev(n->prev()); + --_size; + + if (_size == 0) + _head = _tail = NULL; // FIXME: Shouldn't be necessary + + return n; + } + return NULL; +} +#endif + + +/** Find an element in the list. + * + * This will only return the first element found. If there are duplicated, + * another call to find() will return the next, etc. + */ +template <typename T> +typename List<T>::iterator +List<T>::find(const T& val) +{ + for (iterator i = begin(); i != end(); ++i) + if (*i == val) + return i; + + return end(); +} + + +/** Remove an element from the list using an iterator. + * + * This function is realtime safe - it is the caller's responsibility to + * delete the returned Node, or there will be a leak. + * Thread safe (safe to call while another thread reads the list). + * @a iter is invalid immediately following this call. + */ +template <typename T> +typename List<T>::Node* +List<T>::erase(const iterator iter) +{ + Node* const n = iter._listnode; + + if (n) { + + Node* const prev = n->prev(); + Node* const next = n->next(); + + // Removing the head (or the only element) + if (n == _head.get()) + _head = next; + + // Removing the tail (or the only element) + if (n == _tail.get()) + _tail = _tail.get()->prev(); + + if (prev) + n->prev()->next(next); + + if (next) + n->next()->prev(prev); + + --_size; + } + + return n; +} + + +//// Iterator stuff //// + +template <typename T> +List<T>::iterator::iterator(List<T>* list) +: _list(list), + _listnode(NULL) +{ +} + + +template <typename T> +T& +List<T>::iterator::operator*() +{ + assert(_listnode); + return _listnode->elem(); +} + + +template <typename T> +T* +List<T>::iterator::operator->() +{ + assert(_listnode); + return &_listnode->elem(); +} + + +template <typename T> +inline typename List<T>::iterator& +List<T>::iterator::operator++() +{ + assert(_listnode); + _listnode = _listnode->next(); + + return *this; +} + + +template <typename T> +inline bool +List<T>::iterator::operator!=(const iterator& iter) const +{ + return (_listnode != iter._listnode); +} + + +template <typename T> +inline bool +List<T>::iterator::operator!=(const const_iterator& iter) const +{ + return (_listnode != iter._listnode); +} + + +template <typename T> +inline bool +List<T>::iterator::operator==(const iterator& iter) const +{ + return (_listnode == iter._listnode); +} + + +template <typename T> +inline bool +List<T>::iterator::operator==(const const_iterator& iter) const +{ + return (_listnode == iter._listnode); +} + + +template <typename T> +inline typename List<T>::iterator +List<T>::begin() +{ + typename List<T>::iterator iter(this); + + iter._listnode = _head.get(); + + return iter; +} + + +template <typename T> +inline const typename List<T>::iterator +List<T>::end() const +{ + return _end_iter; +} + + + +/// const_iterator stuff /// + + +template <typename T> +List<T>::const_iterator::const_iterator(const List<T>* const list) +: _list(list), + _listnode(NULL) +{ +} + + +template <typename T> +const T& +List<T>::const_iterator::operator*() +{ + assert(_listnode); + return _listnode->elem(); +} + + +template <typename T> +const T* +List<T>::const_iterator::operator->() +{ + assert(_listnode); + return &_listnode->elem(); +} + + +template <typename T> +inline typename List<T>::const_iterator& +List<T>::const_iterator::operator++() +{ + assert(_listnode); + _listnode = _listnode->next(); + + return *this; +} + + +template <typename T> +inline bool +List<T>::const_iterator::operator!=(const const_iterator& iter) const +{ + return (_listnode != iter._listnode); +} + + +template <typename T> +inline bool +List<T>::const_iterator::operator!=(const iterator& iter) const +{ + return (_listnode != iter._listnode); +} + + +template <typename T> +inline bool +List<T>::const_iterator::operator==(const const_iterator& iter) const +{ + return (_listnode == iter._listnode); +} + + +template <typename T> +inline bool +List<T>::const_iterator::operator==(const iterator& iter) const +{ + return (_listnode == iter._listnode); +} + +template <typename T> +inline typename List<T>::const_iterator +List<T>::begin() const +{ + typename List<T>::const_iterator iter(this); + iter._listnode = _head.get(); + return iter; +} + +#if 0 +template <typename T> +inline typename List<T>::const_iterator +List<T>::end() const +{ + /*typename List<T>::const_iterator iter(this); + iter._listnode = NULL; + iter._next = NULL; + return iter;*/ + return _const_end_iter; +} +#endif + + +} // namespace Raul + + +#endif // RAUL_LIST_IMPL_HPP diff --git a/raul/Makefile.am b/raul/Makefile.am index cd44b73..f552f7c 100644 --- a/raul/Makefile.am +++ b/raul/Makefile.am @@ -9,6 +9,7 @@ raulinclude_HEADERS = \ DoubleBuffer.hpp \ JackDriver.hpp \ List.hpp \ + ListImpl.hpp \ MIDISink.hpp \ Maid.hpp \ Namespaces.hpp \ diff --git a/raul/Path.hpp b/raul/Path.hpp index d1a86f9..b6a1395 100644 --- a/raul/Path.hpp +++ b/raul/Path.hpp @@ -18,6 +18,7 @@ #ifndef RAUL_PATH_HPP #define RAUL_PATH_HPP +#include <iostream> #include <cctype> #include <string> #include <cassert> @@ -130,7 +131,7 @@ public: { return ( child == parent || (child.length() > parent.length() && (!strncmp(parent.c_str(), child.c_str(), parent.length()) - && child[parent.length()] == '/')) ); + && (parent == "/" || child[parent.length()] == '/'))) ); } }; diff --git a/raul/TimeSlice.hpp b/raul/TimeSlice.hpp index 0681fb5..a7f445b 100644 --- a/raul/TimeSlice.hpp +++ b/raul/TimeSlice.hpp @@ -118,18 +118,9 @@ public: /** Length of current sub-cycle in beats */ inline BeatCount length_beats() const { return _length_beats; } - - // Real-time conversion -/* - TickCount ticks_to_offset(TickTime time) { - assert(time >= _start_ticks); - TickCount ret = time - _start_ticks + _offset_ticks; - assert(ret < _offset_ticks + _length_ticks); - return ret; - } -*/ /** Set the offset between real-time and timeslice-time. */ inline void set_offset(TickCount offset) { _offset_ticks = offset; } + /** Offset relative to external (e.g Jack) time */ inline TickCount offset_ticks() const { return _offset_ticks; } diff --git a/tests/path_test.cpp b/tests/path_test.cpp index cf62340..c5c4415 100644 --- a/tests/path_test.cpp +++ b/tests/path_test.cpp @@ -14,6 +14,13 @@ main() cerr << !(Path("/foo").is_parent_of(Path("/foo2"))) << endl; cerr << Path::nameify("Signal Level [dB]") << endl; - + + cerr << endl << endl << "Descendants..." << endl; + cerr << "/ /foo " << Path::descendant_comparator("/", "/foo") << endl; + cerr << "/foo /foo/bar " << Path::descendant_comparator("/foo", "/foo/bar") << endl; + cerr << "/foo /foo " << Path::descendant_comparator("/foo", "/foo") << endl; + cerr << "/ / " << Path::descendant_comparator("/", "/") << endl; + cerr << "/baz / " << Path::descendant_comparator("/baz", "/") << endl; + return 0; } |