#include "signaldata.h" #include <qvector.h> #include <qmutex.h> #include <qreadwritelock.h> class SignalData::PrivateData { public: PrivateData(): boundingRect(1.0, 1.0, -2.0, -2.0) // invalid { values.reserve(1000); } inline void append(const QPointF &sample) { values.append(sample); // adjust the bounding rectangle if ( boundingRect.width() < 0 || boundingRect.height() < 0 ) { boundingRect.setRect(sample.x(), sample.y(), 0.0, 0.0); } else { boundingRect.setRight(sample.x()); if ( sample.y() > boundingRect.bottom() ) boundingRect.setBottom(sample.y()); if ( sample.y() < boundingRect.top() ) boundingRect.setTop(sample.y()); } } QReadWriteLock lock; QVector<QPointF> values; QRectF boundingRect; QMutex mutex; // protecting pendingValues QVector<QPointF> pendingValues; }; SignalData::SignalData() { d_data = new PrivateData(); } SignalData::~SignalData() { delete d_data; } int SignalData::size() const { return d_data->values.size(); } QPointF SignalData::value(int index) const { return d_data->values[index]; } QRectF SignalData::boundingRect() const { return d_data->boundingRect; } void SignalData::lock() { d_data->lock.lockForRead(); } void SignalData::unlock() { d_data->lock.unlock(); } void SignalData::append(const QPointF &sample) { d_data->mutex.lock(); d_data->pendingValues += sample; const bool isLocked = d_data->lock.tryLockForWrite(); if ( isLocked ) { const int numValues = d_data->pendingValues.size(); const QPointF *pendingValues = d_data->pendingValues.data(); for ( int i = 0; i < numValues; i++ ) d_data->append(pendingValues[i]); d_data->pendingValues.clear(); d_data->lock.unlock(); } d_data->mutex.unlock(); } void SignalData::clearStaleValues(double limit) { d_data->lock.lockForWrite(); d_data->boundingRect = QRectF(1.0, 1.0, -2.0, -2.0); // invalid const QVector<QPointF> values = d_data->values; d_data->values.clear(); d_data->values.reserve(values.size()); int index; for ( index = values.size() - 1; index >= 0; index-- ) { if ( values[index].x() < limit ) break; } if ( index > 0 ) d_data->append(values[index++]); while ( index < values.size() - 1 ) d_data->append(values[index++]); d_data->lock.unlock(); } SignalData &SignalData::instance() { static SignalData valueVector; return valueVector; }