From 0c25b2aa8e173a96060adc52a34ecd43da79c305 Mon Sep 17 00:00:00 2001 From: Hans Baier Date: Fri, 16 May 2008 20:54:24 +0000 Subject: * Fixed crash on closing MIDI automation tracks, because ARDOUR::Parameter::operator< violated strict weak ordering, which is necessary for std::set to work correctly * few small style guide corrections git-svn-id: svn://localhost/ardour2/branches/3.0@3363 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/midi_ring_buffer.h | 30 ++++++++++++++-------- libs/ardour/ardour/parameter.h | 48 +++++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 12 deletions(-) (limited to 'libs') diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h index baa8e9d948..76cefd57a1 100644 --- a/libs/ardour/ardour/midi_ring_buffer.h +++ b/libs/ardour/ardour/midi_ring_buffer.h @@ -141,13 +141,15 @@ template bool MidiRingBufferBase::full_peek(size_t size, T* dst) { - if (read_space() < size) + if (read_space() < size) { return false; + } const size_t read_size = peek(size, dst); - if (read_size < size) + if (read_size < size) { peek(size - read_size, dst + read_size); + } return true; } @@ -181,13 +183,15 @@ template bool MidiRingBufferBase::full_read(size_t size, T* dst) { - if (read_space() < size) + if (read_space() < size) { return false; + } const size_t read_size = read(size, dst); - if (read_size < size) + if (read_size < size) { read(size - read_size, dst + read_size); + } return true; } @@ -292,11 +296,14 @@ inline bool MidiRingBuffer::read(double* time, size_t* size, Byte* buf) { bool success = MidiRingBufferBase::full_read(sizeof(double), (Byte*)time); - if (success) + + if (success) { success = MidiRingBufferBase::full_read(sizeof(size_t), (Byte*)size); - if (success) + } + if (success) { success = MidiRingBufferBase::full_read(*size, buf); - + } + return success; } @@ -308,8 +315,9 @@ inline bool MidiRingBuffer::read_prefix(double* time, size_t* size) { bool success = MidiRingBufferBase::full_read(sizeof(double), (Byte*)time); - if (success) + if (success) { success = MidiRingBufferBase::full_read(sizeof(size_t), (Byte*)size); + } return success; } @@ -338,8 +346,9 @@ MidiRingBuffer::write(double time, size_t size, const Byte* buf) // Don't write event if it doesn't match channel filter if (is_channel_event(buf[0]) && get_channel_mode() == FilterChannels) { Byte channel = buf[0] & 0x0F; - if ( !(get_channel_mask() & (1L << channel)) ) + if ( !(get_channel_mask() & (1L << channel)) ) { return 0; + } } if (write_space() < (sizeof(double) + sizeof(size_t) + size)) { @@ -388,8 +397,9 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t full_peek(sizeof(double), (Byte*)&ev_time); - if (ev_time > end) + if (ev_time > end) { break; + } bool success = MidiRingBufferBase::full_read(sizeof(double), (Byte*)&ev_time); if (success) { diff --git a/libs/ardour/ardour/parameter.h b/libs/ardour/ardour/parameter.h index a795ee0eaa..b86174aa0a 100644 --- a/libs/ardour/ardour/parameter.h +++ b/libs/ardour/ardour/parameter.h @@ -58,17 +58,61 @@ public: inline uint32_t id() const { return _id; } inline uint8_t channel() const { return _channel; } + /** + * Equivalence operator + * It is obvious from the definition that this operator + * is transitive, as required by stict weak ordering + * (see: http://www.sgi.com/tech/stl/StrictWeakOrdering.html) + */ inline bool operator==(const Parameter& id) const { return (_type == id._type && _id == id._id && _channel == id._channel); } - /** Arbitrary but fixed ordering (for use in e.g. std::map) */ + /** Strict weak ordering + * (see: http://www.sgi.com/tech/stl/StrictWeakOrdering.html) + * This is necessary so that std::set works): + * Sort Parameters first according to type then to id and lastly to channel. + * + * Proof: + *
    + *
  1. Irreflexivity: f(x, x) is false because of the irreflexivity of \c < in each branch.
  2. + * + *
  3. Antisymmetry: given x != y, f(x, y) implies !f(y, x) because of the same + * property of \c < in each branch and the symmetry of operator==.
  4. + * + *
  5. Transitivity: let f(x, y) and f(y, z) be true. We prove by assuming the contrary, + * that f(x, z) does not hold. + * That would imply exactly one of the following: + *
      + *
    1. x == z which contradicts the assumption f(x, y) and f(y, x) + * because of antisymmetry. + *
    2. + *
    3. f(z, x) is true. That would imply that one of the ivars (we call it i) + * of x is greater than the same ivar in z while all "previous" ivars + * are equal. That would imply that also in y all those "previous" + * ivars are equal and because if x.i > z.i it is impossible + * that there is an y that satisfies x.i < y.i < z.i at the same + * time which contradicts the assumption. + *
    4. + *
    + *
  6. + *
+ */ + inline bool operator<(const Parameter& id) const { #ifndef NDEBUG if (_type == NullAutomation) PBD::warning << "Uninitialized Parameter compared." << endmsg; #endif - return (_channel < id._channel || _type < id._type || _id < id._id); + if (_type < id._type) { + return true; + } else if (_type == id._type && _id < id._id) { + return true; + } else if (_id == id._id && _channel < id._channel) { + return true; + } + + return false; } inline operator bool() const { return (_type != 0); } -- cgit v1.2.3