mirror of
https://github.com/enduro2d/enduro2d.git
synced 2026-01-05 01:51:02 +07:00
Merge pull request #3 from enduro2d/feature/module
simple module holder class
This commit is contained in:
@@ -14,6 +14,7 @@
|
|||||||
#include "filesystem.hpp"
|
#include "filesystem.hpp"
|
||||||
#include "image.hpp"
|
#include "image.hpp"
|
||||||
#include "jobber.hpp"
|
#include "jobber.hpp"
|
||||||
|
#include "module.hpp"
|
||||||
#include "path.hpp"
|
#include "path.hpp"
|
||||||
#include "streams.hpp"
|
#include "streams.hpp"
|
||||||
#include "strfmts.hpp"
|
#include "strfmts.hpp"
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ namespace e2d
|
|||||||
class input_stream;
|
class input_stream;
|
||||||
class output_stream;
|
class output_stream;
|
||||||
class url;
|
class url;
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
class module;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace e2d
|
namespace e2d
|
||||||
|
|||||||
88
headers/enduro2d/utils/module.hpp
Normal file
88
headers/enduro2d/utils/module.hpp
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "Enduro2D"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2018 Matvey Cherevko
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "_utils.hpp"
|
||||||
|
|
||||||
|
namespace e2d
|
||||||
|
{
|
||||||
|
class module_not_initialized final : public exception {
|
||||||
|
public:
|
||||||
|
const char* what() const noexcept final {
|
||||||
|
return "module not initialized";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class module_already_initialized final : public exception {
|
||||||
|
public:
|
||||||
|
const char* what() const noexcept final {
|
||||||
|
return "module already initialized";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename BaseT >
|
||||||
|
class module : private noncopyable {
|
||||||
|
public:
|
||||||
|
using base_type = BaseT;
|
||||||
|
virtual ~module() noexcept = default;
|
||||||
|
public:
|
||||||
|
template < typename ImplT, typename... Args >
|
||||||
|
static void initialize(Args&&... args) {
|
||||||
|
if ( is_initialized() ) {
|
||||||
|
throw module_already_initialized();
|
||||||
|
}
|
||||||
|
instance_ = std::make_unique<ImplT>(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void shutdown() noexcept {
|
||||||
|
instance_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_initialized() noexcept {
|
||||||
|
return !!instance_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BaseT& instance() {
|
||||||
|
if ( !is_initialized() ) {
|
||||||
|
throw module_not_initialized();
|
||||||
|
}
|
||||||
|
return *instance_;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
static std::unique_ptr<BaseT> instance_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename BaseT >
|
||||||
|
std::unique_ptr<BaseT> module<BaseT>::instance_;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace e2d { namespace modules
|
||||||
|
{
|
||||||
|
template < typename ImplT, typename... Args >
|
||||||
|
void initialize(Args&&... args) {
|
||||||
|
using BaseT = typename ImplT::base_type;
|
||||||
|
module<BaseT>::template initialize<ImplT>(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename ImplT >
|
||||||
|
void shutdown() noexcept {
|
||||||
|
using BaseT = typename ImplT::base_type;
|
||||||
|
module<BaseT>::shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename ImplT >
|
||||||
|
bool is_initialized() noexcept {
|
||||||
|
using BaseT = typename ImplT::base_type;
|
||||||
|
return module<BaseT>::is_initialized();
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename ImplT >
|
||||||
|
ImplT& instance() {
|
||||||
|
using BaseT = typename ImplT::base_type;
|
||||||
|
return static_cast<ImplT&>(module<BaseT>::instance());
|
||||||
|
}
|
||||||
|
}}
|
||||||
95
untests/sources/untests_utils/module.cpp
Normal file
95
untests/sources/untests_utils/module.cpp
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "Enduro2D"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2018 Matvey Cherevko
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "_utils.hpp"
|
||||||
|
using namespace e2d;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
using namespace e2d;
|
||||||
|
|
||||||
|
class mul_module : public module<mul_module> {
|
||||||
|
public:
|
||||||
|
virtual u32 act(u32 v) const noexcept = 0;
|
||||||
|
virtual u32 multiplier() const noexcept = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class mul_module_impl : public mul_module {
|
||||||
|
public:
|
||||||
|
mul_module_impl(u32 m) : m_(m) {}
|
||||||
|
u32 act(u32 v) const noexcept { return v * m_; }
|
||||||
|
u32 multiplier() const noexcept { return m_; }
|
||||||
|
void multiplier(u32 v) noexcept { m_ = v; }
|
||||||
|
private:
|
||||||
|
u32 m_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("module") {
|
||||||
|
{
|
||||||
|
REQUIRE_FALSE(module<mul_module>::is_initialized());
|
||||||
|
REQUIRE_FALSE(module<mul_module_impl>::is_initialized());
|
||||||
|
|
||||||
|
REQUIRE_THROWS_AS(module<mul_module>::instance(), module_not_initialized);
|
||||||
|
REQUIRE_THROWS_AS(module<mul_module_impl>::instance(), module_not_initialized);
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW(module<mul_module>::initialize<mul_module_impl>(2));
|
||||||
|
REQUIRE_THROWS_AS(module<mul_module>::initialize<mul_module_impl>(1), module_already_initialized);
|
||||||
|
|
||||||
|
REQUIRE(module<mul_module>::is_initialized());
|
||||||
|
REQUIRE_FALSE(module<mul_module_impl>::is_initialized());
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW(module<mul_module>::instance());
|
||||||
|
REQUIRE_THROWS_AS(module<mul_module_impl>::instance(), module_not_initialized);
|
||||||
|
|
||||||
|
REQUIRE(module<mul_module>::instance().act(10) == 20);
|
||||||
|
REQUIRE(module<mul_module>::instance().multiplier() == 2);
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW(module<mul_module>::shutdown());
|
||||||
|
|
||||||
|
REQUIRE_FALSE(module<mul_module>::is_initialized());
|
||||||
|
REQUIRE_FALSE(module<mul_module_impl>::is_initialized());
|
||||||
|
|
||||||
|
REQUIRE_THROWS_AS(module<mul_module>::instance(), module_not_initialized);
|
||||||
|
REQUIRE_THROWS_AS(module<mul_module_impl>::instance(), module_not_initialized);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
REQUIRE_FALSE(modules::is_initialized<mul_module>());
|
||||||
|
REQUIRE_FALSE(modules::is_initialized<mul_module_impl>());
|
||||||
|
|
||||||
|
REQUIRE_THROWS_AS(modules::instance<mul_module>(), module_not_initialized);
|
||||||
|
REQUIRE_THROWS_AS(modules::instance<mul_module_impl>(), module_not_initialized);
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW(modules::initialize<mul_module_impl>(3));
|
||||||
|
|
||||||
|
REQUIRE(modules::is_initialized<mul_module>());
|
||||||
|
REQUIRE(modules::is_initialized<mul_module_impl>());
|
||||||
|
REQUIRE_NOTHROW(modules::instance<mul_module>());
|
||||||
|
REQUIRE_NOTHROW(modules::instance<mul_module_impl>());
|
||||||
|
|
||||||
|
REQUIRE(modules::instance<mul_module>().act(10) == 30);
|
||||||
|
REQUIRE(modules::instance<mul_module_impl>().act(20) == 60);
|
||||||
|
|
||||||
|
REQUIRE(modules::instance<mul_module>().multiplier() == 3);
|
||||||
|
REQUIRE(modules::instance<mul_module_impl>().multiplier() == 3);
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW(modules::instance<mul_module_impl>().multiplier(5));
|
||||||
|
|
||||||
|
REQUIRE(modules::instance<mul_module>().act(10) == 50);
|
||||||
|
REQUIRE(modules::instance<mul_module_impl>().act(20) == 100);
|
||||||
|
|
||||||
|
REQUIRE(modules::instance<mul_module>().multiplier() == 5);
|
||||||
|
REQUIRE(modules::instance<mul_module_impl>().multiplier() == 5);
|
||||||
|
|
||||||
|
REQUIRE_NOTHROW(modules::shutdown<mul_module_impl>());
|
||||||
|
|
||||||
|
REQUIRE_FALSE(modules::is_initialized<mul_module>());
|
||||||
|
REQUIRE_FALSE(modules::is_initialized<mul_module_impl>());
|
||||||
|
|
||||||
|
REQUIRE_THROWS_AS(modules::instance<mul_module>(), module_not_initialized);
|
||||||
|
REQUIRE_THROWS_AS(modules::instance<mul_module_impl>(), module_not_initialized);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user