diff options
-rw-r--r-- | raul/List.h | 46 | ||||
-rw-r--r-- | raul/TimeSlice.h | 2 | ||||
-rw-r--r-- | src/SMFReader.cpp | 15 | ||||
-rw-r--r-- | tests/list_test.cpp | 81 |
4 files changed, 134 insertions, 10 deletions
diff --git a/raul/List.h b/raul/List.h index e7e2158..79748ba 100644 --- a/raul/List.h +++ b/raul/List.h @@ -55,7 +55,7 @@ private: -/** A realtime safe, (partially) thread safe doubly linked list. +/** A realtime safe, (partially) thread safe doubly-linked list. * * Elements can be added safely while another thread is reading the list. * Like a typical ringbuffer, this is single-reader single-writer threadsafe @@ -75,6 +75,8 @@ public: void push_back(ListNode<T>* elem); // realtime safe void push_back(T& elem); // NOT realtime safe + void append(List<T>& list); + void clear(); /// Valid only in the write thread @@ -235,6 +237,48 @@ List<T>::push_back(T& elem) } +/** 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) +{ + ListNode<T>* const my_head = _head.get(); + ListNode<T>* const my_tail = _tail.get(); + ListNode<T>* const other_head = list._head.get(); + ListNode<T>* 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 diff --git a/raul/TimeSlice.h b/raul/TimeSlice.h index dec91e5..0c8bab8 100644 --- a/raul/TimeSlice.h +++ b/raul/TimeSlice.h @@ -86,7 +86,7 @@ public: void set_bpm(double bpm) { _beat_rate = 60.0/bpm; - //update_beat_time(); + update_beat_time(); } inline Seconds beats_to_seconds(BeatTime beats) const { diff --git a/src/SMFReader.cpp b/src/SMFReader.cpp index 56232cf..a267e48 100644 --- a/src/SMFReader.cpp +++ b/src/SMFReader.cpp @@ -97,6 +97,19 @@ SMFReader::open(const string& filename) if (_fd) { // Read type (bytes 8..9) + fseek(_fd, 0, SEEK_SET); + char mthd[5]; + mthd[4] = '\0'; + fread(mthd, 1, 4, _fd); + if (strcmp(mthd, "MThd")) { + cerr << "File is not an SMF file, aborting." << endl; + fclose(_fd); + _fd = NULL; + return false; + } + + + // Read type (bytes 8..9) fseek(_fd, 8, SEEK_SET); uint16_t type_be = 0; fread(&type_be, 2, 1, _fd); @@ -153,7 +166,7 @@ SMFReader::seek_to_track(unsigned track) if (!strcmp(id, "MTrk")) { ++track_pos; - std::cerr << "Found track " << track_pos << endl; + //std::cerr << "Found track " << track_pos << endl; } else { std::cerr << "Unknown chunk ID " << id << endl; } diff --git a/tests/list_test.cpp b/tests/list_test.cpp index faee491..133067b 100644 --- a/tests/list_test.cpp +++ b/tests/list_test.cpp @@ -33,7 +33,7 @@ int main() } } - std::cerr << "Removed 4 (by iterator)...\n"; + cout << "Removed 4 (by iterator)...\n"; for (List<int>::iterator i = l.begin(); i != l.end(); ++i) { cout << *i << endl; } @@ -41,7 +41,7 @@ int main() /*l.remove(1); - std::cerr << "Removed 1 (head) (by value)...\n"; + cout << "Removed 1 (head) (by value)...\n"; for (List<int>::iterator i = l.begin(); i != l.end(); ++i) { cout << *i << endl; } @@ -55,7 +55,7 @@ int main() } } - std::cerr << "Removed 2 (head) (by iterator)...\n"; + cout << "Removed 2 (head) (by iterator)...\n"; for (List<int>::iterator i = l.begin(); i != l.end(); ++i) { cout << *i << endl; } @@ -63,7 +63,7 @@ int main() /*l.remove(5); - std::cerr << "Removed 5 (by value)...\n"; + cout << "Removed 5 (by value)...\n"; for (List<int>::iterator i = l.begin(); i != l.end(); ++i) { cout << *i << endl; } @@ -71,7 +71,7 @@ int main() l.remove(8); - std::cerr << "Removed 8 (tail) (by value)...\n"; + cout << "Removed 8 (tail) (by value)...\n"; for (List<int>::iterator i = l.begin(); i != l.end(); ++i) { cout << *i << endl; } @@ -84,7 +84,7 @@ int main() } } - std::cerr << "Removed 7 (tail) (by iterator)...\n"; + cout << "Removed 7 (tail) (by iterator)...\n"; for (List<int>::iterator i = l.begin(); i != l.end(); ++i) { cout << *i << endl; } @@ -93,9 +93,76 @@ int main() List<int> r; r.push_back(new ListNode<int>(9)); r.erase(r.begin()); - std::cerr << "Should not see ANY numbers:\n"; + cout << "Should not see ANY numbers:\n"; for (List<int>::iterator i = r.begin(); i != r.end(); ++i) { cout << *i << endl; } + + cout << "\n\nTesting appending to an empty list:\n"; + l.clear(); + + List<int> l2; + l2.push_back(new ListNode<int>(1)); + l2.push_back(new ListNode<int>(2)); + l2.push_back(new ListNode<int>(3)); + l2.push_back(new ListNode<int>(4)); + + cout << "l1:\n"; + for (List<int>::iterator i = l.begin(); i != l.end(); ++i) { + cout << *i << endl; + } + + cout << "l2:\n"; + for (List<int>::iterator i = l2.begin(); i != l2.end(); ++i) { + cout << *i << endl; + } + + l.append(l2); + cout << "l1.append(l2):\n"; + for (List<int>::iterator i = l.begin(); i != l.end(); ++i) { + cout << *i << endl; + } + + cout << "\n\nAppending non-empty lists:\n"; + l2.push_back(new ListNode<int>(5)); + l2.push_back(new ListNode<int>(6)); + l2.push_back(new ListNode<int>(7)); + l2.push_back(new ListNode<int>(8)); + + cout << "l1:\n"; + for (List<int>::iterator i = l.begin(); i != l.end(); ++i) { + cout << *i << endl; + } + + cout << "l2:\n"; + for (List<int>::iterator i = l2.begin(); i != l2.end(); ++i) { + cout << *i << endl; + } + + l.append(l2); + cout << "l1.append(l2):\n"; + for (List<int>::iterator i = l.begin(); i != l.end(); ++i) { + cout << *i << endl; + } + + + cout << "\n\nAppending an empty list:\n"; + + cout << "l1:\n"; + for (List<int>::iterator i = l.begin(); i != l.end(); ++i) { + cout << *i << endl; + } + + cout << "l2:\n"; + for (List<int>::iterator i = l2.begin(); i != l2.end(); ++i) { + cout << *i << endl; + } + + l.append(l2); + cout << "l1.append(l2):\n"; + for (List<int>::iterator i = l.begin(); i != l.end(); ++i) { + cout << *i << endl; + } + return 0; } |