Initial Release

This commit is contained in:
CJ van den Berg 2024-02-08 22:23:40 +01:00
commit 5a00e06cb9
81 changed files with 12670 additions and 0 deletions

66
src/c/context.cpp Normal file
View file

@ -0,0 +1,66 @@
#include "thespian/env.hpp"
#include <__type_traits/is_swappable.h>
#include <thespian/c/context.h>
#include <thespian/c/handle.h>
#include <thespian/context.hpp>
#include <thespian/handle.hpp>
using std::string_view;
using thespian::context;
thread_local const char *last_error{}; // NOLINT
extern "C" {
auto thespian_get_last_error() -> const char * { return last_error; }
void thespian_set_last_error(const char *msg) { last_error = msg; }
thespian_context
thespian_context_create(thespian_context_destroy *d) { // NOLINT
return reinterpret_cast<thespian_context>( // NOLINT
context::create(reinterpret_cast<context::dtor *>(d))); // NOLINT
}
void thespian_context_run(thespian_context ctx) {
reinterpret_cast<context *>(ctx)->run(); // NOLINT
}
void thespian_context_on_last_exit(thespian_context ctx,
thespian_last_exit_handler h) {
reinterpret_cast<context *>(ctx)->on_last_exit(h); // NOLINT
}
auto thespian_context_spawn_link(thespian_context ctx_, thespian_behaviour b,
thespian_behaviour_state s,
thespian_exit_handler eh,
thespian_exit_handler_state es,
const char *name, thespian_env env,
thespian_handle *handle) -> int {
auto *ctx = reinterpret_cast<context *>(ctx_); // NOLINT
thespian::env_t empty_env_{};
thespian::env_t &env_ =
env ? *reinterpret_cast<thespian::env_t *>(env) : empty_env_; // NOLINT
auto ret = ctx->spawn_link(
[b, s]() -> thespian::result {
auto *ret = b(s);
if (ret) {
auto err = cbor::buffer();
const uint8_t *data = ret->base; // NOLINT
std::copy(data, data + ret->len, back_inserter(err)); // NOLINT
return thespian::to_error(err);
}
return thespian::ok();
},
[eh, es](auto e) {
if (eh)
eh(es, e.data(), e.size());
},
string_view(name), std::move(env_));
if (!ret)
return -1;
*handle = reinterpret_cast<thespian_handle>( // NOLINT
new thespian::handle{ret.value()});
return 0;
}
}

92
src/c/env.cpp Normal file
View file

@ -0,0 +1,92 @@
#include <cbor/cbor.hpp>
#include <thespian/c/env.h>
#include <thespian/c/handle.h>
#include <thespian/env.hpp>
#include <thespian/trace.hpp>
#include <cassert>
namespace {
auto to_env(thespian_env e) -> thespian::env_t & {
assert(e);
return *reinterpret_cast<thespian::env_t *>(e); // NOLINT
}
auto destroy(thespian_env e) -> void {
delete reinterpret_cast<thespian::env_t *>(e); // NOLINT
}
} // namespace
extern "C" {
void thespian_env_enable_all_channels(thespian_env e) {
to_env(e).enable_all_channels();
}
void thespian_env_disable_all_channels(thespian_env e) {
to_env(e).disable_all_channels();
}
void thespian_env_enable(thespian_env e, thespian_trace_channel c) {
to_env(e).enable(static_cast<thespian::channel>(c));
}
void thespian_env_disable(thespian_env e, thespian_trace_channel c) {
to_env(e).disable(static_cast<thespian::channel>(c));
}
auto thespian_env_enabled(thespian_env e, thespian_trace_channel c) -> bool {
return to_env(e).enabled(static_cast<thespian::channel>(c));
}
void thespian_env_on_trace(thespian_env e, thespian_trace_handler h) {
to_env(e).on_trace([h](const cbor::buffer &m) { h({m.data(), m.size()}); });
}
void thespian_env_trace(thespian_env e, cbor_buffer m) {
cbor::buffer buf;
const uint8_t *data = m.base;
std::copy(data, data + m.len, back_inserter(buf)); // NOLINT
to_env(e).trace(buf);
}
auto thespian_env_is(thespian_env e, c_string_view key) -> bool {
return to_env(e).is({key.base, key.len});
}
void thespian_env_set(thespian_env e, c_string_view key, bool value) {
to_env(e).is({key.base, key.len}) = value;
}
auto thespian_env_num(thespian_env e, c_string_view key) -> int64_t {
return to_env(e).num({key.base, key.len});
}
void thespian_env_num_set(thespian_env e, c_string_view key, int64_t value) {
to_env(e).num({key.base, key.len}) = value;
}
auto thespian_env_str(thespian_env e, c_string_view key) -> c_string_view {
auto &ret = to_env(e).str({key.base, key.len});
return {ret.data(), ret.size()};
}
void thespian_env_str_set(thespian_env e, c_string_view key,
c_string_view value) {
to_env(e).str({key.base, key.len}) = std::string_view{value.base, value.len};
}
auto thespian_env_proc(thespian_env e, c_string_view key) -> thespian_handle {
auto &ret = to_env(e).proc({key.base, key.len});
return reinterpret_cast<thespian_handle>(&ret); // NOLINT
}
void thespian_env_proc_set(thespian_env e, c_string_view key,
thespian_handle value) {
thespian::handle *h{reinterpret_cast<thespian::handle *>( // NOLINT
value)};
to_env(e).proc({key.base, key.len}) = *h;
}
auto thespian_env_clone(thespian_env e) -> thespian_env {
return reinterpret_cast<thespian_env>( // NOLINT
new thespian::env_t{to_env(e)});
}
void thespian_env_destroy(thespian_env e) { destroy(e); }
auto thespian_env_get() -> thespian_env {
return reinterpret_cast<thespian_env>(&thespian::env()); // NOLINT
}
auto thespian_env_new() -> thespian_env {
return reinterpret_cast<thespian_env>(new thespian::env_t); // NOLINT
}
}

76
src/c/file_descriptor.cpp Normal file
View file

@ -0,0 +1,76 @@
#include <thespian/c/context.h>
#include <thespian/c/file_descriptor.h>
#include <thespian/file_descriptor.hpp>
using thespian::file_descriptor;
using thespian::file_descriptor_impl;
using thespian::file_descriptor_ref;
// NOLINTBEGIN(*-reinterpret-cast, *-use-trailing-*)
extern "C" {
auto thespian_file_descriptor_create(const char *tag, int fd)
-> thespian_file_descriptor_handle * {
try {
auto *p = file_descriptor::create(tag, fd).ref.release();
return reinterpret_cast<thespian_file_descriptor_handle *>(p);
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
return nullptr;
} catch (...) {
thespian_set_last_error("unknown thespian_file_descriptor_create error");
return nullptr;
}
}
int thespian_file_descriptor_wait_write(thespian_file_descriptor_handle *p) {
try {
file_descriptor::wait_write(reinterpret_cast<file_descriptor_impl *>(p));
return 0;
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
return -1;
} catch (...) {
thespian_set_last_error(
"unknown thespian_file_descriptor_wait_write error");
return -1;
}
}
int thespian_file_descriptor_wait_read(thespian_file_descriptor_handle *p) {
try {
file_descriptor::wait_read(reinterpret_cast<file_descriptor_impl *>(p));
return 0;
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
return -1;
} catch (...) {
thespian_set_last_error("unknown thespian_file_descriptor_wait_read error");
return -1;
}
}
int thespian_file_descriptor_cancel(thespian_file_descriptor_handle *p) {
try {
file_descriptor::cancel(reinterpret_cast<file_descriptor_impl *>(p));
return 0;
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
return -1;
} catch (...) {
thespian_set_last_error("unknown thespian_file_descriptor_wait_read error");
return -1;
}
}
void thespian_file_descriptor_destroy(thespian_file_descriptor_handle *p) {
try {
file_descriptor::destroy(reinterpret_cast<file_descriptor_impl *>(p));
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
} catch (...) {
thespian_set_last_error("unknown thespian_file_descriptor_destroy error");
}
}
}
// NOLINTEND(*-reinterpret-cast, *-use-trailing-*)

70
src/c/handle.cpp Normal file
View file

@ -0,0 +1,70 @@
#include <thespian/c/handle.h>
#include <thespian/handle.hpp>
#include <thespian/instance.hpp>
namespace {
static thread_local cbor::buffer
message_buffer; // NOLINT(*-avoid-non-const-global-variables)
static thread_local thespian_error
error_buffer; // NOLINT(*-avoid-non-const-global-variables)
auto to_thespian_result(thespian::result r) -> thespian_result {
if (r) {
return nullptr;
}
message_buffer = r.error();
error_buffer.base = message_buffer.data();
error_buffer.len = message_buffer.size();
return &error_buffer;
}
} // namespace
extern "C" {
auto thespian_handle_clone(thespian_handle h) -> thespian_handle {
thespian::handle *h_{
reinterpret_cast<thespian::handle *>( // NOLINT(*-reinterpret-cast)
h)};
if (!h_)
return nullptr;
return reinterpret_cast<thespian_handle>( // NOLINT(*-reinterpret-cast)
new thespian::handle{*h_});
}
void thespian_handle_destroy(thespian_handle h) {
thespian::handle *h_{
reinterpret_cast<thespian::handle *>( // NOLINT(*-reinterpret-cast)
h)};
delete h_;
}
auto thespian_handle_send_raw(thespian_handle h, cbor_buffer m)
-> thespian_result {
thespian::handle *h_{
reinterpret_cast<thespian::handle *>( // NOLINT(*-reinterpret-cast)
h)};
cbor::buffer buf;
const uint8_t *data = m.base;
std::copy(data, data + m.len, // NOLINT(*-pointer-arithmetic)
back_inserter(buf));
return to_thespian_result(h_->send_raw(move(buf)));
}
auto thespian_handle_send_exit(thespian_handle h, c_string_view err)
-> thespian_result {
thespian::handle *h_{
reinterpret_cast<thespian::handle *>( // NOLINT(*-reinterpret-cast)
h)};
return to_thespian_result(h_->exit(std::string(err.base, err.len)));
}
auto thespian_handle_is_expired(thespian_handle h) -> bool {
thespian::handle *h_{
reinterpret_cast<thespian::handle *>( // NOLINT(*-reinterpret-cast)
h)};
return h_->expired();
}
}

65
src/c/instance.cpp Normal file
View file

@ -0,0 +1,65 @@
#include "cbor/c/cbor.h"
#include "thespian/c/handle.h"
#include <thespian/c/instance.h>
#include <thespian/instance.hpp>
using std::string_view;
extern "C" {
void thespian_receive(thespian_receiver r, thespian_behaviour_state s) {
thespian::receive([r, s](auto from, cbor::buffer msg) -> thespian::result {
thespian_handle from_handle = reinterpret_cast<thespian_handle>( // NOLINT
&from);
auto *ret = r(s, from_handle, {msg.data(), msg.size()});
if (ret) {
auto err = cbor::buffer();
const uint8_t *data = ret->base;
std::copy(data, data + ret->len, back_inserter(err)); // NOLINT
return thespian::to_error(err);
}
return thespian::ok();
});
}
auto thespian_get_trap() -> bool { return thespian::trap(); }
auto thespian_set_trap(bool on) -> bool { return thespian::trap(on); }
void thespian_link(thespian_handle h) {
thespian::handle *h_{
reinterpret_cast<thespian::handle *>( // NOLINT(*-reinterpret-cast)
h)};
thespian::link(*h_);
}
auto thespian_self() -> thespian_handle {
auto &self = thespian::self_ref();
return reinterpret_cast<thespian_handle>(&self); // NOLINT(*-reinterpret-cast)
}
auto thespian_spawn_link(thespian_behaviour b, thespian_behaviour_state s,
const char *name, thespian_env env,
thespian_handle *handle) -> int {
thespian::env_t empty_env_{};
thespian::env_t env_ =
env ? *reinterpret_cast<thespian::env_t *>(env) : empty_env_; // NOLINT
auto ret = spawn_link(
[b, s]() -> thespian::result {
auto *ret = b(s);
if (ret) {
auto err = cbor::buffer();
const uint8_t *data = ret->base; // NOLINT
std::copy(data, data + ret->len, back_inserter(err)); // NOLINT
return thespian::to_error(err);
}
return thespian::ok();
},
string_view(name), std::move(env_));
if (!ret)
return -1;
*handle = reinterpret_cast<thespian_handle>( // NOLINT
new thespian::handle{ret.value()});
return 0;
}
}

76
src/c/metronome.cpp Normal file
View file

@ -0,0 +1,76 @@
#include <thespian/c/context.h>
#include <thespian/c/metronome.h>
#include <thespian/metronome.hpp>
#include <chrono>
using std::chrono::microseconds;
using std::chrono::milliseconds;
using thespian::destroy_metronome;
using thespian::metronome_impl;
using thespian::metronome_ref;
using thespian::start_metronome;
using thespian::stop_metronome;
extern "C" {
auto thespian_metronome_create_ms(unsigned long ms)
-> thespian_metronome_handle * {
try {
auto *handle = thespian::create_metronome(milliseconds(ms)).ref.release();
return reinterpret_cast<thespian_metronome_handle *>(handle); // NOLINT
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
return nullptr;
} catch (...) {
thespian_set_last_error("unknown thespian_metronome_create_ms error");
return nullptr;
}
}
auto thespian_metronome_create_us(unsigned long us)
-> thespian_metronome_handle * {
try {
auto *handle = thespian::create_metronome(microseconds(us)).ref.release();
return reinterpret_cast<thespian_metronome_handle *>(handle); // NOLINT
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
return nullptr;
} catch (...) {
thespian_set_last_error("unknown thespian_metronome_create_us error");
return nullptr;
}
}
auto thespian_metronome_start(thespian_metronome_handle *handle) -> int {
try {
start_metronome(reinterpret_cast<metronome_impl *>(handle)); // NOLINT
return 0;
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
return -1;
} catch (...) {
thespian_set_last_error("unknown thespian_metronome_start error");
return -1;
}
}
auto thespian_metronome_stop(thespian_metronome_handle *handle) -> int {
try {
stop_metronome(reinterpret_cast<metronome_impl *>(handle)); // NOLINT
return 0;
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
return -1;
} catch (...) {
thespian_set_last_error("unknown thespian_metronome_stop error");
return -1;
}
}
void thespian_metronome_destroy(thespian_metronome_handle *handle) {
try {
destroy_metronome(reinterpret_cast<metronome_impl *>(handle)); // NOLINT
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
} catch (...) {
thespian_set_last_error("unknown thespian_metronome_destroy error");
}
}
}

50
src/c/signal.cpp Normal file
View file

@ -0,0 +1,50 @@
#include <thespian/c/context.h>
#include <thespian/c/signal.h>
#include <thespian/signal.hpp>
using thespian::cancel_signal;
using thespian::destroy_signal;
using thespian::signal_impl;
using thespian::signal_ref;
extern "C" {
auto thespian_signal_create(int signum, cbor_buffer m)
-> thespian_signal_handle * {
try {
cbor::buffer buf;
const uint8_t *data = m.base;
std::copy(data, data + m.len, // NOLINT(*-pointer-arithmetic)
back_inserter(buf));
auto *handle = thespian::create_signal(signum, move(buf)).ref.release();
return reinterpret_cast<thespian_signal_handle *>(handle); // NOLINT
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
return nullptr;
} catch (...) {
thespian_set_last_error("unknown thespian_signal_create error");
return nullptr;
}
}
auto thespian_signal_cancel(thespian_signal_handle *handle) -> int {
try {
cancel_signal(reinterpret_cast<signal_impl *>(handle)); // NOLINT
return 0;
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
return -1;
} catch (...) {
thespian_set_last_error("unknown thespian_signal_start error");
return -1;
}
}
void thespian_signal_destroy(thespian_signal_handle *handle) {
try {
destroy_signal(reinterpret_cast<signal_impl *>(handle)); // NOLINT
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
} catch (...) {
thespian_set_last_error("unknown thespian_signal_destroy error");
}
}
}

73
src/c/timeout.cpp Normal file
View file

@ -0,0 +1,73 @@
#include <thespian/c/context.h>
#include <thespian/c/timeout.h>
#include <thespian/timeout.hpp>
#include <chrono>
using std::chrono::microseconds;
using std::chrono::milliseconds;
using thespian::cancel_timeout;
using thespian::destroy_timeout;
using thespian::timeout_impl;
using thespian::timeout_ref;
extern "C" {
auto thespian_timeout_create_ms(unsigned long ms, cbor_buffer m)
-> thespian_timeout_handle * {
try {
cbor::buffer buf;
const uint8_t *data = m.base;
std::copy(data, data + m.len, // NOLINT(*-pointer-arithmetic)
back_inserter(buf));
auto *handle =
thespian::create_timeout(milliseconds(ms), move(buf)).ref.release();
return reinterpret_cast<thespian_timeout_handle *>(handle); // NOLINT
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
return nullptr;
} catch (...) {
thespian_set_last_error("unknown thespian_timeout_create_ms error");
return nullptr;
}
}
auto thespian_timeout_create_us(unsigned long us, cbor_buffer m)
-> thespian_timeout_handle * {
try {
cbor::buffer buf;
const uint8_t *data = m.base;
std::copy(data, data + m.len, // NOLINT(*-pointer-arithmetic)
back_inserter(buf));
auto *handle =
thespian::create_timeout(microseconds(us), move(buf)).ref.release();
return reinterpret_cast<thespian_timeout_handle *>(handle); // NOLINT
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
return nullptr;
} catch (...) {
thespian_set_last_error("unknown thespian_timeout_create_us error");
return nullptr;
}
}
auto thespian_timeout_cancel(thespian_timeout_handle *handle) -> int {
try {
cancel_timeout(reinterpret_cast<timeout_impl *>(handle)); // NOLINT
return 0;
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
return -1;
} catch (...) {
thespian_set_last_error("unknown thespian_timeout_start error");
return -1;
}
}
void thespian_timeout_destroy(thespian_timeout_handle *handle) {
try {
destroy_timeout(reinterpret_cast<timeout_impl *>(handle)); // NOLINT
} catch (const std::exception &e) {
thespian_set_last_error(e.what());
} catch (...) {
thespian_set_last_error("unknown thespian_timeout_destroy error");
}
}
}

25
src/c/trace.cpp Normal file
View file

@ -0,0 +1,25 @@
#include <thespian/c/trace.h>
#include <thespian/trace.hpp>
extern "C" {
void thespian_on_trace(thespian_trace_handler h) {
thespian::on_trace([h](const cbor::buffer &m) { h({m.data(), m.size()}); });
}
void thespian_trace_to_json_file(const char *file_name) {
thespian::trace_to_json_file(file_name);
}
void thespian_trace_to_cbor_file(const char *file_name) {
thespian::trace_to_cbor_file(file_name);
}
void thespian_trace_to_mermaid_file(const char *file_name) {
thespian::trace_to_mermaid_file(file_name);
}
void thespian_trace_to_trace(thespian_trace_channel default_channel) {
thespian::trace_to_trace(default_channel);
}
}