Compare commits

...

8 Commits

26 changed files with 384 additions and 272 deletions

View File

@ -30,8 +30,9 @@ target_sources(nf7_core
uv/file.hh uv/file.hh
uv/parallelism.hh uv/parallelism.hh
clock.hh clock.hh
dealer.hh
logger.hh logger.hh
mutex.hh meta_env.hh
version.hh version.hh
) )
@ -50,6 +51,7 @@ target_sources(nf7_core_test
uv/file_test.cc uv/file_test.cc
uv/parallelism_test.cc uv/parallelism_test.cc
clock_test.cc clock_test.cc
meta_env_test.cc
) )
target_link_libraries(nf7_core_test target_link_libraries(nf7_core_test
PRIVATE PRIVATE

52
core/dealer.hh Normal file
View File

@ -0,0 +1,52 @@
// No copyright
#pragma once
#include <memory>
#include <utility>
#include "iface/subsys/dealer.hh"
namespace nf7::core {
template <typename T>
class Maker : public subsys::Maker<T> {
public:
using subsys::Maker<T>::Maker;
using subsys::Maker<T>::Notify;
};
template <typename T>
class Taker : public subsys::Taker<T>, public Observer<T>::Target {
public:
using subsys::Taker<T>::Taker;
void Take(T&& v) noexcept override {
Observer<T>::Target::Notify(std::move(v));
}
};
template <typename T>
class NullMaker final : public subsys::Maker<T> {
public:
static inline const auto kInstance = std::make_shared<NullMaker<T>>();
public:
NullMaker() noexcept : subsys::Maker<T>("nf7::core::NullMaker") { }
private:
using subsys::Maker<T>::Notify;
};
template <typename T>
class NullTaker final : public subsys::Taker<T> {
public:
static inline const auto kInstance = std::make_shared<NullTaker<T>>();
public:
NullTaker() noexcept : subsys::Taker<T>("nf7::core::NullTaker") { }
void Take(T&&) noexcept override { }
};
} // namespace nf7::core

View File

@ -11,13 +11,7 @@ namespace nf7::core {
class NullLogger : public subsys::Logger { class NullLogger : public subsys::Logger {
public: public:
static const std::shared_ptr<NullLogger>& instance() static inline const auto kInstance = std::make_shared<NullLogger>();
try {
static const auto kInstance = std::make_shared<NullLogger>();
return kInstance;
} catch (const std::bad_alloc&) {
throw MemoryException {};
}
public: public:
NullLogger() noexcept : subsys::Logger("nf7::core::NullLogger") { } NullLogger() noexcept : subsys::Logger("nf7::core::NullLogger") { }

View File

@ -60,7 +60,19 @@ class Lambda::Thread : public luajit::Thread {
}; };
void Lambda::Main(const nf7::Value& v) noexcept { Lambda::Lambda(nf7::Env& env,
const std::shared_ptr<Value>& func,
const std::shared_ptr<subsys::Maker<IO>>& maker)
: nf7::Lambda(), Observer<IO>(*maker),
clock_(env.GetOr<subsys::Clock>()),
concurrency_(env.Get<subsys::Concurrency>()),
logger_(env.GetOr<subsys::Logger>(NullLogger::kInstance)),
maker_(maker),
taker_(env.GetOr<subsys::Taker<IO>>(NullTaker<IO>::kInstance)),
lua_(env.Get<luajit::Context>()),
func_(func) { }
void Lambda::Notify(const IO& v) noexcept {
lua_->Exec([this, self = shared_from_this(), v](auto& lua) { lua_->Exec([this, self = shared_from_this(), v](auto& lua) {
recvq_.push_back(v); recvq_.push_back(v);
++recv_count_; ++recv_count_;
@ -134,8 +146,9 @@ void Lambda::PushLuaContextObject(TaskContext& lua) noexcept {
lua_pushcfunction(*lua, [](auto L) { lua_pushcfunction(*lua, [](auto L) {
const auto la = self(L); const auto la = self(L);
const auto v = (TaskContext {la->lua_, L}).CheckValue(2); const auto v = (TaskContext {la->lua_, L}).CheckValue(2);
la->concurrency_->Exec( la->concurrency_->Exec([la, v = v](auto&) mutable {
[la, v](auto&) { la->emitter()->Emit(nf7::Value {v}); }); la->taker_->Take(std::move(v));
});
return 1; return 1;
}); });
lua_setfield(*lua, -2, "send"); lua_setfield(*lua, -2, "send");

View File

@ -9,6 +9,7 @@
#include "iface/subsys/clock.hh" #include "iface/subsys/clock.hh"
#include "iface/subsys/concurrency.hh" #include "iface/subsys/concurrency.hh"
#include "iface/subsys/dealer.hh"
#include "iface/subsys/logger.hh" #include "iface/subsys/logger.hh"
#include "iface/env.hh" #include "iface/env.hh"
#include "iface/lambda.hh" #include "iface/lambda.hh"
@ -16,38 +17,47 @@
#include "core/luajit/context.hh" #include "core/luajit/context.hh"
#include "core/luajit/thread.hh" #include "core/luajit/thread.hh"
#include "core/logger.hh" #include "core/logger.hh"
#include "core/dealer.hh"
namespace nf7::core::luajit { namespace nf7::core::luajit {
class Lambda : class Lambda :
public nf7::LambdaBase, public nf7::Lambda,
public std::enable_shared_from_this<Lambda> { public std::enable_shared_from_this<Lambda>,
public: private Observer<nf7::Value> {
explicit Lambda(nf7::Env& env, const std::shared_ptr<luajit::Value>& func)
: LambdaBase(),
clock_(env.GetOr<subsys::Clock>()),
concurrency_(env.Get<subsys::Concurrency>()),
logger_(env.GetOr<subsys::Logger>(NullLogger::instance())),
lua_(env.Get<luajit::Context>()),
func_(func) { }
uint64_t exitCount() const noexcept { return exit_count_; }
uint64_t abortCount() const noexcept { return abort_count_; }
private: private:
class Thread; class Thread;
private: using IO = nf7::Value;
void Main(const nf7::Value& v) noexcept override;
public:
Lambda(nf7::Env& env, const std::shared_ptr<Value>& func)
: Lambda(
env, func,
env.GetOr<subsys::Maker<IO>>(NullMaker<IO>::kInstance)) { }
private:
Lambda(nf7::Env&,
const std::shared_ptr<Value>&,
const std::shared_ptr<subsys::Maker<IO>>&);
private:
void Notify(const IO&) noexcept override;
void Resume(TaskContext&) noexcept; void Resume(TaskContext&) noexcept;
void PushLuaContextObject(TaskContext&) noexcept; void PushLuaContextObject(TaskContext&) noexcept;
public:
uint64_t exitCount() const noexcept { return exit_count_; }
uint64_t abortCount() const noexcept { return abort_count_; }
private: private:
const std::shared_ptr<subsys::Clock> clock_; const std::shared_ptr<subsys::Clock> clock_;
const std::shared_ptr<subsys::Concurrency> concurrency_; const std::shared_ptr<subsys::Concurrency> concurrency_;
const std::shared_ptr<subsys::Logger> logger_; const std::shared_ptr<subsys::Logger> logger_;
const std::shared_ptr<subsys::Maker<IO>> maker_;
const std::shared_ptr<subsys::Taker<IO>> taker_;
const std::shared_ptr<Context> lua_; const std::shared_ptr<Context> lua_;
const std::shared_ptr<Value> func_; const std::shared_ptr<Value> func_;
@ -57,7 +67,7 @@ class Lambda :
std::atomic<uint64_t> exit_count_ = 0; std::atomic<uint64_t> exit_count_ = 0;
std::atomic<uint64_t> abort_count_ = 0; std::atomic<uint64_t> abort_count_ = 0;
std::deque<nf7::Value> recvq_; std::deque<IO> recvq_;
uint64_t recv_count_ = 0; uint64_t recv_count_ = 0;
bool awaiting_value_ = false; bool awaiting_value_ = false;
}; };

View File

@ -7,9 +7,11 @@
#include <vector> #include <vector>
#include "iface/subsys/clock.hh" #include "iface/subsys/clock.hh"
#include "iface/subsys/dealer.hh"
#include "core/luajit/context.hh" #include "core/luajit/context.hh"
#include "core/clock.hh" #include "core/clock.hh"
#include "core/dealer.hh"
#include "iface/common/observer_test.hh" #include "iface/common/observer_test.hh"
#include "iface/subsys/logger_test.hh" #include "iface/subsys/logger_test.hh"
@ -22,10 +24,15 @@ using namespace std::literals;
namespace { namespace {
class LuaJIT_Lambda : public nf7::core::luajit::test::ContextFixture { class LuaJIT_Lambda : public nf7::core::luajit::test::ContextFixture {
public: public:
using ContextFixture::ContextFixture; LuaJIT_Lambda()
: maker_(std::make_shared<nf7::core::Maker<nf7::Value>>("mock maker")),
taker_(std::make_shared<nf7::core::Taker<nf7::Value>>("mock taker")) {
Install<nf7::subsys::Maker<nf7::Value>>(maker_);
Install<nf7::subsys::Taker<nf7::Value>>(taker_);
}
std::shared_ptr<nf7::core::luajit::Value> Compile( std::shared_ptr<nf7::core::luajit::Value> Compile(
const char* script) noexcept { const char* script) {
auto lua = env().Get<nf7::core::luajit::Context>(); auto lua = env().Get<nf7::core::luajit::Context>();
std::shared_ptr<nf7::core::luajit::Value> func; std::shared_ptr<nf7::core::luajit::Value> func;
@ -48,24 +55,27 @@ class LuaJIT_Lambda : public nf7::core::luajit::test::ContextFixture {
auto func = Compile(script); auto func = Compile(script);
auto sut = std::make_shared<nf7::core::luajit::Lambda>(*env, func);
for (const auto& v : in) {
sut->taker()->Take(v);
}
::testing::StrictMock< ::testing::StrictMock<
nf7::test::ObserverMock<nf7::Value>> obs {*sut->maker()}; nf7::test::ObserverMock<nf7::Value>> obs {*taker_};
::testing::Sequence seq; ::testing::Sequence seq;
for (const auto& v : out) { for (const auto& v : out) {
EXPECT_CALL(obs, NotifyWithMove(nf7::Value {v})) EXPECT_CALL(obs, NotifyWithMove(nf7::Value {v}))
.InSequence(seq); .InSequence(seq);
} }
auto sut = std::make_shared<nf7::core::luajit::Lambda>(*env, func);
for (const auto& v : in) {
maker_->Notify({v});
}
ConsumeTasks(); ConsumeTasks();
EXPECT_EQ(sut->exitCount(), expectExit); EXPECT_EQ(sut->exitCount(), expectExit);
EXPECT_EQ(sut->abortCount(), expectAbort); EXPECT_EQ(sut->abortCount(), expectAbort);
} }
protected:
const std::shared_ptr<nf7::core::Maker<nf7::Value>> maker_;
const std::shared_ptr<nf7::core::Taker<nf7::Value>> taker_;
}; };
} // namespace } // namespace
@ -101,12 +111,12 @@ TEST_P(LuaJIT_Lambda, CtxMultiRecvWithDelay) {
"nf7:assert(\"integer\" == ctx:recv():type())"); "nf7:assert(\"integer\" == ctx:recv():type())");
auto sut = std::make_shared<nf7::core::luajit::Lambda>(env(), func); auto sut = std::make_shared<nf7::core::luajit::Lambda>(env(), func);
sut->taker()->Take(nf7::Value::Null {}); maker_->Notify(nf7::Value::Null {});
ConsumeTasks(); ConsumeTasks();
EXPECT_EQ(sut->exitCount(), 0); EXPECT_EQ(sut->exitCount(), 0);
EXPECT_EQ(sut->abortCount(), 0); EXPECT_EQ(sut->abortCount(), 0);
sut->taker()->Take(nf7::Value::Integer {}); maker_->Notify(nf7::Value::Integer {});
ConsumeTasks(); ConsumeTasks();
EXPECT_EQ(sut->exitCount(), 1); EXPECT_EQ(sut->exitCount(), 1);
EXPECT_EQ(sut->abortCount(), 0); EXPECT_EQ(sut->abortCount(), 0);

91
core/meta_env.hh Normal file
View File

@ -0,0 +1,91 @@
// No copyright
#pragma once
#include <algorithm>
#include <cassert>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "iface/subsys/meta_env.hh"
namespace nf7::core {
class NullMetaEnv : public subsys::MetaEnv {
public:
static inline const auto kInstance = std::make_shared<NullMetaEnv>();
public:
NullMetaEnv() noexcept : subsys::MetaEnv("nf7::core::NullMetaEnv") { }
public:
Env* FindOr(std::string_view) const noexcept override { return nullptr; }
std::optional<Pair> FindOr(uint64_t) const noexcept override { return std::nullopt; }
std::vector<Pair> FetchAll() const override { return {}; }
std::shared_ptr<subsys::MetaEnv> parent() const noexcept override { return nullptr; }
};
class MetaEnv : public subsys::MetaEnv {
public:
using SharedPair = std::pair<std::string, std::shared_ptr<Env>>;
private:
static std::vector<SharedPair>&& Sort(std::vector<SharedPair>&& v) noexcept {
std::sort(v.begin(), v.end(),
[](const auto& a, const auto& b) { return a.first < b.first; });
return v;
}
public:
explicit MetaEnv(std::vector<SharedPair>&& children,
const std::weak_ptr<subsys::MetaEnv>& parent = {}) noexcept
: subsys::MetaEnv("nf7::core::MetaEnv"),
children_(Sort(std::move(children))),
parent_(parent) {
assert(std::all_of(children_.begin(), children_.end(),
[](auto& x) { return x.second; }));
}
public:
Env* FindOr(std::string_view name) const noexcept override {
const auto itr = std::lower_bound(
children_.cbegin(), children_.cend(), name,
[](const auto& a, const auto& b) { return a.first < b; });
if (children_.cend() == itr || itr->first != name) {
return nullptr;
}
return itr->second.get();
}
std::optional<Pair> FindOr(uint64_t index) const noexcept override {
if (index >= children_.size()) {
return std::nullopt;
}
const auto& child = children_[index];
return Pair {child.first, *child.second};
}
std::vector<Pair> FetchAll() const override
try {
std::vector<Pair> ret;
ret.reserve(children_.size());
for (const auto& child : children_) {
ret.emplace_back(child.first, *child.second);
}
return ret;
} catch (const std::bad_alloc&) {
throw MemoryException {};
}
public:
std::shared_ptr<subsys::MetaEnv> parent() const noexcept override {
return parent_.lock();
}
private:
const std::vector<SharedPair> children_;
const std::weak_ptr<subsys::MetaEnv> parent_;
};
} // namespace nf7::core

74
core/meta_env_test.cc Normal file
View File

@ -0,0 +1,74 @@
// No copyright
#include "core/meta_env.hh"
#include <gtest/gtest.h>
#include "iface/env.hh"
static inline std::shared_ptr<nf7::Env> MakeEmptyEnv() {
return std::make_shared<nf7::SimpleEnv>(nf7::SimpleEnv::FactoryMap {});
}
static inline bool MatchPair(const std::optional<nf7::subsys::MetaEnv::Pair>& a,
const nf7::subsys::MetaEnv::Pair& b) {
return a && a->first == b.first && &a->second == &b.second;
}
TEST(MetaEnv, FindOrByName) {
const auto a = MakeEmptyEnv();
const auto b = MakeEmptyEnv();
const auto c = MakeEmptyEnv();
nf7::core::MetaEnv sut {
{
{"b", b},
{"c", c},
{"a", a},
},
};
EXPECT_EQ(sut.FindOr(""), nullptr);
EXPECT_EQ(sut.FindOr("a"), a.get());
EXPECT_EQ(sut.FindOr("b"), b.get());
EXPECT_EQ(sut.FindOr("c"), c.get());
EXPECT_EQ(sut.FindOr("d"), nullptr);
}
TEST(MetaEnv, FindOrByIndex) {
const auto a = MakeEmptyEnv();
const auto b = MakeEmptyEnv();
const auto c = MakeEmptyEnv();
nf7::core::MetaEnv sut {
{
{"b", b},
{"c", c},
{"a", a},
},
};
EXPECT_TRUE(MatchPair(sut.FindOr(0), {"a", *a}));
EXPECT_TRUE(MatchPair(sut.FindOr(1), {"b", *b}));
EXPECT_TRUE(MatchPair(sut.FindOr(2), {"c", *c}));
EXPECT_EQ(sut.FindOr(3), std::nullopt);
}
TEST(MetaEnv, FetchAll) {
const auto a = MakeEmptyEnv();
const auto b = MakeEmptyEnv();
const auto c = MakeEmptyEnv();
nf7::core::MetaEnv sut {
{
{"b", b},
{"c", c},
{"a", a},
},
};
const auto all = sut.FetchAll();
EXPECT_EQ(all.size(), 3);
EXPECT_TRUE(MatchPair(all[0], {"a", *a}));
EXPECT_TRUE(MatchPair(all[1], {"b", *b}));
EXPECT_TRUE(MatchPair(all[2], {"c", *c}));
}

View File

@ -1,17 +0,0 @@
// No copyright
#pragma once
#include "iface/common/mutex.hh"
#include "iface/data/wrap.hh"
namespace nf7::core {
class Mutex : public data::Wrap<nf7::Mutex> {
public:
Mutex() : Wrap("nf7::core::Mutex", mtx_) { }
private:
nf7::Mutex mtx_;
};
} // namespace nf7::core

View File

@ -55,7 +55,7 @@ void Concurrency::Push(SyncTask&& task) noexcept {
Concurrency::Impl::Impl(Env& env) Concurrency::Impl::Impl(Env& env)
: clock_(env.Get<subsys::Clock>()), : clock_(env.Get<subsys::Clock>()),
logger_(env.GetOr<subsys::Logger>(NullLogger::instance())) { logger_(env.GetOr<subsys::Logger>(NullLogger::kInstance)) {
} }
std::chrono::milliseconds Concurrency::Impl::Consume() noexcept { std::chrono::milliseconds Concurrency::Impl::Consume() noexcept {

View File

@ -29,7 +29,7 @@ class Context : public subsys::Interface {
protected: protected:
Context(const char* name, Env& env) Context(const char* name, Env& env)
: subsys::Interface(name), : subsys::Interface(name),
logger_(env.GetOr<subsys::Logger>(NullLogger::instance())), logger_(env.GetOr<subsys::Logger>(NullLogger::kInstance)),
loop_(MakeLoop()) { } loop_(MakeLoop()) { }
public: public:

View File

@ -52,11 +52,11 @@ std::shared_ptr<File> File::Make(
File::File(Env& env, File::File(Env& env,
std::string_view path, std::string_view path,
uvw::file_req::file_open_flags open_flags) uvw::file_req::file_open_flags open_flags)
try : data::FiniteBuffer("nf7::core::uv::File::Finite"), try : subsys::FiniteBuffer("nf7::core::uv::File::Finite"),
data::ResizableBuffer("nf7::core::uv::File::Resizable"), subsys::ResizableBuffer("nf7::core::uv::File::Resizable"),
data::ReadableBuffer("nf7::core::uv::File::Readable"), subsys::ReadableBuffer("nf7::core::uv::File::Readable"),
data::WritableBuffer("nf7::core::uv::File::Writable"), subsys::WritableBuffer("nf7::core::uv::File::Writable"),
logger_(env.GetOr<subsys::Logger>(NullLogger::instance())), logger_(env.GetOr<subsys::Logger>(NullLogger::kInstance)),
delete_(env.Get<Context>()->Make<uvw::async_handle>()), delete_(env.Get<Context>()->Make<uvw::async_handle>()),
path_(path), path_(path),
open_flags_(open_flags), open_flags_(open_flags),

View File

@ -13,7 +13,7 @@
#include "iface/common/future.hh" #include "iface/common/future.hh"
#include "iface/common/mutex.hh" #include "iface/common/mutex.hh"
#include "iface/common/void.hh" #include "iface/common/void.hh"
#include "iface/data/buffer.hh" #include "iface/subsys/buffer.hh"
#include "iface/subsys/logger.hh" #include "iface/subsys/logger.hh"
#include "iface/env.hh" #include "iface/env.hh"
@ -23,10 +23,10 @@ namespace nf7::core::uv {
class File : class File :
public std::enable_shared_from_this<File>, public std::enable_shared_from_this<File>,
public data::FiniteBuffer, public subsys::FiniteBuffer,
public data::ResizableBuffer, public subsys::ResizableBuffer,
public data::ReadableBuffer, public subsys::ReadableBuffer,
public data::WritableBuffer { public subsys::WritableBuffer {
private: private:
class Finite; class Finite;
class Resizable; class Resizable;
@ -34,7 +34,7 @@ class File :
class Writable; class Writable;
public: public:
using ReadResult = data::ReadableBuffer::Result; using ReadResult = subsys::ReadableBuffer::Result;
public: public:
static std::shared_ptr<File> Make( static std::shared_ptr<File> Make(
@ -69,10 +69,10 @@ class File :
Future<Void> Resize(uint64_t n) noexcept override { return Truncate(n); } Future<Void> Resize(uint64_t n) noexcept override { return Truncate(n); }
public: public:
std::shared_ptr<data::FiniteBuffer> MakeFinite(); std::shared_ptr<subsys::FiniteBuffer> MakeFinite();
std::shared_ptr<data::ResizableBuffer> MakeResizable(); std::shared_ptr<subsys::ResizableBuffer> MakeResizable();
std::shared_ptr<data::ReadableBuffer> MakeReadable(); std::shared_ptr<subsys::ReadableBuffer> MakeReadable();
std::shared_ptr<data::WritableBuffer> MakeWritable(); std::shared_ptr<subsys::WritableBuffer> MakeWritable();
private: private:
const std::shared_ptr<subsys::Logger> logger_; const std::shared_ptr<subsys::Logger> logger_;

View File

@ -27,7 +27,7 @@ Parallelism::Parallelism(Env& env)
Parallelism::Impl::Impl(Env& env) Parallelism::Impl::Impl(Env& env)
: clock_(env.Get<subsys::Clock>()), : clock_(env.Get<subsys::Clock>()),
logger_(env.GetOr<subsys::Logger>(NullLogger::instance())), logger_(env.GetOr<subsys::Logger>(NullLogger::kInstance)),
ctx_(env.Get<Context>()) { } ctx_(env.Get<Context>()) { }
void Parallelism::Impl::Consume() noexcept { void Parallelism::Impl::Consume() noexcept {

View File

@ -11,7 +11,6 @@ target_sources(nf7_iface
version.cc version.cc
PUBLIC PUBLIC
common/container.hh common/container.hh
common/dealer.hh
common/exception.hh common/exception.hh
common/future.hh common/future.hh
common/leak_detector.hh common/leak_detector.hh
@ -23,16 +22,14 @@ target_sources(nf7_iface
common/task_context.hh common/task_context.hh
common/value.hh common/value.hh
common/void.hh common/void.hh
data/buffer.hh
data/interface.hh
data/wrap.hh
subsys/concurrency.hh subsys/concurrency.hh
subsys/database.hh subsys/database.hh
subsys/dealer.hh
subsys/interface.hh subsys/interface.hh
subsys/logger.hh subsys/logger.hh
subsys/meta_env.hh
subsys/parallelism.hh subsys/parallelism.hh
env.hh env.hh
file.hh
lambda.hh lambda.hh
version.hh version.hh
) )
@ -41,7 +38,6 @@ add_executable(nf7_iface_test)
target_sources(nf7_iface_test target_sources(nf7_iface_test
PRIVATE PRIVATE
common/container_test.cc common/container_test.cc
common/dealer_test.cc
common/exception_test.cc common/exception_test.cc
common/future_test.cc common/future_test.cc
common/leak_detector_test.cc common/leak_detector_test.cc
@ -53,8 +49,6 @@ target_sources(nf7_iface_test
common/value_test.cc common/value_test.cc
subsys/logger_test.hh subsys/logger_test.hh
env_test.hh env_test.hh
lambda_test.cc
lambda_test.hh
) )
target_link_libraries(nf7_iface_test target_link_libraries(nf7_iface_test
PRIVATE PRIVATE

View File

@ -1,55 +0,0 @@
// No copyright
#pragma once
#include <string>
#include <utility>
#include "iface/common/observer.hh"
namespace nf7 {
class DealerMeta { };
template <typename T>
class Dealer {
public:
explicit Dealer(const DealerMeta& meta = {}) noexcept : meta_(meta) { }
virtual ~Dealer() = default;
Dealer(const Dealer&) = default;
Dealer(Dealer&&) = default;
Dealer& operator=(const Dealer&) = default;
Dealer& operator=(Dealer&&) = default;
const DealerMeta& meta() const noexcept { return meta_; }
private:
const DealerMeta& meta_;
};
template <typename T>
class Maker : public Dealer<T>, public Observer<T>::Target {
public:
explicit Maker(const DealerMeta& meta = {}) noexcept : Dealer<T>(meta) { }
protected:
void Emit(T&& v) noexcept { Observer<T>::Target::Notify(std::move(v)); }
};
template <typename T>
class Emitter : public Maker<T> {
public:
explicit Emitter(const DealerMeta& meta = {}) noexcept : Maker<T>(meta) { }
using Maker<T>::Emit;
};
template <typename T>
class Taker : public Dealer<T>, public Observer<T>::Target {
public:
explicit Taker(const DealerMeta& meta = {}) noexcept : Dealer<T>(meta) { }
void Take(const T& v) noexcept { Observer<T>::Target::Notify(v); }
};
} // namespace nf7

View File

@ -1,16 +0,0 @@
// No copyright
#include "iface/common/dealer.hh"
#include <gtest/gtest.h>
#include "iface/common/observer_test.hh"
TEST(Emitter, Emit) {
nf7::Emitter<int32_t> sut {};
nf7::test::ObserverMock<int32_t> obs {sut};
EXPECT_CALL(obs, NotifyWithMove(int32_t {777})).Times(1);
sut.Emit(int32_t {777});
}

View File

@ -1,23 +0,0 @@
// No copyright
#pragma once
namespace nf7::data {
class Interface {
public:
Interface() = delete;
explicit Interface(const char* name) : name_(name) { }
virtual ~Interface() = default;
Interface(const Interface&) = delete;
Interface(Interface&&) = delete;
Interface& operator=(const Interface&) = delete;
Interface& operator=(Interface&&) = delete;
const char* name() const noexcept { return name_; }
private:
const char* name_;
};
} // namespace nf7::data

View File

@ -1,11 +0,0 @@
// No copyright
#pragma once
#include "iface/common/container.hh"
#include "iface/data/interface.hh"
namespace nf7 {
using File = Container<data::Interface>;
} // namespace nf7

View File

@ -5,7 +5,6 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "iface/common/dealer.hh"
#include "iface/common/leak_detector.hh" #include "iface/common/leak_detector.hh"
#include "iface/common/exception.hh" #include "iface/common/exception.hh"
#include "iface/common/observer.hh" #include "iface/common/observer.hh"
@ -15,50 +14,13 @@ namespace nf7 {
class Lambda : private LeakDetector<Lambda> { class Lambda : private LeakDetector<Lambda> {
public: public:
Lambda() = delete; Lambda() = default;
Lambda(const std::shared_ptr<Taker<Value>>& taker,
const std::shared_ptr<Maker<Value>>& maker) noexcept
: taker_(std::move(taker)), maker_(maker) { }
virtual ~Lambda() = default; virtual ~Lambda() = default;
Lambda(const Lambda&) = delete; Lambda(const Lambda&) = delete;
Lambda(Lambda&&) = delete; Lambda(Lambda&&) = delete;
Lambda& operator=(const Lambda&) = delete; Lambda& operator=(const Lambda&) = delete;
Lambda& operator=(Lambda&&) = delete; Lambda& operator=(Lambda&&) = delete;
const std::shared_ptr<Taker<Value>>& taker() const noexcept { return taker_; }
const std::shared_ptr<Maker<Value>>& maker() const noexcept { return maker_; }
private:
const std::shared_ptr<Taker<Value>> taker_;
const std::shared_ptr<Maker<Value>> maker_;
};
class LambdaBase : public Lambda, private Observer<Value> {
public:
LambdaBase(DealerMeta&& takerMeta = {}, DealerMeta&& makerMeta = {})
try : LambdaBase(std::make_shared<Taker<Value>>(std::move(takerMeta)),
std::make_shared<Emitter<Value>>(std::move(makerMeta))) {
} catch (const std::bad_alloc&) {
throw MemoryException {};
}
private:
LambdaBase(const std::shared_ptr<Taker<Value>>& taker,
const std::shared_ptr<Emitter<Value>>& maker)
: Lambda(taker, maker), Observer<Value>(*taker), emitter_(maker) { }
protected:
virtual void Main(const Value&) noexcept = 0;
const std::shared_ptr<Emitter<Value>>& emitter() const noexcept {
return emitter_;
}
private:
void Notify(const Value& v) noexcept override { Main(v); }
const std::shared_ptr<Emitter<Value>> emitter_;
}; };
} // namespace nf7 } // namespace nf7

View File

@ -1,15 +0,0 @@
// No copyright
#include "iface/lambda.hh"
#include "iface/lambda_test.hh"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
TEST(LambdaBase, TakeAndRun) {
nf7::test::LambdaBaseMock sut;
EXPECT_CALL(sut, Main);
sut.taker()->Take(nf7::Value::Null {});
}

View File

@ -1,23 +0,0 @@
// No copyright
#pragma once
#include "iface/lambda.hh"
#include <gmock/gmock.h>
#include "iface/common/dealer.hh"
#include "iface/common/value.hh"
namespace nf7::test {
class LambdaBaseMock : public LambdaBase {
public:
using LambdaBase::LambdaBase;
MOCK_METHOD(void, Main, (const Value&), (noexcept));
using LambdaBase::emitter;
};
} // namespace nf7::test

View File

@ -6,9 +6,9 @@
#include "iface/common/future.hh" #include "iface/common/future.hh"
#include "iface/common/void.hh" #include "iface/common/void.hh"
#include "iface/data/interface.hh" #include "iface/subsys/interface.hh"
namespace nf7::data { namespace nf7::subsys {
class FiniteBuffer : public Interface { class FiniteBuffer : public Interface {
public: public:
@ -54,4 +54,5 @@ class WritableBuffer : public Interface {
} }
}; };
} // namespace nf7::data } // namespace nf7::subsys

27
iface/subsys/dealer.hh Normal file
View File

@ -0,0 +1,27 @@
// No copyright
#pragma once
#include "iface/common/observer.hh"
#include "iface/subsys/interface.hh"
namespace nf7::subsys {
template <typename T>
class Maker : public Interface, public Observer<T>::Target {
public:
using Interface::Interface;
protected:
using Observer<T>::Target::Notify;
};
template <typename T>
class Taker : public Interface {
public:
using Interface::Interface;
virtual void Take(T&&) noexcept = 0;
};
} // namespace nf7::subsys

42
iface/subsys/meta_env.hh Normal file
View File

@ -0,0 +1,42 @@
// No copyright
#pragma once
#include <cstdint>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "iface/common/exception.hh"
#include "iface/env.hh"
namespace nf7::subsys {
class MetaEnv : public Interface {
public:
using Pair = std::pair<std::string, Env&>;
public:
using Interface::Interface;
public:
virtual Env* FindOr(std::string_view) const noexcept = 0;
virtual std::optional<Pair> FindOr(uint64_t) const noexcept = 0;
virtual std::vector<Pair> FetchAll() const = 0;
public:
Env& Find(std::string_view key) const {
auto ret = FindOr(key);
return ret? *ret: throw Exception {"missing file"};
}
Pair Find(uint64_t idx) const {
auto ret = FindOr(idx);
return ret? *ret: throw Exception {"missing file"};
}
public:
virtual std::shared_ptr<MetaEnv> parent() const noexcept = 0;
};
} // namespace nf7::subsys

View File

@ -1,14 +1,14 @@
// No copyright // No copyright
#pragma once #pragma once
#include "iface/data/interface.hh" #include "iface/subsys/interface.hh"
namespace nf7::data { namespace nf7::subsys {
template <typename T> template <typename T>
class Wrap : public Interface { class Wrapper : public Interface {
protected: protected:
Wrap(const char* name, T& data) noexcept Wrapper(const char* name, T& data) noexcept
: Interface(name), data_(data) { } : Interface(name), data_(data) { }
public: public:
@ -18,4 +18,4 @@ class Wrap : public Interface {
T& data_; T& data_;
}; };
} // namespace nf7::data } // namespace nf7::subsys