Merge pull request 'feat/75-setup-env' (#79) from feat/75-setup-env into main
Reviewed-on: #79
This commit is contained in:
commit
99379b19f9
@ -2,12 +2,44 @@ cmake_minimum_required(VERSION 3.20)
|
|||||||
project(nf7 C CXX)
|
project(nf7 C CXX)
|
||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
|
|
||||||
|
option(SANITIZER "ADDRESS or THREAD" "THREAD")
|
||||||
|
|
||||||
|
# all targets should link to this to use common compile options
|
||||||
|
add_library(nf7_config INTERFACE EXCLUDE_FROM_ALL)
|
||||||
|
target_compile_options(nf7_config INTERFACE
|
||||||
|
$<$<CXX_COMPILER_ID:MSVC>:
|
||||||
|
/W4
|
||||||
|
$<$<CONFIG:Debug>:/WX>
|
||||||
|
>
|
||||||
|
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:
|
||||||
|
-Wall -Wextra -Wpedantic
|
||||||
|
$<$<CONFIG:Debug>:-Werror>
|
||||||
|
$<$<STREQUAL:${SANITIZER},ADDRESS>:-fsanitize=address,leak,undefined>
|
||||||
|
$<$<STREQUAL:${SANITIZER},THREAD>:-fsanitize=thread,undefined>
|
||||||
|
>
|
||||||
|
)
|
||||||
|
target_link_options(nf7_config INTERFACE
|
||||||
|
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:
|
||||||
|
$<$<STREQUAL:${SANITIZER},ADDRESS>:-fsanitize=address,leak,undefined>
|
||||||
|
$<$<STREQUAL:${SANITIZER},THREAD>:-fsanitize=thread,undefined>
|
||||||
|
>
|
||||||
|
)
|
||||||
|
|
||||||
|
# include thirdparty libs and external scripts
|
||||||
|
add_subdirectory(thirdparty EXCLUDE_FROM_ALL)
|
||||||
include(cmake/git_hash.cmake)
|
include(cmake/git_hash.cmake)
|
||||||
|
|
||||||
|
# add main targets
|
||||||
add_subdirectory(iface)
|
add_subdirectory(iface)
|
||||||
add_subdirectory(core)
|
add_subdirectory(core)
|
||||||
|
|
||||||
add_executable(nf7)
|
add_executable(nf7)
|
||||||
target_sources(nf7 PRIVATE main.cc)
|
target_sources(nf7 PRIVATE main.cc)
|
||||||
target_link_libraries(nf7 PRIVATE nf7_iface nf7_core)
|
target_link_libraries(nf7
|
||||||
|
PRIVATE
|
||||||
|
nf7_config
|
||||||
|
nf7_iface
|
||||||
|
nf7_core
|
||||||
|
)
|
||||||
|
10
Dockerfile
10
Dockerfile
@ -1,10 +1,12 @@
|
|||||||
FROM alpine:3.14
|
FROM debian:unstable-slim
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
RUN apt update && apt install -y --no-install-recommends \
|
||||||
|
ca-certificates \
|
||||||
cmake \
|
cmake \
|
||||||
gdb \
|
gdb \
|
||||||
git \
|
git \
|
||||||
g++ \
|
g++-13 \
|
||||||
make
|
make \
|
||||||
|
&& apt -y clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
WORKDIR /repo
|
WORKDIR /repo
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
add_library(nf7_core)
|
add_library(nf7_core)
|
||||||
target_link_libraries(nf7_core PRIVATE git_hash nf7_iface)
|
target_link_libraries(nf7_core
|
||||||
|
PRIVATE
|
||||||
|
git_hash
|
||||||
|
nf7_config
|
||||||
|
nf7_iface
|
||||||
|
)
|
||||||
target_sources(nf7_core
|
target_sources(nf7_core
|
||||||
PRIVATE
|
PRIVATE
|
||||||
version.cc
|
version.cc
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
add_library(nf7_iface)
|
add_library(nf7_iface)
|
||||||
target_include_directories(nf7_iface PUBLIC ${PROJECT_SOURCE_DIR})
|
target_include_directories(nf7_iface PUBLIC ${PROJECT_SOURCE_DIR})
|
||||||
target_link_libraries(nf7_iface PRIVATE git_hash)
|
target_link_libraries(nf7_iface
|
||||||
|
PRIVATE
|
||||||
|
git_hash
|
||||||
|
nf7_config
|
||||||
|
)
|
||||||
target_sources(nf7_iface
|
target_sources(nf7_iface
|
||||||
PRIVATE
|
PRIVATE
|
||||||
version.cc
|
version.cc
|
||||||
|
25
iface/exception.hh
Normal file
25
iface/exception.hh
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// No copyright
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
#include <source_location>
|
||||||
|
|
||||||
|
namespace nf7::iface {
|
||||||
|
|
||||||
|
class Exception : public std::exception, std::nested_exception {
|
||||||
|
public:
|
||||||
|
Exception() = delete;
|
||||||
|
explicit Exception(
|
||||||
|
const char* what,
|
||||||
|
std::source_location location = std::source_location::current()) :
|
||||||
|
what_(what), location_(location) { }
|
||||||
|
|
||||||
|
const char* what() const noexcept override { return what_; }
|
||||||
|
const std::source_location& location() const noexcept { return location_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* what_;
|
||||||
|
std::source_location location_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace nf7::iface
|
163
iface/future.hh
Normal file
163
iface/future.hh
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
// No copyright
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <utility>
|
||||||
|
#include <variant>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "iface/exception.hh"
|
||||||
|
|
||||||
|
namespace nf7 {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class InternalFuture final :
|
||||||
|
public std::enable_shared_from_this<InternalFuture<T>> {
|
||||||
|
public:
|
||||||
|
using Listener =
|
||||||
|
std::function<void(std::shared_ptr<InternalFuture<T>>&&) noexcept>;
|
||||||
|
|
||||||
|
InternalFuture() = default;
|
||||||
|
InternalFuture(T&& v) noexcept : result_(std::move(v)) { }
|
||||||
|
explicitInternalFuture(std::exception_ptr e) noexcept : result_(e) { }
|
||||||
|
|
||||||
|
void Complete(T&& v) noexcept {
|
||||||
|
assert(yet());
|
||||||
|
result_ = std::move(v);
|
||||||
|
Finalize();
|
||||||
|
}
|
||||||
|
void Throw(std::exception_ptr e = std::current_exception()) noexcept {
|
||||||
|
assert(yet());
|
||||||
|
result_ = e;
|
||||||
|
Finalize();
|
||||||
|
}
|
||||||
|
void Listen(Listener&& listener) {
|
||||||
|
if (yet()) {
|
||||||
|
try {
|
||||||
|
listeners_.push_back(std::move(listener));
|
||||||
|
} catch (const std::exception&) {
|
||||||
|
throw Exception("memory shortage");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
listener(shared_from_this());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ref() noexcept {
|
||||||
|
++refcnt_;
|
||||||
|
}
|
||||||
|
void Unref() noexcept {
|
||||||
|
--refcnt_;
|
||||||
|
if (0 == refcnt_ && yet()) {
|
||||||
|
Throw(std::make_exception_ptr(Exception("future is forgotten")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool yet() const noexcept {
|
||||||
|
return std::nullopt == result_;
|
||||||
|
}
|
||||||
|
bool done() const noexcept {
|
||||||
|
return !yet() && std::holds_alternative<T>(*result_);
|
||||||
|
}
|
||||||
|
bool error() const noexcept {
|
||||||
|
return !yet() && std::holds_alternative<std::exception_ptr>(*result_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Finalize() noexcept {
|
||||||
|
for (const auto& listener : listeners_) {
|
||||||
|
listener(shared_from_this());
|
||||||
|
}
|
||||||
|
listeners_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::variant<T, std::exception_ptr>> result_;
|
||||||
|
|
||||||
|
std::vector<Listener> listeners_;
|
||||||
|
|
||||||
|
uint32_t refcnt_ = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Future final {
|
||||||
|
public:
|
||||||
|
class Completer;
|
||||||
|
|
||||||
|
Future() = delete;
|
||||||
|
Future(std::shared_ptr<InternalFuture>&& in) noexcept
|
||||||
|
: internal_(std::move(in));
|
||||||
|
|
||||||
|
void Listen(std::function<void(const Future<T>&)>&& listener) {
|
||||||
|
internal().Listen(std::move(listener));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool yet() const noexcept { return internal().yet(); }
|
||||||
|
bool done() const noexcept { return internal().done(); }
|
||||||
|
bool error() const noexcept { return internal().error(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
InternalFuture& internal() noexcept {
|
||||||
|
struct Visitor {
|
||||||
|
InternalFuture& operator(InernalFuture& i) noexcept {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
InternalFuture& operator(std::shared_ptr<InternalFuture>& i) noexcept {
|
||||||
|
return *i;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return std::visit(InternalGetter(), internal_);
|
||||||
|
}
|
||||||
|
const InternalFuture& internal() const noexcept {
|
||||||
|
struct Visitor {
|
||||||
|
const InternalFuture& operator(const InernalFuture& i) noexcept {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
const InternalFuture& operator(
|
||||||
|
const std::shared_ptr<InternalFuture>& i) noexcept {
|
||||||
|
return *i;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return std::visit(InternalGetter(), internal_);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::variant<InternalFuture, std::shared_ptr<InternalFuture>> internal_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Future<T>::Completer final {
|
||||||
|
public:
|
||||||
|
Completer() : Completer(std::make_shared<InternalFuture>())
|
||||||
|
try {
|
||||||
|
} catch (const std::exception&) {
|
||||||
|
throw Exception("memory shortage");
|
||||||
|
}
|
||||||
|
explicit Completer(std::shared_ptr<InternalFuture>&& internal) noexcept
|
||||||
|
: internal_(std::move(internal)) {
|
||||||
|
internal_->Ref();
|
||||||
|
}
|
||||||
|
~Completer() noexcept {
|
||||||
|
if (nullptr != internal_) {
|
||||||
|
internal_->Unref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Completer(const Completer&) = default;
|
||||||
|
Completer(Completer&&) = default;
|
||||||
|
Completer& operator=(const Completer&) = default;
|
||||||
|
Completer& operator=(Completer&&) = default;
|
||||||
|
|
||||||
|
void Complete(T&& v) noexcept {
|
||||||
|
internal_->Complete(std::move(v));
|
||||||
|
}
|
||||||
|
void Throw(std::exception_ptr e = std::current_exception()) noexcept {
|
||||||
|
internal_->Throw(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<InternalFuture> internal_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace nf7
|
10
thirdparty/CMakeLists.txt
vendored
Normal file
10
thirdparty/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
# ---- gtest (BSD-3-Clause)
|
||||||
|
FetchContent_Declare(
|
||||||
|
googletest
|
||||||
|
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||||
|
GIT_TAG v1.13.0
|
||||||
|
)
|
||||||
|
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||||
|
FetchContent_MakeAvailable(googletest)
|
Loading…
x
Reference in New Issue
Block a user