Skip to content
Snippets Groups Projects
Commit d7d556ba authored by Nicolas Pope's avatar Nicolas Pope
Browse files

Add channel registration

parent b2ded16e
No related branches found
No related tags found
No related merge requests found
Pipeline #27217 failed
...@@ -13,6 +13,32 @@ ...@@ -13,6 +13,32 @@
namespace ftl { namespace ftl {
namespace data { namespace data {
class Session;
/** Kind of channel in terms of data persistence */
enum class ChannelMode {
PERSISTENT, // Most recent value, even from previous fram
IMMEDIATE, // Only most recent value since last frame
SEQUENCE // All changes since last frame
};
struct ChannelConfig {
std::string name;
ChannelMode mode;
size_t type_id;
};
template <typename T>
ChannelConfig make_channel(const std::string &name, ChannelMode mode) {
// TODO: Generate packer + unpacker?
return {name, mode, typeid(T).hash_code()};
}
//template <>
//ChannelConfig make_channel<void>(const std::string &name, ChannelMode mode) {
// return {name, mode, 0};
//}
class Frame { class Frame {
public: public:
uint32_t id=0; uint32_t id=0;
...@@ -20,7 +46,7 @@ class Frame { ...@@ -20,7 +46,7 @@ class Frame {
public: public:
Frame() : parent_(nullptr) {}; Frame() : parent_(nullptr) {};
explicit Frame(Frame *parent) : parent_(parent) {}; explicit Frame(Session *parent) : parent_(parent) {};
~Frame() { flush(); }; ~Frame() { flush(); };
Frame(Frame &&f) { Frame(Frame &&f) {
...@@ -38,13 +64,9 @@ class Frame { ...@@ -38,13 +64,9 @@ class Frame {
Frame(const Frame &)=delete; Frame(const Frame &)=delete;
Frame &operator=(const Frame &)=delete; Frame &operator=(const Frame &)=delete;
inline bool has(ftl::codecs::Channel c) { inline bool has(ftl::codecs::Channel c);
return data_.find(c) != data_.end() || (parent_ && parent_->has(c));
}
inline bool changed(ftl::codecs::Channel c) { inline bool changed(ftl::codecs::Channel c);
return changed_.find(c) != changed_.end();
}
inline const std::unordered_set<ftl::codecs::Channel> &changed() const { return changed_; } inline const std::unordered_set<ftl::codecs::Channel> &changed() const { return changed_; }
...@@ -83,14 +105,9 @@ class Frame { ...@@ -83,14 +105,9 @@ class Frame {
template <typename T> template <typename T>
void set(ftl::codecs::Channel c, const T &v); void set(ftl::codecs::Channel c, const T &v);
inline void on(ftl::codecs::Channel c, const std::function<bool(Frame&,ftl::codecs::Channel)> &cb) { inline void on(ftl::codecs::Channel c, const std::function<bool(Frame&,ftl::codecs::Channel)> &cb);
if (parent_) parent_->on(c, cb);
else triggers_[c].push_back(cb); // TODO: Find better way to enable removal
}
inline void on(const std::function<bool(Frame&,ftl::codecs::Channel)> &cb) { inline void on(const std::function<bool(Frame&,ftl::codecs::Channel)> &cb);
any_triggers_.push_back(cb);
}
void merge(Frame &); void merge(Frame &);
...@@ -114,19 +131,46 @@ class Frame { ...@@ -114,19 +131,46 @@ class Frame {
// onEndFlush // onEndFlush
// onError // onError
static void registerChannel(ftl::codecs::Channel, const ChannelConfig &config);
static void clearRegistry();
static bool isPersistent(ftl::codecs::Channel);
static size_t getChannelType(ftl::codecs::Channel);
static std::string getChannelName(ftl::codecs::Channel);
static ftl::codecs::Channel getChannelByName(const std::string &name);
private: private:
std::map<ftl::codecs::Channel, std::any> data_; std::map<ftl::codecs::Channel, std::any> data_;
std::unordered_set<ftl::codecs::Channel> changed_; std::unordered_set<ftl::codecs::Channel> changed_;
std::unordered_map<ftl::codecs::Channel, std::list<std::function<bool(Frame&,ftl::codecs::Channel)>>> triggers_; std::unordered_map<ftl::codecs::Channel, std::list<std::function<bool(Frame&,ftl::codecs::Channel)>>> triggers_;
std::list<std::function<bool(Frame&,ftl::codecs::Channel)>> any_triggers_; std::list<std::function<bool(Frame&,ftl::codecs::Channel)>> any_triggers_;
Frame *parent_; Session *parent_;
}; };
class Session : public Frame {};
} }
} }
// ==== Implementations ======================================================== // ==== Implementations ========================================================
bool ftl::data::Frame::has(ftl::codecs::Channel c) {
return data_.find(c) != data_.end() || (parent_ && parent_->has(c));
}
bool ftl::data::Frame::changed(ftl::codecs::Channel c) {
return changed_.find(c) != changed_.end();
}
void ftl::data::Frame::on(ftl::codecs::Channel c, const std::function<bool(Frame&,ftl::codecs::Channel)> &cb) {
if (parent_) parent_->on(c, cb);
else triggers_[c].push_back(cb); // TODO: Find better way to enable removal
}
void ftl::data::Frame::on(const std::function<bool(Frame&,ftl::codecs::Channel)> &cb) {
any_triggers_.push_back(cb);
}
template <typename T> template <typename T>
bool ftl::data::Frame::isType(ftl::codecs::Channel c) { bool ftl::data::Frame::isType(ftl::codecs::Channel c) {
auto i = data_.find(c); auto i = data_.find(c);
...@@ -160,6 +204,8 @@ const T &ftl::data::Frame::get(ftl::codecs::Channel c) const { ...@@ -160,6 +204,8 @@ const T &ftl::data::Frame::get(ftl::codecs::Channel c) const {
template <typename T> template <typename T>
T &ftl::data::Frame::create(ftl::codecs::Channel c, const T &value) { T &ftl::data::Frame::create(ftl::codecs::Channel c, const T &value) {
touch(c); touch(c);
size_t t = getChannelType(c);
if (t > 0 && t != typeid(T).hash_code()) throw FTL_Error("Incorrect type for channel " << static_cast<unsigned int>(c));
auto &d = data_[c]; auto &d = data_[c];
d = value; d = value;
return *std::any_cast<T>(&d); return *std::any_cast<T>(&d);
...@@ -168,6 +214,8 @@ T &ftl::data::Frame::create(ftl::codecs::Channel c, const T &value) { ...@@ -168,6 +214,8 @@ T &ftl::data::Frame::create(ftl::codecs::Channel c, const T &value) {
template <typename T> template <typename T>
T &ftl::data::Frame::create(ftl::codecs::Channel c) { T &ftl::data::Frame::create(ftl::codecs::Channel c) {
touch(c); touch(c);
size_t t = getChannelType(c);
if (t > 0 && t != typeid(T).hash_code()) throw FTL_Error("Incorrect type for channel " << static_cast<unsigned int>(c));
if (!isType<T>(c)) return data_[c].emplace<T>(); if (!isType<T>(c)) return data_[c].emplace<T>();
else return *std::any_cast<T>(&data_[c]); else return *std::any_cast<T>(&data_[c]);
} }
......
#include <ftl/data/new_frame.hpp> #include <ftl/data/new_frame.hpp>
using ftl::data::Frame; using ftl::data::Frame;
using ftl::data::ChannelConfig;
using ftl::data::ChannelMode;
#define LOGURU_REPLACE_GLOG 1 #define LOGURU_REPLACE_GLOG 1
#include <loguru.hpp> #include <loguru.hpp>
static std::unordered_map<ftl::codecs::Channel, ChannelConfig> reg_channels;
void Frame::registerChannel(ftl::codecs::Channel c, const ChannelConfig &config) {
auto i = reg_channels.find(c);
if (i != reg_channels.end()) {
throw FTL_Error("Channel " << static_cast<unsigned int>(c) << " already registered");
}
reg_channels[c] = config;
}
void Frame::clearRegistry() {
reg_channels.clear();
}
bool Frame::isPersistent(ftl::codecs::Channel c) {
auto i = reg_channels.find(c);
return (i != reg_channels.end()) ? i->second.mode == ChannelMode::PERSISTENT : true;
}
size_t Frame::getChannelType(ftl::codecs::Channel c) {
auto i = reg_channels.find(c);
return (i != reg_channels.end()) ? i->second.type_id : 0;
}
std::string Frame::getChannelName(ftl::codecs::Channel c) {
auto i = reg_channels.find(c);
return (i != reg_channels.end()) ? i->second.name : "";
}
ftl::codecs::Channel Frame::getChannelByName(const std::string &name) {
return ftl::codecs::Channel::Colour;
}
bool Frame::flush() { bool Frame::flush() {
if (parent_) { if (parent_) {
for (auto c : changed_) { for (auto c : changed_) {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#include <ftl/data/new_frame.hpp> #include <ftl/data/new_frame.hpp>
using ftl::data::Session;
using ftl::data::Frame; using ftl::data::Frame;
using ftl::codecs::Channel; using ftl::codecs::Channel;
...@@ -133,7 +133,7 @@ TEST_CASE("ftl::data::Frame create", "[Frame]") { ...@@ -133,7 +133,7 @@ TEST_CASE("ftl::data::Frame create", "[Frame]") {
TEST_CASE("ftl::data::Frame use of parent", "[Frame]") { TEST_CASE("ftl::data::Frame use of parent", "[Frame]") {
SECTION("get from parent") { SECTION("get from parent") {
Frame p; Session p;
Frame f(&p); Frame f(&p);
p.create<int>(Channel::Pose, 55); p.create<int>(Channel::Pose, 55);
...@@ -147,7 +147,7 @@ TEST_CASE("ftl::data::Frame use of parent", "[Frame]") { ...@@ -147,7 +147,7 @@ TEST_CASE("ftl::data::Frame use of parent", "[Frame]") {
} }
SECTION("has from parent") { SECTION("has from parent") {
Frame p; Session p;
Frame f(&p); Frame f(&p);
p.create<int>(Channel::Pose, 55); p.create<int>(Channel::Pose, 55);
...@@ -155,7 +155,7 @@ TEST_CASE("ftl::data::Frame use of parent", "[Frame]") { ...@@ -155,7 +155,7 @@ TEST_CASE("ftl::data::Frame use of parent", "[Frame]") {
} }
SECTION("no change in parent") { SECTION("no change in parent") {
Frame p; Session p;
Frame f(&p); Frame f(&p);
p.create<int>(Channel::Pose, 55); p.create<int>(Channel::Pose, 55);
...@@ -197,7 +197,7 @@ TEST_CASE("ftl::data::Frame flush", "[Frame]") { ...@@ -197,7 +197,7 @@ TEST_CASE("ftl::data::Frame flush", "[Frame]") {
} }
SECTION("parent event on flush") { SECTION("parent event on flush") {
Frame p; Session p;
Frame f(&p); Frame f(&p);
int event = 0; int event = 0;
...@@ -214,7 +214,7 @@ TEST_CASE("ftl::data::Frame flush", "[Frame]") { ...@@ -214,7 +214,7 @@ TEST_CASE("ftl::data::Frame flush", "[Frame]") {
} }
SECTION("parent change on flush") { SECTION("parent change on flush") {
Frame p; Session p;
Frame f(&p); Frame f(&p);
p.create<int>(Channel::Pose, 55); p.create<int>(Channel::Pose, 55);
...@@ -242,6 +242,33 @@ TEST_CASE("ftl::data::Frame flush", "[Frame]") { ...@@ -242,6 +242,33 @@ TEST_CASE("ftl::data::Frame flush", "[Frame]") {
} }
} }
TEST_CASE("ftl::data::Frame register", "[Frame]") {
SECTION("register typed channel and valid create") {
Frame f;
Frame::registerChannel(Channel::Colour, ftl::data::make_channel<float>("colour", ftl::data::ChannelMode::PERSISTENT));
REQUIRE( f.create<float>(Channel::Colour, 5.0f) == 5.0f );
Frame::clearRegistry();
}
SECTION("register typed channel and invalid create") {
Frame f;
Frame::registerChannel(Channel::Colour, ftl::data::make_channel<float>("colour", ftl::data::ChannelMode::PERSISTENT));
bool err = false;
try {
f.create<int>(Channel::Colour, 5);
} catch(const std::exception &e) {
err = true;
}
REQUIRE( err );
Frame::clearRegistry();
}
}
// ==== Complex type overload test ============================================= // ==== Complex type overload test =============================================
struct TestA { struct TestA {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment