summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-10-08 16:30:57 +0000
committerDavid Robillard <d@drobilla.net>2007-10-08 16:30:57 +0000
commit9f975e1e8a7dd0d8d90739829dc07d1188ad51e5 (patch)
tree2dda260e26488f364aec848262279e6b08c3d99a
parentd9269cb513631751e951c07b32b41a496de0a493 (diff)
downloadraul-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.hpp416
-rw-r--r--raul/ListImpl.hpp431
-rw-r--r--raul/Makefile.am1
-rw-r--r--raul/Path.hpp3
-rw-r--r--raul/TimeSlice.hpp11
-rw-r--r--tests/path_test.cpp9
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;
}