Changeset - 46213689acd3
[Not reviewed]
stream
0 4 0
Hasan Yavuz Ă–ZDERYA - 8 years ago 2017-12-19 10:13:34
hy@ozderya.net
sink stores pointer to connected source
4 files changed with 42 insertions and 0 deletions:
0 comments (0 inline, 0 general)
src/sink.cpp
Show inline comments
 
@@ -29,24 +29,35 @@ void Sink::connectFollower(Sink* sink)
 
}
 

	
 
void Sink::disconnectFollower(Sink* sink)
 
{
 
    Q_ASSERT(followers.contains(sink));
 

	
 
    followers.removeOne(sink);
 
}
 

	
 
void Sink::feedIn(const SamplePack& data)
 
{
 
    for (auto sink : followers)
 
    {
 
        sink->feedIn(data);
 
    }
 
}
 

	
 
void Sink::setNumChannels(unsigned nc, bool x)
 
{
 
    for (auto sink : followers)
 
    {
 
        sink->setNumChannels(nc, x);
 
    }
 
}
 

	
 
void Sink::setSource(const Source* s)
 
{
 
    Q_ASSERT((source == NULL) != (s == NULL));
 
    source = s;
 
}
 

	
 
const Source* Sink::connectedSource() const
 
{
 
    return source;
 
}
src/sink.h
Show inline comments
 
@@ -13,44 +13,53 @@
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  GNU General Public License for more details.
 

	
 
  You should have received a copy of the GNU General Public License
 
  along with serialplot.  If not, see <http://www.gnu.org/licenses/>.
 
*/
 

	
 
#ifndef SINK_H
 
#define SINK_H
 

	
 
#include <QList>
 
#include "samplepack.h"
 

	
 
class Source;
 

	
 
class Sink
 
{
 
public:
 
    /// Connects a sink to get any data that this sink
 
    /// gets. Connecting an already connected sink is an error.
 
    void connectFollower(Sink* sink);
 
    /// Disconnects a follower. Disconnecting an unconnected sink is
 
    /// an error.
 
    void disconnectFollower(Sink* sink);
 
    /// Returns the connected source. `NULL` if it's not connected.
 
    const Source* connectedSource() const;
 

	
 
protected:
 
    /// Entry point for incoming data. Re-implementations should
 
    /// call this function to feed followers.
 
    virtual void feedIn(const SamplePack& data);
 
    /// Is set by connected source. Re-implementations should call
 
    /// this function to update followers.
 
    virtual void setNumChannels(unsigned nc, bool x);
 
    /// Returns true if sink has X data
 
    virtual bool hasX() const = 0;
 
    /// Returns number of channels
 
    virtual unsigned numChannels() const = 0;
 
    /// Set by the connected source when its connected. When
 
    /// disconnecting it's set to `NULL`.
 
    ///
 
    /// @important Trying to connect a source while its already
 
    /// connected is an error.
 
    void setSource(const Source* s);
 

	
 
    friend Source;
 

	
 
private:
 
    QList<Sink*> followers;
 
    const Source* source = NULL;   ///< source that this sink is connected to
 
};
 

	
 
#endif // SINK_H
src/source.cpp
Show inline comments
 
@@ -3,51 +3,55 @@
 

	
 
  This file is part of serialplot.
 

	
 
  serialplot 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 3 of the License, or
 
  (at your option) any later version.
 

	
 
  serialplot 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 more details.
 

	
 
  You should have received a copy of the GNU General Public License
 
  along with serialplot.  If not, see <http://www.gnu.org/licenses/>.
 
*/
 

	
 
#include <QtGlobal>
 

	
 
#include "source.h"
 

	
 
void Source::connect(Sink* sink)
 
{
 
    Q_ASSERT(!sinks.contains(sink));
 
    Q_ASSERT(sink->connectedSource() == NULL);
 

	
 
    sinks.append(sink);
 
    sink->setSource(this);
 
    sink->setNumChannels(numChannels(), hasX());
 
}
 

	
 
void Source::disconnect(Sink* sink)
 
{
 
    Q_ASSERT(sinks.contains(sink));
 
    Q_ASSERT(sink->connectedSource() == this);
 

	
 
    sink->setSource(NULL);
 
    sinks.removeOne(sink);
 
}
 

	
 
void Source::feedOut(const SamplePack& data) const
 
{
 
    for (auto sink : sinks)
 
    {
 
        sink->feedIn(data);
 
    }
 
}
 

	
 
void Source::updateNumChannels() const
 
{
 
    for (auto sink : sinks)
 
    {
 
        sink->setNumChannels(numChannels(), hasX());
 
    }
 
}
tests/test.cpp
Show inline comments
 
@@ -102,48 +102,54 @@ TEST_CASE("sink", "[memory, stream]")
 

	
 
    sink.setNumChannels(3, false);
 
    REQUIRE(sink.numChannels() == 3);
 

	
 
    sink.feedIn(pack);
 
    REQUIRE(sink.totalFed == 100);
 
    sink.feedIn(pack);
 
    REQUIRE(sink.totalFed == 200);
 

	
 
    TestSink follower;
 

	
 
    sink.connectFollower(&follower);
 
    REQUIRE(follower.numChannels() == 3);
 
    REQUIRE(follower.hasX() == false);
 

	
 
    sink.feedIn(pack);
 
    REQUIRE(sink.totalFed == 300);
 
    REQUIRE(follower.totalFed == 100);
 

	
 
    sink.setNumChannels(2, true);
 
    REQUIRE(follower.numChannels() == 2);
 
    REQUIRE(follower.hasX() == true);
 
}
 

	
 
TEST_CASE("sink must be created unconnected", "[memory, stream]")
 
{
 
    TestSink sink;
 
    REQUIRE(sink.connectedSource() == NULL);
 
}
 

	
 
class TestSource : public Source
 
{
 
public:
 
    int _numChannels;
 
    bool _hasX;
 

	
 
    TestSource(unsigned nc, bool x)
 
        {
 
            _numChannels = nc;
 
            _hasX = x;
 
        };
 

	
 
    virtual unsigned numChannels() const
 
        {
 
            return _numChannels;
 
        };
 

	
 
    virtual bool hasX() const
 
        {
 
            return _hasX;
 
        };
 

	
 
    void _feed(const SamplePack& data) const
 
        {
 
@@ -164,48 +170,60 @@ TEST_CASE("source", "[memory, stream]")
 
    TestSink sink;
 

	
 
    TestSource source(3, false);
 

	
 
    REQUIRE(source.numChannels() == 3);
 
    REQUIRE(source.hasX() == false);
 

	
 
    source.connect(&sink);
 
    REQUIRE(sink.numChannels() == 3);
 
    REQUIRE(sink.hasX() == false);
 

	
 
    source._setNumChannels(5, true);
 
    REQUIRE(sink.numChannels() == 5);
 
    REQUIRE(sink.hasX() == true);
 

	
 
    SamplePack pack(100, 5, true);
 
    source._feed(pack);
 
    REQUIRE(sink.totalFed == 100);
 

	
 
    source.disconnect(&sink);
 
    source._feed(pack);
 
    REQUIRE(sink.totalFed == 100);
 
}
 

	
 
TEST_CASE("source must set/unset sink 'source'", "[memory, stream]")
 
{
 
    TestSink sink;
 
    TestSource source(3, false);
 

	
 
    source.connect(&sink);
 
    REQUIRE(sink.connectedSource() == &source);
 

	
 
    source.disconnect(&sink);
 
    REQUIRE(sink.connectedSource() == NULL);
 
}
 

	
 
TEST_CASE("IndexBuffer", "[memory, buffer]")
 
{
 
    IndexBuffer buf(10);
 

	
 
    REQUIRE(buf.size() == 10);
 
    for (unsigned i = 0; i < 10; i++)
 
    {
 
        REQUIRE(buf.sample(i) == i);
 
    }
 
    auto l = buf.limits();
 
    REQUIRE(l.start == 0);
 
    REQUIRE(l.end == 9);
 

	
 
    buf.resize(20);
 
    REQUIRE(buf.size() == 20);
 
    REQUIRE(buf.sample(15) == 15);
 
    l = buf.limits();
 
    REQUIRE(l.start == 0);
 
    REQUIRE(l.end == 19);
 
}
 

	
 
TEST_CASE("LinIndexBuffer", "[memory, buffer]")
 
{
 
    LinIndexBuffer buf(10, 0., 3.0);
0 comments (0 inline, 0 general)