Compare commits

...

5 Commits

Author SHA1 Message Date
5cbcbd4847 implement lua thread 2023-12-03 14:46:30 +09:00
fba2172c29 update naming rule 2023-12-03 11:33:25 +09:00
5046c64ffa add NF7_VERSION macro 2023-12-02 22:39:39 +09:00
564cc36806 add new module, nf7core_luajit 2023-12-02 22:39:11 +09:00
1d8ff509fe add new deps, luajit 2023-12-02 22:31:48 +09:00
37 changed files with 1203 additions and 507 deletions

View File

@ -1,5 +1,6 @@
# ---- basic modules
set(MODS
lua
sdl2
test
)

View File

@ -6,25 +6,25 @@ echo "#include <assert.h>"
echo
echo "#include \"util/log.h\""
echo
echo "const uint32_t NF7_CORE_MAX_MODS = UINT32_C($#);"
echo "const uint32_t NF7CORE_MAX_MODS = UINT32_C($#);"
echo
echo "uint32_t nf7_core_new(const struct nf7* nf7, struct nf7_mod** mods) {"
echo "uint32_t nf7core_new(const struct nf7* nf7, struct nf7_mod** mods) {"
echo " assert(nullptr != nf7);"
echo " assert(nullptr != mods);"
echo
echo " uint32_t i = 0;"
echo
for name in $@; do
echo " extern const struct nf7_mod_meta nf7_core_${name};"
echo " extern struct nf7_mod* nf7_core_${name}_new(const struct nf7*);"
echo " nf7_util_log_debug(\"loading module: %s\", nf7_core_${name}.name);"
echo " mods[i] = nf7_core_${name}_new(nf7);"
echo " extern const struct nf7_mod_meta nf7core_${name};"
echo " extern struct nf7_mod* nf7core_${name}_new(const struct nf7*);"
echo " nf7util_log_debug(\"loading module: %s\", nf7core_${name}.name);"
echo " mods[i] = nf7core_${name}_new(nf7);"
echo " if (nullptr != mods[i]) {"
echo " assert(nullptr != mods[i]->meta);"
echo " ++i;"
echo " nf7_util_log_info(\"loaded module: %s\", nf7_core_${name}.name);"
echo " nf7util_log_info(\"loaded module: %s\", nf7core_${name}.name);"
echo " } else {"
echo " nf7_util_log_warn(\"failed to load module: %s\", nf7_core_${name}.name);"
echo " nf7util_log_warn(\"failed to load module: %s\", nf7core_${name}.name);"
echo " }"
echo
done

View File

@ -6,15 +6,15 @@
// A maximum number of modules which nf7core may provide.
extern const uint32_t NF7_CORE_MAX_MODS;
extern const uint32_t NF7CORE_MAX_MODS;
// Initializes all modules and returns their instances.
uint32_t nf7_core_new(const struct nf7* nf7, struct nf7_mod** mods);
uint32_t nf7core_new(const struct nf7* nf7, struct nf7_mod** mods);
// PRECONDS:
// - `nf7` is a valid pointer
// - `mods` is a valid pointer
// to memory large enough to keep `NF7_CORE_MAX_MODS` pointers
// to memory large enough to keep `nf7core_MAX_MODS` pointers
// POSTCONDS:
// - When x is lower than the return value,
// mods[x] is a valid pointer to an initialized module

21
core/lua/CMakeLists.txt Normal file
View File

@ -0,0 +1,21 @@
add_library(nf7core_lua)
target_sources(nf7core_lua
PRIVATE
mod.c
thread.c
value_ptr.c
PUBLIC
mod.h
thread.h
value.h
value_ptr.h
)
target_link_libraries(nf7core_lua
PRIVATE
nf7if
nf7util
luajit
)
target_tests(nf7core_lua
thread.test.c
)

64
core/lua/mod.c Normal file
View File

@ -0,0 +1,64 @@
// No copyright
#include "core/lua/mod.h"
#include <assert.h>
#include "util/log.h"
#include "core/lua/thread.h"
static void del_(struct nf7core_lua*);
struct nf7_mod* nf7core_lua_new(struct nf7* nf7) {
assert(nullptr != nf7);
struct nf7core_lua* this =
nf7util_malloc_new(nf7->malloc, sizeof(*this));
if (nullptr == this) {
nf7util_log_error("failed to allocate a module context");
goto ABORT;
}
*this = (struct nf7core_lua) {
.meta = &nf7core_lua,
.nf7 = nf7,
.malloc = nf7->malloc,
.uv = nf7->uv,
};
this->thread = nf7core_lua_thread_new(this, nullptr, nullptr);
if (nullptr == this->thread) {
nf7util_log_error("failed to create main thread");
goto ABORT;
}
return (struct nf7_mod*) this;
ABORT:
nf7util_log_warn("aborting lua module init");
del_(this);
return nullptr;
}
static void del_(struct nf7core_lua* this) {
if (nullptr == this) {
return;
}
if (nullptr != this->thread) {
nf7core_lua_thread_unref(this->thread);
}
nf7util_malloc_del(this->malloc, this);
}
static void del_mod_(struct nf7_mod* mod) {
struct nf7core_lua* this = (void*) mod;
del_(this);
}
const struct nf7_mod_meta nf7core_lua = {
.name = (const uint8_t*) "nf7core_lua",
.desc = (const uint8_t*) "lua script execution",
.ver = NF7_VERSION,
.delete = del_mod_,
};

26
core/lua/mod.h Normal file
View File

@ -0,0 +1,26 @@
// No copyright
#pragma once
#include <stdint.h>
#include <lua.h>
#include "nf7.h"
#include "util/malloc.h"
#include "util/refcnt.h"
extern const struct nf7_mod_meta nf7core_lua;
struct nf7core_lua {
const struct nf7_mod_meta* meta;
const struct nf7* nf7;
struct nf7util_malloc* malloc;
uv_loop_t* uv;
struct nf7core_lua_thread* thread;
};
struct nf7_mod* nf7core_lua_new(struct nf7*);

180
core/lua/thread.c Normal file
View File

@ -0,0 +1,180 @@
// No copyright
#include "core/lua/thread.h"
#include <assert.h>
#include "util/log.h"
static void* alloc_(void*, void*, size_t, size_t);
static void del_(struct nf7core_lua_thread*);
static void on_time_(uv_timer_t*);
static void on_close_(uv_handle_t*);
NF7UTIL_REFCNT_IMPL(, nf7core_lua_thread, {del_(this);});
struct nf7core_lua_thread* nf7core_lua_thread_new(
struct nf7core_lua* mod,
struct nf7core_lua_thread* base,
struct nf7core_lua_value_ptr* func) {
assert(nullptr != mod);
struct nf7core_lua_thread* this =
nf7util_malloc_new(mod->malloc, sizeof(*this));
if (nullptr == this) {
nf7util_log_error("failed to allocate new thread context");
return nullptr;
}
*this = (struct nf7core_lua_thread) {
.mod = mod,
.malloc = mod->malloc,
.uv = mod->uv,
};
if (0 != nf7util_log_uv(uv_timer_init(this->uv, &this->timer))) {
nf7util_log_error("failed to init uv timer");
goto ABORT;
}
this->timer.data = this;
if (nullptr != base) {
this->lua = lua_newthread(base->lua);
if (nullptr == this->lua) {
nf7util_log_error("failed to allocate new lua thread");
goto ABORT;
}
this->base = base;
nf7core_lua_thread_ref(this->base);
} else {
this->lua_owned = true;
this->lua = lua_newstate(alloc_, this);
if (nullptr == this->lua) {
nf7util_log_error("failed to allocate new lua state");
goto ABORT;
}
nf7util_log_debug("new lua state is created");
}
if (nullptr != func) {
this->state = NF7CORE_LUA_THREAD_PAUSED;
nf7core_lua_value_ptr_push(func, this->lua);
} else {
this->state = NF7CORE_LUA_THREAD_DONE;
}
nf7core_lua_thread_ref(this);
return this;
ABORT:
nf7util_log_warn("aborting thread creation");
del_(this);
return nullptr;
}
bool nf7core_lua_thread_resume_varg_after(
struct nf7core_lua_thread* this, uint64_t timeout, va_list vargs) {
assert(nullptr != this);
assert(NF7CORE_LUA_THREAD_PAUSED == this->state);
// stores parameters
for (uint32_t i = 0;; ++i) {
struct nf7core_lua_value* src = va_arg(vargs, struct nf7core_lua_value*);
if (nullptr == src) {
this->args.n = i;
break;
}
assert(i < NF7CORE_LUA_THREAD_MAX_ARGS &&
"too many args or forgotten last nullptr");
struct nf7core_lua_value* dst = &this->args.ptr[i];
if (!nf7core_lua_value_set(dst, src)) {
nf7core_lua_value_set(dst, &NF7CORE_LUA_VALUE_NIL());
nf7util_log_warn(
"failed to store parameter value, it's replaced by nil");
}
}
if (0 != nf7util_log_uv(uv_timer_start(&this->timer, on_time_, timeout, 0))) {
nf7util_log_error(
"failed to start timer for resuming thread");
return false;
}
nf7core_lua_thread_ref(this);
nf7util_log_debug("lua thread state change: PAUSED -> SCHEDULED");
this->state = NF7CORE_LUA_THREAD_SCHEDULED;
return true;
}
static void* alloc_(void* data, void* ptr, size_t, size_t nsize) {
struct nf7core_lua_thread* this = data;
return nf7util_malloc_renew(this->malloc, ptr, nsize);
}
static void del_(struct nf7core_lua_thread* this) {
if (nullptr == this) {
return;
}
if (nullptr != this->timer.data) {
uv_close((uv_handle_t*) &this->timer, on_close_);
return;
}
if (nullptr != this->lua && this->lua_owned) {
lua_close(this->lua);
nf7util_log_debug("lua state is closed");
}
if (nullptr != this->base) {
nf7core_lua_thread_unref(this->base);
}
nf7util_malloc_del(this->malloc, this);
}
static void on_time_(uv_timer_t* timer) {
struct nf7core_lua_thread* this = timer->data;
assert(nullptr != this);
assert(NF7CORE_LUA_THREAD_SCHEDULED == this->state);
lua_State* L = this->lua;
for (uint32_t i = 0; i < this->args.n; ++i) {
struct nf7core_lua_value* v = &this->args.ptr[i];
nf7core_lua_value_push(v, L);
nf7core_lua_value_unset(v);
}
nf7util_log_debug("lua thread state change: SCHEDULED -> RUNNING");
this->state = NF7CORE_LUA_THREAD_RUNNING;
const int result = lua_resume(L, (int) this->args.n);
switch (result) {
case 0:
nf7util_log_debug("lua thread state change: RUNNING -> DONE");
this->state = NF7CORE_LUA_THREAD_DONE;
break;
case LUA_YIELD:
nf7util_log_debug("lua thread state change: RUNNING -> PAUSED");
this->state = NF7CORE_LUA_THREAD_PAUSED;
break;
case LUA_ERRMEM:
case LUA_ERRRUN:
case LUA_ERRERR:
nf7util_log_warn("lua execution failed: ", lua_tostring(L, -1));
nf7util_log_debug("lua thread state change: RUNNING -> ABORTED");
this->state = NF7CORE_LUA_THREAD_ABORTED;
break;
}
if (nullptr != this->post_exec) {
this->post_exec(this, L);
}
lua_settop(L, 0);
nf7core_lua_thread_unref(this);
}
static void on_close_(uv_handle_t* handle) {
struct nf7core_lua_thread* this = handle->data;
this->timer.data = nullptr;
del_(this);
}

92
core/lua/thread.h Normal file
View File

@ -0,0 +1,92 @@
// No copyright
#pragma once
#include <stdarg.h>
#include <lua.h>
#include <uv.h>
#include "util/malloc.h"
#include "util/refcnt.h"
#include "core/lua/mod.h"
#include "core/lua/value.h"
#include "core/lua/value_ptr.h"
struct nf7core_lua_thread {
struct nf7core_lua* mod;
struct nf7util_malloc* malloc;
uv_loop_t* uv;
bool lua_owned;
lua_State* lua;
struct nf7core_lua_thread* base;
uv_timer_t timer;
uint32_t refcnt;
uint8_t state;
# define NF7CORE_LUA_THREAD_PAUSED 0
# define NF7CORE_LUA_THREAD_SCHEDULED 1
# define NF7CORE_LUA_THREAD_RUNNING 2
# define NF7CORE_LUA_THREAD_DONE 3
# define NF7CORE_LUA_THREAD_ABORTED 4
struct {
# define NF7CORE_LUA_THREAD_MAX_ARGS 4
uint32_t n;
struct nf7core_lua_value ptr[NF7CORE_LUA_THREAD_MAX_ARGS];
} args;
void* data;
void (*post_exec)(struct nf7core_lua_thread*, lua_State*);
};
NF7UTIL_REFCNT_DECL(, nf7core_lua_thread);
// Creates and returns new thread.
struct nf7core_lua_thread* nf7core_lua_thread_new(
struct nf7core_lua* mod,
struct nf7core_lua_thread* base,
struct nf7core_lua_value_ptr* func);
// POSTCONDS:
// - If the base is not nullptr, the returned thread must be synchronized with
// the base, otherwise, it's completely independent. (base thread)
// - If the func is not nullptr, the returned thread prepares to execute a
// function in the value,
// otherwise, it can execute nothing (this is for the base thread)
// Resumes the co-routine with the values.
bool nf7core_lua_thread_resume_varg_after(
struct nf7core_lua_thread* this, uint64_t timeout, va_list vargs);
// PRECONDS:
// - `nullptr != this`
// - `nullptr != this->func`
// - `NF7CORE_LUA_THREAD_PAUSED == this->state`
// - Items in `vargs` must be `const struct nf7core_lua_value*` or `nullptr`.
// - The last item of `vargs` must be `nullptr`.
// POSTCONDS:
// - When returns true:
// - `NF7CORE_LUA_THREAD_SCHEDULED == this->state`
// - the state will changes to RUNNING after `timeout` [ms]
// - Otherwise, nothing happens.
static inline bool nf7core_lua_thread_resume(
struct nf7core_lua_thread* this, ...) {
va_list vargs;
va_start(vargs, this);
const bool ret = nf7core_lua_thread_resume_varg_after(this, 0, vargs);
va_end(vargs);
return ret;
}
static inline bool nf7core_lua_thread_resume_after(
struct nf7core_lua_thread* this, uint64_t timeout, ...) {
va_list vargs;
va_start(vargs, this);
const bool ret = nf7core_lua_thread_resume_varg_after(this, timeout, vargs);
va_end(vargs);
return ret;
}

67
core/lua/thread.test.c Normal file
View File

@ -0,0 +1,67 @@
// No copyright
#include "core/lua/thread.h"
#include <lauxlib.h>
#include "util/log.h"
#include "test/common.h"
static void finalize_(struct nf7core_lua_thread* this, lua_State*) {
struct nf7test* test_ = this->data;
nf7test_expect(NF7CORE_LUA_THREAD_DONE == this->state);
nf7test_unref(test_);
}
NF7TEST(nf7core_lua_thread_test_valid_syntax) {
struct nf7core_lua* mod =
(void*) nf7_get_mod_by_meta(test_->nf7, &nf7core_lua);
if (!nf7test_expect(nullptr != mod)) {
return false;
}
struct nf7core_lua_thread* base = mod->thread;
lua_State* L = base->lua;
if (!nf7test_expect(0 == luaL_loadstring(L, "local x = 100"))) {
nf7util_log_error("lua compile error: %s", lua_tostring(L, -1));
return false;
}
struct nf7core_lua_value_ptr* func = nf7core_lua_value_ptr_new(base, L);
if (!nf7test_expect(nullptr != func)) {
return false;
}
struct nf7core_lua_thread* thread = nf7core_lua_thread_new(mod, base, func);
nf7core_lua_value_ptr_unref(func);
if (!nf7test_expect(nullptr != thread)) {
return false;
}
thread->data = test_;
thread->post_exec = finalize_;
if (!nf7test_expect(nf7core_lua_thread_resume(thread, nullptr))) {
return false;
}
nf7core_lua_thread_unref(thread);
nf7test_ref(test_);
return true;
}
NF7TEST(nf7core_lua_thread_test_invalid_syntax) {
struct nf7core_lua* mod =
(void*) nf7_get_mod_by_meta(test_->nf7, &nf7core_lua);
if (!nf7test_expect(nullptr != mod)) {
return false;
}
struct nf7core_lua_thread* base = mod->thread;
lua_State* L = base->lua;
if (!nf7test_expect(0 != luaL_loadstring(L, "helloworld"))) {
return false;
}
return true;
}

88
core/lua/value.h Normal file
View File

@ -0,0 +1,88 @@
// No copyright
#pragma once
#include <assert.h>
#include <stdint.h>
#include "core/lua/value_ptr.h"
struct nf7core_lua_value {
uint32_t type;
# define NF7CORE_LUA_VALUE_TYPE_NIL 0
# define NF7CORE_LUA_VALUE_TYPE_INT 1
# define NF7CORE_LUA_VALUE_TYPE_NUM 2
# define NF7CORE_LUA_VALUE_TYPE_PTR 3
union {
lua_Integer i;
lua_Number n;
struct nf7core_lua_value_ptr* ptr;
};
};
#define NF7CORE_LUA_VALUE_NIL() \
(struct nf7core_lua_value) { .type = NF7CORE_LUA_VALUE_TYPE_NIL, }
#define NF7CORE_LUA_VALUE_INT(v) \
(struct nf7core_lua_value) { .type = NF7CORE_LUA_VALUE_TYPE_INT, .i = (v), }
#define NF7CORE_LUA_VALUE_NUM(v) \
(struct nf7core_lua_value) { .type = NF7CORE_LUA_VALUE_TYPE_NUM, .n = (v), }
#define NF7CORE_LUA_VALUE_PTR(v) \
(struct nf7core_lua_value) { \
.type = NF7CORE_LUA_VALUE_TYPE_PTR, \
.ptr = (v), \
}
static inline void nf7core_lua_value_push(
const struct nf7core_lua_value* this, lua_State* L) {
assert(nullptr != this);
assert(nullptr != L);
switch (this->type) {
case NF7CORE_LUA_VALUE_TYPE_NIL:
lua_pushnil(L);
break;
case NF7CORE_LUA_VALUE_TYPE_INT:
lua_pushinteger(L, this->i);
break;
case NF7CORE_LUA_VALUE_TYPE_NUM:
lua_pushnumber(L, this->n);
break;
case NF7CORE_LUA_VALUE_TYPE_PTR:
assert(nullptr != this->ptr);
nf7core_lua_value_ptr_push(this->ptr, L);
break;
default:
assert(false);
}
}
static inline void nf7core_lua_value_unset(struct nf7core_lua_value* this) {
assert(nullptr != this);
switch (this->type) {
case NF7CORE_LUA_VALUE_TYPE_PTR:
nf7core_lua_value_ptr_unref(this->ptr);
break;
default:
break;
}
this->type = NF7CORE_LUA_VALUE_TYPE_NIL;
}
static inline bool nf7core_lua_value_set(
struct nf7core_lua_value* this, const struct nf7core_lua_value* src) {
assert(nullptr != this);
assert(nullptr != src);
nf7core_lua_value_unset(this);
switch (src->type) {
case NF7CORE_LUA_VALUE_TYPE_PTR:
*this = *src;
nf7core_lua_value_ptr_ref(this->ptr);
return true;
default:
*this = *src;
return true;
}
}

64
core/lua/value_ptr.c Normal file
View File

@ -0,0 +1,64 @@
// No copyright
#include "core/lua/value_ptr.h"
#include <lua.h>
#include <lauxlib.h>
#include "core/lua/thread.h"
struct nf7core_lua_value_ptr {
struct nf7core_lua_thread* thread;
struct nf7util_malloc* malloc;
lua_State* lua;
uint32_t refcnt;
int index;
};
static void del_(struct nf7core_lua_value_ptr*);
NF7UTIL_REFCNT_IMPL(, nf7core_lua_value_ptr, {del_(this);});
struct nf7core_lua_value_ptr* nf7core_lua_value_ptr_new(
struct nf7core_lua_thread* thread, lua_State* L) {
assert(nullptr != thread);
assert(nullptr != L);
struct nf7core_lua_value_ptr* this =
nf7util_malloc_new(thread->malloc, sizeof(*this));
if (nullptr == this) {
goto ABORT;
}
*this = (struct nf7core_lua_value_ptr) {
.malloc = thread->malloc,
.lua = L,
};
this->thread = thread;
nf7core_lua_thread_ref(this->thread);
this->index = luaL_ref(this->lua, LUA_REGISTRYINDEX);
nf7core_lua_value_ptr_ref(this);
return this;
ABORT:
lua_pop(L, 1);
return nullptr;
}
void nf7core_lua_value_ptr_push(
const struct nf7core_lua_value_ptr* this, lua_State* lua) {
assert(nullptr != this);
assert(nullptr != lua);
lua_rawgeti(lua, LUA_REGISTRYINDEX, this->index);
}
static void del_(struct nf7core_lua_value_ptr* this) {
assert(nullptr != this);
luaL_unref(this->lua, LUA_REGISTRYINDEX, this->index);
nf7core_lua_thread_unref(this->thread);
nf7util_malloc_del(this->malloc, this);
}

22
core/lua/value_ptr.h Normal file
View File

@ -0,0 +1,22 @@
// No copyright
#pragma once
#include <stdint.h>
#include <lua.h>
#include "util/refcnt.h"
struct nf7core_lua_thread;
struct nf7core_lua_value_ptr;
NF7UTIL_REFCNT_DECL(, nf7core_lua_value_ptr);
struct nf7core_lua_value_ptr* nf7core_lua_value_ptr_new(
struct nf7core_lua_thread*, lua_State*);
// POSTCONDS:
// - the top value is always popped
void nf7core_lua_value_ptr_push(
const struct nf7core_lua_value_ptr*, lua_State*);

View File

@ -18,31 +18,31 @@
static atomic_uint_least32_t sdl_refcnt_ = 0;
static void poll_(struct nf7_core_sdl2_poll*, const SDL_Event*);
static void del_(struct nf7_core_sdl2*);
NF7_UTIL_REFCNT_IMPL(, nf7_core_sdl2, {del_(this);});
static void poll_(struct nf7core_sdl2_poll*, const SDL_Event*);
static void del_(struct nf7core_sdl2*);
NF7UTIL_REFCNT_IMPL(, nf7core_sdl2, {del_(this);});
struct nf7_mod* nf7_core_sdl2_new(const struct nf7* nf7) {
struct nf7_mod* nf7core_sdl2_new(const struct nf7* nf7) {
assert(nullptr != nf7);
if (0 < atomic_fetch_add(&sdl_refcnt_, 1)) {
nf7_util_log_error(
nf7util_log_error(
"multiple SDL2 module instance cannot be exists at the same time");
return nullptr;
}
if (0 != SDL_Init(SDL_INIT_VIDEO)) {
nf7_util_log_error("failed to init SDL: %s", SDL_GetError());
nf7util_log_error("failed to init SDL: %s", SDL_GetError());
return nullptr;
}
struct nf7_core_sdl2* this = nf7_util_malloc_new(nf7->malloc, sizeof(*this));
struct nf7core_sdl2* this = nf7util_malloc_new(nf7->malloc, sizeof(*this));
if (nullptr == this) {
nf7_util_log_error("failed to allocate instance");
nf7util_log_error("failed to allocate instance");
goto ABORT;
}
*this = (struct nf7_core_sdl2) {
.meta = &nf7_core_sdl2,
*this = (struct nf7core_sdl2) {
.meta = &nf7core_sdl2,
.nf7 = nf7,
.malloc = nf7->malloc,
.uv = nf7->uv,
@ -53,54 +53,54 @@ struct nf7_mod* nf7_core_sdl2_new(const struct nf7* nf7) {
this->poll = poll_new_(this);
if (nullptr == this->poll) {
nf7_util_log_error("failed to setup polling");
nf7util_log_error("failed to setup polling");
goto ABORT;
}
this->poll->data = this;
this->poll->handler = poll_;
nf7_util_signal_init(&this->event_signal);
nf7_core_sdl2_ref(this);
nf7util_signal_init(&this->event_signal);
nf7core_sdl2_ref(this);
return (struct nf7_mod*) this;
ABORT:
nf7_util_log_warn("initialization is aborted");
nf7util_log_warn("initialization is aborted");
del_(this);
return nullptr;
}
static void poll_(struct nf7_core_sdl2_poll* poll, const SDL_Event* e) {
struct nf7_core_sdl2* this = poll->data;
static void poll_(struct nf7core_sdl2_poll* poll, const SDL_Event* e) {
struct nf7core_sdl2* this = poll->data;
this->event = e;
nf7_util_signal_emit(&this->event_signal);
nf7util_signal_emit(&this->event_signal);
this->event = nullptr;
}
static void del_(struct nf7_core_sdl2* this) {
static void del_(struct nf7core_sdl2* this) {
if (nullptr == this) {
return;
}
nf7_util_signal_deinit(&this->event_signal);
nf7util_signal_deinit(&this->event_signal);
poll_del_(this->poll);
nf7_util_malloc_del(this->malloc, this);
nf7util_malloc_del(this->malloc, this);
if (1 == atomic_fetch_sub(&sdl_refcnt_, 1)) {
nf7_util_log_debug("finalizing SDL...");
nf7util_log_debug("finalizing SDL...");
SDL_Quit();
nf7_util_log_info("SDL is finalized");
nf7util_log_info("SDL is finalized");
}
}
static void unref_(struct nf7_mod* this_) {
struct nf7_core_sdl2* this = (struct nf7_core_sdl2*) this_;
nf7_core_sdl2_unref(this);
struct nf7core_sdl2* this = (struct nf7core_sdl2*) this_;
nf7core_sdl2_unref(this);
}
const struct nf7_mod_meta nf7_core_sdl2 = {
const struct nf7_mod_meta nf7core_sdl2 = {
.name = (const uint8_t*) "nf7core_sdl2",
.desc = (const uint8_t*) "provides SDL2 features",
.ver = 0,
.ver = NF7_VERSION,
.delete = unref_,
};

View File

@ -13,24 +13,24 @@
#include "util/signal.h"
extern const struct nf7_mod_meta nf7_core_sdl2;
extern const struct nf7_mod_meta nf7core_sdl2;
struct nf7_core_sdl2_poll;
struct nf7core_sdl2_poll;
struct nf7_core_sdl2 {
struct nf7core_sdl2 {
const struct nf7_mod_meta* meta;
// library pointers (immutable)
const struct nf7* nf7;
struct nf7_util_malloc* malloc;
struct nf7util_malloc* malloc;
uv_loop_t* uv;
SDL_Window* win;
void* gl;
uint32_t refcnt;
struct nf7_core_sdl2_poll* poll;
struct nf7core_sdl2_poll* poll;
const SDL_Event* event;
struct nf7_util_signal event_signal;
struct nf7util_signal event_signal;
};
NF7_UTIL_REFCNT_DECL(, nf7_core_sdl2);
NF7UTIL_REFCNT_DECL(, nf7core_sdl2);

View File

@ -8,36 +8,36 @@
#include "core/sdl2/mod.h"
struct nf7_core_sdl2_poll {
struct nf7core_sdl2_poll {
const struct nf7* nf7;
struct nf7_util_malloc* malloc;
struct nf7util_malloc* malloc;
uv_loop_t* uv;
uv_timer_t timer;
uint64_t interval;
void* data;
void (*handler)(struct nf7_core_sdl2_poll*, const SDL_Event*);
void (*handler)(struct nf7core_sdl2_poll*, const SDL_Event*);
};
static struct nf7_core_sdl2_poll* poll_new_(struct nf7_core_sdl2*);
static void poll_del_(struct nf7_core_sdl2_poll*);
static struct nf7core_sdl2_poll* poll_new_(struct nf7core_sdl2*);
static void poll_del_(struct nf7core_sdl2_poll*);
static void poll_on_time_(uv_timer_t*);
static void poll_on_close_(uv_handle_t*);
static struct nf7_core_sdl2_poll* poll_new_(struct nf7_core_sdl2* mod) {
static struct nf7core_sdl2_poll* poll_new_(struct nf7core_sdl2* mod) {
assert(nullptr != mod);
struct nf7_core_sdl2_poll* this =
nf7_util_malloc_new(mod->malloc, sizeof(*this));
struct nf7core_sdl2_poll* this =
nf7util_malloc_new(mod->malloc, sizeof(*this));
if (nullptr == this) {
nf7_util_log_error("failed to allocate poll context");
nf7util_log_error("failed to allocate poll context");
return nullptr;
}
*this = (struct nf7_core_sdl2_poll) {
*this = (struct nf7core_sdl2_poll) {
.nf7 = mod->nf7,
.malloc = mod->malloc,
.uv = mod->uv,
@ -45,21 +45,21 @@ static struct nf7_core_sdl2_poll* poll_new_(struct nf7_core_sdl2* mod) {
.interval = 30,
};
if (0 != nf7_util_log_uv(uv_timer_init(this->uv, &this->timer))) {
nf7_util_log_error("failed to init poll timer");
if (0 != nf7util_log_uv(uv_timer_init(this->uv, &this->timer))) {
nf7util_log_error("failed to init poll timer");
return nullptr;
}
uv_unref((uv_handle_t*) &this->timer);
this->timer.data = this;
if (0 != nf7_util_log_uv(uv_timer_start(&this->timer, poll_on_time_, 0, 0))) {
nf7_util_log_error("failed to start poll timer");
if (0 != nf7util_log_uv(uv_timer_start(&this->timer, poll_on_time_, 0, 0))) {
nf7util_log_error("failed to start poll timer");
poll_del_(this);
return nullptr;
}
return this;
}
static void poll_del_(struct nf7_core_sdl2_poll* this) {
static void poll_del_(struct nf7core_sdl2_poll* this) {
if (this == nullptr) {
return;
}
@ -68,13 +68,13 @@ static void poll_del_(struct nf7_core_sdl2_poll* this) {
uv_close((uv_handle_t*) &this->timer, poll_on_close_);
return;
}
nf7_util_malloc_del(this->malloc, this);
nf7util_malloc_del(this->malloc, this);
}
static void poll_on_time_(uv_timer_t* timer) {
assert(nullptr != timer);
struct nf7_core_sdl2_poll* this = timer->data;
struct nf7core_sdl2_poll* this = timer->data;
SDL_Event e;
while (0 != SDL_PollEvent(&e)) {
@ -84,13 +84,13 @@ static void poll_on_time_(uv_timer_t* timer) {
}
if (0 != uv_timer_start(&this->timer, poll_on_time_, this->interval, 0)) {
nf7_util_log_error("failed to restart poll timer");
nf7util_log_error("failed to restart poll timer");
poll_del_(this);
}
}
static void poll_on_close_(uv_handle_t* handle) {
struct nf7_core_sdl2_poll* this = handle->data;
struct nf7core_sdl2_poll* this = handle->data;
assert(nullptr != this);
handle->data = nullptr;
poll_del_(this);

View File

@ -9,23 +9,23 @@
static void setup_gl_(void);
static void handle_(struct nf7_util_signal_recv* recv);
static void handle_(struct nf7util_signal_recv* recv);
bool nf7_core_sdl2_win_init(struct nf7_core_sdl2_win* this) {
bool nf7core_sdl2_win_init(struct nf7core_sdl2_win* this) {
assert(nullptr != this);
assert(nullptr != this->mod);
assert(nullptr != this->malloc);
// TODO error handling
this->event_recv = (struct nf7_util_signal_recv) {
this->event_recv = (struct nf7util_signal_recv) {
.signal = &this->mod->event_signal,
};
this->event_recv.data = this;
this->event_recv.func = handle_;
if (!nf7_util_signal_recv_set(&this->event_recv, &this->mod->event_signal)) {
nf7_util_log_error("failed to listen event signal");
if (!nf7util_signal_recv_set(&this->event_recv, &this->mod->event_signal)) {
nf7util_log_error("failed to listen event signal");
return false;
}
@ -41,45 +41,45 @@ bool nf7_core_sdl2_win_init(struct nf7_core_sdl2_win* this) {
1280, 720,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
if (nullptr == this->win) {
nf7_util_log_error("failed to create SDL window: %s", SDL_GetError());
nf7util_log_error("failed to create SDL window: %s", SDL_GetError());
return false;
}
this->win_id = SDL_GetWindowID(this->win);
if (0 == this->win_id) {
nf7_util_log_error("failed to get window id: %s", SDL_GetError());
nf7util_log_error("failed to get window id: %s", SDL_GetError());
return false;
}
nf7_util_log_debug("GUI window %" PRIu32 " is created", this->win_id);
nf7util_log_debug("GUI window %" PRIu32 " is created", this->win_id);
this->gl = SDL_GL_CreateContext(this->win);
if (nullptr == this->gl) {
nf7_util_log_error("failed to create GL context: %s", SDL_GetError());
nf7util_log_error("failed to create GL context: %s", SDL_GetError());
return false;
}
nf7_util_log_debug("OpenGL context is created");
nf7util_log_debug("OpenGL context is created");
if (0 != SDL_GL_SetSwapInterval(0)) {
nf7_util_log_warn(
nf7util_log_warn(
"failed to set swap interval, this will cause a performance issue: %s",
SDL_GetError());
}
nf7_core_sdl2_ref(this->mod);
nf7core_sdl2_ref(this->mod);
return true;
}
void nf7_core_sdl2_win_deinit(struct nf7_core_sdl2_win* this) {
void nf7core_sdl2_win_deinit(struct nf7core_sdl2_win* this) {
if (nullptr != this) {
if (nullptr != this->gl) {
SDL_GL_DeleteContext(this->gl);
nf7_util_log_debug("OpenGL context is deleted");
nf7util_log_debug("OpenGL context is deleted");
}
if (nullptr != this->win) {
SDL_DestroyWindow(this->win);
nf7_util_log_debug("GUI window is destroyed");
nf7util_log_debug("GUI window is destroyed");
}
nf7_util_signal_recv_unset(&this->event_recv);
nf7_core_sdl2_unref(this->mod);
nf7util_signal_recv_unset(&this->event_recv);
nf7core_sdl2_unref(this->mod);
}
}
@ -97,8 +97,8 @@ static void setup_gl_(void) {
# endif
}
static void handle_(struct nf7_util_signal_recv* recv) {
struct nf7_core_sdl2_win* this = recv->data;
static void handle_(struct nf7util_signal_recv* recv) {
struct nf7core_sdl2_win* this = recv->data;
assert(nullptr != this);
const SDL_Event* e = this->mod->event;
@ -113,7 +113,7 @@ static void handle_(struct nf7_util_signal_recv* recv) {
switch (we->event) {
case SDL_WINDOWEVENT_CLOSE:
nf7_util_log_debug("received close request");
nf7util_log_debug("received close request");
break;
default:
break;

View File

@ -12,19 +12,19 @@
#include "core/sdl2/mod.h"
struct nf7_core_sdl2_win {
struct nf7_core_sdl2* mod;
struct nf7_util_malloc* malloc;
struct nf7core_sdl2_win {
struct nf7core_sdl2* mod;
struct nf7util_malloc* malloc;
SDL_Window* win;
uint32_t win_id;
void* gl;
struct nf7_util_signal_recv event_recv;
struct nf7util_signal_recv event_recv;
void* data;
void (*handler)(struct nf7_core_sdl2_win*, const SDL_WindowEvent*);
void (*handler)(struct nf7core_sdl2_win*, const SDL_WindowEvent*);
};
bool nf7_core_sdl2_win_init(struct nf7_core_sdl2_win*);
void nf7_core_sdl2_win_deinit(struct nf7_core_sdl2_win*);
bool nf7core_sdl2_win_init(struct nf7core_sdl2_win*);
void nf7core_sdl2_win_deinit(struct nf7core_sdl2_win*);

View File

@ -10,33 +10,33 @@
#include "core/sdl2/mod.h"
struct nf7_core_sdl2_win_test {
struct nf7_test* test;
struct nf7_util_malloc* malloc;
struct nf7core_sdl2_win_test {
struct nf7test* test;
struct nf7util_malloc* malloc;
uv_loop_t* uv;
struct nf7_core_sdl2_win win;
struct nf7core_sdl2_win win;
uv_timer_t timer;
};
static void finalize_(struct nf7_core_sdl2_win_test*);
static void finalize_(struct nf7core_sdl2_win_test*);
static void on_time_(uv_timer_t*);
static void on_close_(uv_handle_t*);
static void on_handle_(struct nf7_core_sdl2_win*, const SDL_WindowEvent*);
static void on_handle_(struct nf7core_sdl2_win*, const SDL_WindowEvent*);
NF7_TEST(nf7_core_sdl2_win_test) {
struct nf7_core_sdl2* mod = (void*) nf7_get_mod_by_meta(
test_->nf7, (struct nf7_mod_meta*) &nf7_core_sdl2);
if (!nf7_test_expect(nullptr != mod)) {
NF7TEST(nf7core_sdl2_win_test) {
struct nf7core_sdl2* mod = (void*) nf7_get_mod_by_meta(
test_->nf7, (struct nf7_mod_meta*) &nf7core_sdl2);
if (!nf7test_expect(nullptr != mod)) {
return false;
}
struct nf7_core_sdl2_win_test* this =
nf7_util_malloc_new(test_->malloc, sizeof(*this));
if (!nf7_test_expect(nullptr != this)) {
struct nf7core_sdl2_win_test* this =
nf7util_malloc_new(test_->malloc, sizeof(*this));
if (!nf7test_expect(nullptr != this)) {
goto ABORT;
}
*this = (struct nf7_core_sdl2_win_test) {
*this = (struct nf7core_sdl2_win_test) {
.test = test_,
.malloc = test_->malloc,
.uv = test_->nf7->uv,
@ -45,20 +45,20 @@ NF7_TEST(nf7_core_sdl2_win_test) {
.malloc = test_->malloc,
},
};
nf7_test_ref(this->test);
nf7test_ref(this->test);
if (!nf7_test_expect(nf7_core_sdl2_win_init(&this->win))) {
if (!nf7test_expect(nf7core_sdl2_win_init(&this->win))) {
goto ABORT;
}
this->win.data = this;
this->win.handler = on_handle_;
if (0 != nf7_util_log_uv(uv_timer_init(this->uv, &this->timer))) {
if (0 != nf7util_log_uv(uv_timer_init(this->uv, &this->timer))) {
goto ABORT;
}
this->timer.data = this;
if (0 != nf7_util_log_uv(uv_timer_start(&this->timer, on_time_, 3000, 0))) {
if (0 != nf7util_log_uv(uv_timer_start(&this->timer, on_time_, 3000, 0))) {
goto ABORT;
}
return true;
@ -68,30 +68,30 @@ ABORT:
return false;
}
static void finalize_(struct nf7_core_sdl2_win_test* this) {
static void finalize_(struct nf7core_sdl2_win_test* this) {
if (nullptr != this->timer.data) {
nf7_util_log_uv_assert(uv_timer_stop(&this->timer));
nf7util_log_uv_assert(uv_timer_stop(&this->timer));
uv_close((uv_handle_t*) &this->timer, on_close_);
return;
}
nf7_core_sdl2_win_deinit(&this->win);
nf7_test_unref(this->test);
nf7_util_malloc_del(this->malloc, this);
nf7core_sdl2_win_deinit(&this->win);
nf7test_unref(this->test);
nf7util_malloc_del(this->malloc, this);
}
static void on_time_(uv_timer_t* timer) {
struct nf7_core_sdl2_win_test* this = timer->data;
struct nf7core_sdl2_win_test* this = timer->data;
finalize_(this);
}
static void on_close_(uv_handle_t* handle) {
struct nf7_core_sdl2_win_test* this = handle->data;
struct nf7core_sdl2_win_test* this = handle->data;
handle->data = nullptr;
finalize_(this);
}
static void on_handle_(struct nf7_core_sdl2_win* win, const SDL_WindowEvent* e) {
struct nf7_core_sdl2_win_test* this = win->data;
static void on_handle_(struct nf7core_sdl2_win* win, const SDL_WindowEvent* e) {
struct nf7core_sdl2_win_test* this = win->data;
switch (e->event) {
case SDL_WINDOWEVENT_CLOSE:

View File

@ -14,38 +14,38 @@
static void del_(struct nf7_mod*);
struct nf7_mod* nf7_core_test_new(struct nf7* nf7) {
struct nf7_mod* nf7core_test_new(const struct nf7* nf7) {
assert(nullptr != nf7);
struct nf7_core_test* this = nf7_util_malloc_new(nf7->malloc, sizeof(*this));
struct nf7core_test* this = nf7util_malloc_new(nf7->malloc, sizeof(*this));
if (nullptr == this) {
nf7_util_log_error("failed to allocate instance");
nf7util_log_error("failed to allocate instance");
return nullptr;
}
*this = (struct nf7_core_test) {
.meta = &nf7_core_test,
*this = (struct nf7core_test) {
.meta = &nf7core_test,
.nf7 = nf7,
.malloc = nf7->malloc,
.uv = nf7->uv,
};
if (!run_trigger_setup_(this)) {
nf7_util_log_error("failed to setup runner");
nf7util_log_error("failed to setup runner");
return nullptr;
}
return (struct nf7_mod*) this;
}
static void del_(struct nf7_mod* mod) {
struct nf7_core_test* this = (struct nf7_core_test*) mod;
nf7_util_malloc_del(this->malloc, this);
struct nf7core_test* this = (struct nf7core_test*) mod;
nf7util_malloc_del(this->malloc, this);
}
const struct nf7_mod_meta nf7_core_test = {
const struct nf7_mod_meta nf7core_test = {
.name = (const uint8_t*) "nf7core_test",
.desc = (const uint8_t*) "executes tests after the initialization",
.ver = 0,
.ver = NF7_VERSION,
.delete = del_,
};

View File

@ -6,17 +6,17 @@
#include "test/common.h"
struct nf7_core_test;
struct nf7_core_test_run;
struct nf7core_test;
struct nf7core_test_run;
struct nf7_core_test {
struct nf7core_test {
const struct nf7_mod_meta* meta;
struct nf7* nf7;
struct nf7_util_malloc* malloc;
const struct nf7* nf7;
struct nf7util_malloc* malloc;
uv_loop_t* uv;
struct nf7_core_test_run* run;
struct nf7core_test_run* run;
};
extern const struct nf7_mod_meta nf7_core_test;
extern const struct nf7_mod_meta nf7core_test;

View File

@ -13,23 +13,23 @@
#include "core/test/mod.h"
static bool run_trigger_setup_(struct nf7_core_test*);
static void run_cancel_(struct nf7_core_test_run*);
static bool run_trigger_setup_(struct nf7core_test*);
static void run_cancel_(struct nf7core_test_run*);
static void run_cancel_close_(uv_handle_t*);
static void run_trigger_(uv_idle_t*);
static void run_single_test_(struct nf7_test*, const char*, nf7_test_func);
static void run_expect_(struct nf7_test*, bool, const char*);
static void run_finalize_(struct nf7_test*);
static void run_single_test_(struct nf7test*, const char*, nf7test_func);
static void run_expect_(struct nf7test*, bool, const char*);
static void run_finalize_(struct nf7test*);
struct nf7_core_test_run {
struct nf7_core_test* mod;
struct nf7_util_malloc* malloc;
struct nf7core_test_run {
struct nf7core_test* mod;
struct nf7util_malloc* malloc;
uv_loop_t* uv;
uv_idle_t idle;
struct nf7_test test;
struct nf7test test;
uint64_t run_tests;
uint64_t succeeded_tests;
@ -38,15 +38,15 @@ struct nf7_core_test_run {
};
static bool run_trigger_setup_(struct nf7_core_test* mod) {
static bool run_trigger_setup_(struct nf7core_test* mod) {
assert(nullptr != mod);
struct nf7_core_test_run* this = nf7_util_malloc_new(mod->malloc, sizeof(*this));
struct nf7core_test_run* this = nf7util_malloc_new(mod->malloc, sizeof(*this));
if (nullptr == this) {
nf7_util_log_error("failed to allocate an test context");
nf7util_log_error("failed to allocate an test context");
return false;
}
*this = (struct nf7_core_test_run) {
*this = (struct nf7core_test_run) {
.mod = mod,
.malloc = mod->malloc,
.uv = mod->uv,
@ -59,17 +59,17 @@ static bool run_trigger_setup_(struct nf7_core_test* mod) {
.finalize = run_finalize_,
},
};
nf7_test_ref(&this->test);
nf7test_ref(&this->test);
nf7_util_log_uv_assert(uv_idle_init(this->uv, &this->idle));
nf7util_log_uv_assert(uv_idle_init(this->uv, &this->idle));
this->idle.data = this;
nf7_util_log_uv_assert(uv_idle_start(&this->idle, run_trigger_));
nf7util_log_uv_assert(uv_idle_start(&this->idle, run_trigger_));
mod->run = this;
return true;
}
static void run_cancel_(struct nf7_core_test_run* this) {
static void run_cancel_(struct nf7core_test_run* this) {
if (nullptr != this) {
if (nullptr != this->mod) {
this->mod->run = nullptr;
@ -79,30 +79,30 @@ static void run_cancel_(struct nf7_core_test_run* this) {
}
}
static void run_cancel_close_(uv_handle_t* handle) {
struct nf7_core_test_run* this = handle->data;
nf7_test_unref(&this->test);
struct nf7core_test_run* this = handle->data;
nf7test_unref(&this->test);
}
static void run_trigger_(uv_idle_t* idle) {
struct nf7_core_test_run* this = idle->data;
struct nf7core_test_run* this = idle->data;
nf7_util_log_info("triggering tests...");
nf7_test_run(&this->test);
nf7_util_log_info("all tests are triggered");
nf7util_log_info("triggering tests...");
nf7test_run(&this->test);
nf7util_log_info("all tests are triggered");
run_cancel_(this);
}
static void run_single_test_(
struct nf7_test* test, const char* name, nf7_test_func func) {
struct nf7test* test, const char* name, nf7test_func func) {
assert(nullptr != test);
assert(nullptr != name);
assert(nullptr != func);
struct nf7_core_test_run* this = test->data;
struct nf7core_test_run* this = test->data;
nf7_util_log_info("running test: %s", name);
nf7util_log_info("running test: %s", name);
this->running_test_name = name;
const bool result = func(&this->test);
@ -111,36 +111,36 @@ static void run_single_test_(
++this->run_tests;
if (result) {
++this->succeeded_tests;
nf7_util_log_info("test succeeded: %s", name);
nf7util_log_info("test succeeded: %s", name);
} else {
nf7_util_log_error("TEST FAILED: %s", name);
nf7util_log_error("TEST FAILED: %s", name);
}
}
static void run_expect_(struct nf7_test* test, bool val, const char* expr) {
static void run_expect_(struct nf7test* test, bool val, const char* expr) {
assert(nullptr != test);
assert(nullptr != expr);
if (val) {
nf7_util_log_debug("expectation is met: %s", expr);
nf7util_log_debug("expectation is met: %s", expr);
} else {
nf7_util_log_error("expectation is NOT met: %s", expr);
nf7util_log_error("expectation is NOT met: %s", expr);
}
}
static void run_finalize_(struct nf7_test* test) {
static void run_finalize_(struct nf7test* test) {
assert(nullptr != test);
struct nf7_core_test_run* this = test->data;
struct nf7core_test_run* this = test->data;
if (0 < this->run_tests) {
if (this->succeeded_tests == this->run_tests) {
nf7_util_log_info(
nf7util_log_info(
"all tests (%" PRIu64 ") has passed! :)",
this->run_tests);
} else {
nf7_util_log_warn(
nf7util_log_warn(
"%" PRIu64 "/%" PRIu64 " tests have FAILED! X(",
this->run_tests - this->succeeded_tests,
this->run_tests);
}
}
nf7_util_malloc_del(this->malloc, this);
nf7util_malloc_del(this->malloc, this);
}

36
main.c
View File

@ -19,13 +19,13 @@ static void cb_close_all_handles_(uv_handle_t*, void*);
int main(int argc, char** argv) {
nf7_util_log_info("HELLO :)");
struct nf7_util_malloc malloc = {0};
nf7util_log_info("HELLO :)");
struct nf7util_malloc malloc = {0};
// init loop
uv_loop_t uv;
if (0 != nf7_util_log_uv(uv_loop_init(&uv))) {
nf7_util_log_error("failed to init main loop");
if (0 != nf7util_log_uv(uv_loop_init(&uv))) {
nf7util_log_error("failed to init main loop");
return EXIT_FAILURE;
}
struct nf7 nf7 = {
@ -37,51 +37,51 @@ int main(int argc, char** argv) {
};
// load modules
struct nf7_mod* nf7_mods[NF7_CORE_MAX_MODS];
nf7.mods.n = nf7_core_new(&nf7, nf7_mods);
struct nf7mod* nf7_mods[NF7CORE_MAX_MODS];
nf7.mods.n = nf7core_new(&nf7, nf7_mods);
nf7.mods.ptr = nf7_mods;
nf7_util_log_info("loaded %" PRIu32 " modules", nf7.mods.n);
nf7util_log_info("loaded %" PRIu32 " modules", nf7.mods.n);
// main loop
if (0 != nf7_util_log_uv(uv_run(&uv, UV_RUN_DEFAULT))) {
nf7_util_log_error("failed to start main loop");
if (0 != nf7util_log_uv(uv_run(&uv, UV_RUN_DEFAULT))) {
nf7util_log_error("failed to start main loop");
return EXIT_FAILURE;
}
nf7_util_log_info("exiting Nf7...");
nf7util_log_info("exiting Nf7...");
// destroy modules
for (uint32_t i = 0; i < nf7.mods.n; ++i) {
struct nf7_mod* mod = nf7.mods.ptr[i];
assert(mod->meta->delete);
nf7_util_log_debug("unloading module: %s", mod->meta->name);
nf7util_log_debug("unloading module: %s", mod->meta->name);
mod->meta->delete(mod);
}
nf7_util_log_info("unloaded all modules");
nf7util_log_info("unloaded all modules");
// teardown loop
uv_walk(&uv, cb_close_all_handles_, nullptr);
uv_run(&uv, UV_RUN_DEFAULT);
if (0 != uv_loop_close(&uv)) {
nf7_util_log_warn("failed to close main loop gracefully");
nf7util_log_warn("failed to close main loop gracefully");
return EXIT_FAILURE;
}
const uint64_t leaks = nf7_util_malloc_get_count(&malloc);
const uint64_t leaks = nf7util_malloc_get_count(&malloc);
if (0 < leaks) {
nf7_util_log_warn("%" PRIu64 " memory leaks detected", leaks);
nf7util_log_warn("%" PRIu64 " memory leaks detected", leaks);
}
nf7_util_log_info("ALL DONE X)");
nf7util_log_info("ALL DONE X)");
return EXIT_SUCCESS;
}
static void cb_close_all_handles_(uv_handle_t* handle, void*) {
const char* name = uv_handle_type_name(handle->type);
if (!uv_is_closing(handle)) {
nf7_util_log_debug("closing remaining handle: %s", name);
nf7util_log_debug("closing remaining handle: %s", name);
uv_close(handle, nullptr);
} else {
nf7_util_log_debug("remaining handle is closing itself: %s", name);
nf7util_log_debug("remaining handle is closing itself: %s", name);
}
}

4
nf7.h
View File

@ -8,6 +8,8 @@
#include "util/malloc.h"
#define NF7_VERSION UINT32_C(0)
struct nf7;
struct nf7_mod;
struct nf7_mod_meta;
@ -20,7 +22,7 @@ struct nf7 {
const char* const* argv;
uv_loop_t* uv;
struct nf7_util_malloc* malloc;
struct nf7util_malloc* malloc;
struct {
uint32_t n;

View File

@ -4,39 +4,39 @@
#include <stdint.h>
#define NF7_TEST(name) bool name([[maybe_unused]] struct nf7_test* test_)
#define NF7TEST(name) bool name([[maybe_unused]] struct nf7test* test_)
struct nf7;
struct nf7_test;
struct nf7_util_malloc;
struct nf7test;
struct nf7util_malloc;
typedef bool (*nf7_test_func)(struct nf7_test*);
typedef bool (*nf7test_func)(struct nf7test*);
struct nf7_test {
struct nf7* nf7;
struct nf7_util_malloc* malloc;
struct nf7test {
const struct nf7* nf7;
struct nf7util_malloc* malloc;
void* data;
uint64_t refcnt;
void (*run)(struct nf7_test*, const char* name, nf7_test_func);
void (*expect)(struct nf7_test*, bool val, const char* expr);
void (*finalize)(struct nf7_test*);
void (*run)(struct nf7test*, const char* name, nf7test_func);
void (*expect)(struct nf7test*, bool val, const char* expr);
void (*finalize)(struct nf7test*);
};
static inline void nf7_test_ref(struct nf7_test* test) {
static inline void nf7test_ref(struct nf7test* test) {
++test->refcnt;
}
static inline void nf7_test_unref(struct nf7_test* test) {
static inline void nf7test_unref(struct nf7test* test) {
if (--test->refcnt == 0) {
test->finalize(test);
}
}
#define nf7_test_expect(expr) nf7_test_expect_(test_, (expr), #expr)
static inline bool nf7_test_expect_(
struct nf7_test* test, bool val, const char* expr) {
#define nf7test_expect(expr) nf7test_expect_(test_, (expr), #expr)
static inline bool nf7test_expect_(
struct nf7test* test, bool val, const char* expr) {
test->expect(test, val, expr);
return val;
}

View File

@ -1,15 +1,15 @@
#!/bin/bash
tests=$(cat ${@//;/ } | sed -e '/^NF7_TEST(/!d; s|^NF7_TEST(\([^)]*\)).*$|\1|' | xargs echo)
tests=$(cat ${@//;/ } | sed -e '/^NF7TEST(/!d; s|^NF7TEST(\([^)]*\)).*$|\1|' | xargs echo)
echo "#include \"test/common.h\""
echo "#include \"test/run.h\""
echo
echo
echo "bool nf7_test_run(struct nf7_test* test) {"
echo "bool nf7test_run(struct nf7test* test) {"
echo " // $tests"
for test in $tests; do
echo " extern bool $test(struct nf7_test*);"
echo " extern bool $test(struct nf7test*);"
echo " test->run(test, \"$test\", $test);"
done
echo " return true;"

View File

@ -4,4 +4,4 @@
#include "test/common.h"
bool nf7_test_run(struct nf7_test*);
bool nf7test_run(struct nf7test*);

View File

@ -9,6 +9,15 @@ FetchContent_Declare(
)
FetchContent_MakeAvailable(libuv)
# ---- LuaJIT (MIT)
FetchContent_Declare(
luajit
GIT_REPOSITORY https://github.com/LuaJIT/LuaJIT.git
GIT_TAG 8635cbabf3094c4d8bd00578c7d812bea87bb2d3
)
FetchContent_Populate(luajit)
include(luajit.cmake)
# ---- OpenGL
find_package(OpenGL REQUIRED GLOBAL)
add_library(OpenGL ALIAS OpenGL::GL)

56
thirdparty/luajit.cmake vendored Normal file
View File

@ -0,0 +1,56 @@
set(src "${luajit_SOURCE_DIR}/src")
if (UNIX)
find_program(MAKE make REQUIRED)
set(lib "${src}/libluajit.a")
add_custom_target(luajit-build
COMMAND
${MAKE} -j BUILDMODE=static CFLAGS=-fPIC CXX=${CMAKE_CXX_COMPILER} CC=${CMAKE_C_COMPILER}
WORKING_DIRECTORY "${luajit_SOURCE_DIR}"
VERBATIM
)
# To enable assertions, add the following options:
# XCFLAGS="-DLUA_USE_APICHECK -DLUA_USE_ASSERT -Og -g"
elseif (MINGW)
find_program(MAKE mingw32-make REQUIRED)
set(lib "${src}/libluajit.a")
add_custom_target(luajit-build
COMMAND ${MAKE} -j BUILDMODE=static CFLAGS=-fPIC
WORKING_DIRECTORY "${luajit_SOURCE_DIR}/src"
VERBATIM
)
elseif (MSVC)
set(lib "${src}/lua51.lib")
add_custom_command(
OUTPUT "${lib}"
COMMAND msvcbuild.bat static
DEPENDS "${luajit_BINARY_DIR}/skip_build"
WORKING_DIRECTORY "${src}"
VERBATIM
)
add_custom_target(luajit-build SOURCES "${lib}")
else()
message(ERROR "unknown environment")
endif()
add_library(luajit-imported STATIC IMPORTED)
set_target_properties(luajit-imported PROPERTIES
IMPORTED_LOCATION "${lib}"
)
add_dependencies(luajit-imported luajit-build)
add_library(luajit INTERFACE)
target_link_libraries(luajit
INTERFACE luajit-imported $<$<PLATFORM_ID:Linux>:m>
)
target_include_directories(luajit SYSTEM BEFORE
INTERFACE "${src}"
)

View File

@ -14,29 +14,29 @@
//
// When you need an array of integers, the following array structs are
// available:
// - nf7_util_array_u8 / nf7_util_array_s8
// - nf7_util_array_u16 / nf7_util_array_s16
// - nf7_util_array_u32 / nf7_util_array_s32
// - nf7_util_array_u64 / nf7_util_array_s64
// - nf7util_array_u8 / nf7util_array_s8
// - nf7util_array_u16 / nf7util_array_s16
// - nf7util_array_u32 / nf7util_array_s32
// - nf7util_array_u64 / nf7util_array_s64
//
// When you need an array of any other types, expand NF7_UTIL_ARRAY macro on
// When you need an array of any other types, expand NF7UTIL_ARRAY macro on
// your *.h like this:
// `NF7_UTIL_ARRAY(my_array, struct A);`
// In addition, expand `NF7_UTIL_ARRAY_IMPL` macro on your *.c like this:
// `NF7_UTIL_ARRAY_IMPL(, my_array, struct A);`
// `NF7UTIL_ARRAY(my_array, struct A);`
// In addition, expand `NF7UTIL_ARRAY_IMPL` macro on your *.c like this:
// `NF7UTIL_ARRAY_IMPL(, my_array, struct A);`
// After that, `struct my_array` can be used as an array struct.
//
// If you need the functions be inline, expand NF7_UTIL_ARRAY_INLINE macro on
// your *.h as same as NF7_UTIL_ARRAY but NF7_UTIL_ARRAY_IMPL is unnecessary.
// If you need the functions be inline, expand NF7UTIL_ARRAY_INLINE macro on
// your *.h as same as NF7UTIL_ARRAY but NF7UTIL_ARRAY_IMPL is unnecessary.
//
// You can see declarations of the functions on a definition of
// NF7_UTIL_ARRAY_DECL macro. They all are prefixed by a name of your array
// NF7UTIL_ARRAY_DECL macro. They all are prefixed by a name of your array
// struct.
#define NF7_UTIL_ARRAY_TYPE(PREFIX, T) \
#define NF7UTIL_ARRAY_TYPE(PREFIX, T) \
struct PREFIX { \
struct nf7_util_malloc* malloc; \
struct nf7util_malloc* malloc; \
\
uint64_t n; \
T* ptr; \
@ -44,8 +44,8 @@
static_assert(true)
#define NF7_UTIL_ARRAY_DECL(ATTR, PREFIX, T) \
ATTR void PREFIX##_init(struct PREFIX*, struct nf7_util_malloc*); \
#define NF7UTIL_ARRAY_DECL(ATTR, PREFIX, T) \
ATTR void PREFIX##_init(struct PREFIX*, struct nf7util_malloc*); \
ATTR void PREFIX##_deinit(struct PREFIX*); \
ATTR bool PREFIX##_resize(struct PREFIX*, uint64_t); \
ATTR bool PREFIX##_insert(struct PREFIX*, uint64_t, T); \
@ -55,8 +55,8 @@
static_assert(true)
#define NF7_UTIL_ARRAY_IMPL(ATTR, PREFIX, T) \
ATTR void PREFIX##_init(struct PREFIX* this, struct nf7_util_malloc* malloc) { \
#define NF7UTIL_ARRAY_IMPL(ATTR, PREFIX, T) \
ATTR void PREFIX##_init(struct PREFIX* this, struct nf7util_malloc* malloc) { \
assert(nullptr != this); \
assert(nullptr != malloc); \
*this = (struct PREFIX) { \
@ -65,7 +65,7 @@
} \
ATTR void PREFIX##_deinit(struct PREFIX* this) { \
assert(nullptr != this); \
nf7_util_malloc_del(this->malloc, this->ptr); \
nf7util_malloc_del(this->malloc, this->ptr); \
*this = (struct PREFIX) {0}; \
} \
\
@ -78,7 +78,7 @@
const bool extend = this->n < n; \
\
T* const newptr = \
nf7_util_malloc_renew(this->malloc, this->ptr, n*sizeof(T)); \
nf7util_malloc_renew(this->malloc, this->ptr, n*sizeof(T)); \
if (0 < n && nullptr == newptr) { \
if (extend) { return false; } \
} else { \
@ -146,23 +146,23 @@
static_assert(true)
#define NF7_UTIL_ARRAY(PREFIX, T) \
NF7_UTIL_ARRAY_TYPE(PREFIX, T); \
NF7_UTIL_ARRAY_DECL(, PREFIX, T); \
#define NF7UTIL_ARRAY(PREFIX, T) \
NF7UTIL_ARRAY_TYPE(PREFIX, T); \
NF7UTIL_ARRAY_DECL(, PREFIX, T); \
static_assert(true)
#define NF7_UTIL_ARRAY_INLINE(PREFIX, T) \
NF7_UTIL_ARRAY_TYPE(PREFIX, T); \
NF7_UTIL_ARRAY_DECL(static inline, PREFIX, T); \
NF7_UTIL_ARRAY_IMPL(static inline, PREFIX, T); \
#define NF7UTIL_ARRAY_INLINE(PREFIX, T) \
NF7UTIL_ARRAY_TYPE(PREFIX, T); \
NF7UTIL_ARRAY_DECL(static inline, PREFIX, T); \
NF7UTIL_ARRAY_IMPL(static inline, PREFIX, T); \
static_assert(true)
NF7_UTIL_ARRAY_INLINE(nf7_util_array_u8 , uint8_t);
NF7_UTIL_ARRAY_INLINE(nf7_util_array_u16, uint16_t);
NF7_UTIL_ARRAY_INLINE(nf7_util_array_u32, uint32_t);
NF7_UTIL_ARRAY_INLINE(nf7_util_array_u64, uint64_t);
NF7_UTIL_ARRAY_INLINE(nf7_util_array_s8 , int8_t);
NF7_UTIL_ARRAY_INLINE(nf7_util_array_s16, int16_t);
NF7_UTIL_ARRAY_INLINE(nf7_util_array_s32, int32_t);
NF7_UTIL_ARRAY_INLINE(nf7_util_array_s64, int64_t);
NF7UTIL_ARRAY_INLINE(nf7util_array_u8 , uint8_t);
NF7UTIL_ARRAY_INLINE(nf7util_array_u16, uint16_t);
NF7UTIL_ARRAY_INLINE(nf7util_array_u32, uint32_t);
NF7UTIL_ARRAY_INLINE(nf7util_array_u64, uint64_t);
NF7UTIL_ARRAY_INLINE(nf7util_array_s8 , int8_t);
NF7UTIL_ARRAY_INLINE(nf7util_array_s16, int16_t);
NF7UTIL_ARRAY_INLINE(nf7util_array_s32, int32_t);
NF7UTIL_ARRAY_INLINE(nf7util_array_s64, int64_t);

View File

@ -7,225 +7,225 @@
#define TEST_(T) do { \
struct nf7_util_array_##T sut; \
nf7_util_array_##T##_init(&sut, test_->malloc); \
struct nf7util_array_##T sut; \
nf7util_array_##T##_init(&sut, test_->malloc); \
const bool ret = \
nf7_test_expect(nf7_util_array_##T##_resize(&sut, 32)) && \
nf7_test_expect(32 == sut.n); \
nf7_util_array_##T##_deinit(&sut); \
nf7test_expect(nf7util_array_##T##_resize(&sut, 32)) && \
nf7test_expect(32 == sut.n); \
nf7util_array_##T##_deinit(&sut); \
return ret; \
} while (0)
NF7_TEST(nf7_util_array_u8_test_resize) { TEST_(u8); }
NF7_TEST(nf7_util_array_u16_test_resize) { TEST_(u16); }
NF7_TEST(nf7_util_array_u32_test_resize) { TEST_(u32); }
NF7_TEST(nf7_util_array_u64_test_resize) { TEST_(u64); }
NF7_TEST(nf7_util_array_s8_test_resize) { TEST_(s8); }
NF7_TEST(nf7_util_array_s16_test_resize) { TEST_(s16); }
NF7_TEST(nf7_util_array_s32_test_resize) { TEST_(s32); }
NF7_TEST(nf7_util_array_s64_test_resize) { TEST_(s64); }
NF7TEST(nf7util_array_u8_test_resize) { TEST_(u8); }
NF7TEST(nf7util_array_u16_test_resize) { TEST_(u16); }
NF7TEST(nf7util_array_u32_test_resize) { TEST_(u32); }
NF7TEST(nf7util_array_u64_test_resize) { TEST_(u64); }
NF7TEST(nf7util_array_s8_test_resize) { TEST_(s8); }
NF7TEST(nf7util_array_s16_test_resize) { TEST_(s16); }
NF7TEST(nf7util_array_s32_test_resize) { TEST_(s32); }
NF7TEST(nf7util_array_s64_test_resize) { TEST_(s64); }
#undef TEST_
#define TEST_(T) do { \
struct nf7_util_array_##T sut; \
nf7_util_array_##T##_init(&sut, test_->malloc); \
struct nf7util_array_##T sut; \
nf7util_array_##T##_init(&sut, test_->malloc); \
const bool ret = \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, 0, 66)) && \
nf7_test_expect(1 == sut.n); \
nf7_test_expect(66 == sut.ptr[0]); \
nf7_util_array_##T##_deinit(&sut); \
nf7test_expect(nf7util_array_##T##_insert(&sut, 0, 66)) && \
nf7test_expect(1 == sut.n); \
nf7test_expect(66 == sut.ptr[0]); \
nf7util_array_##T##_deinit(&sut); \
return ret; \
} while (0)
NF7_TEST(nf7_util_array_u8_test_insert_first) { TEST_(u8); }
NF7_TEST(nf7_util_array_u16_test_insert_first) { TEST_(u16); }
NF7_TEST(nf7_util_array_u32_test_insert_first) { TEST_(u32); }
NF7_TEST(nf7_util_array_u64_test_insert_first) { TEST_(u64); }
NF7_TEST(nf7_util_array_s8_test_insert_first) { TEST_(s8); }
NF7_TEST(nf7_util_array_s16_test_insert_first) { TEST_(s16); }
NF7_TEST(nf7_util_array_s32_test_insert_first) { TEST_(s32); }
NF7_TEST(nf7_util_array_s64_test_insert_first) { TEST_(s64); }
NF7TEST(nf7util_array_u8_test_insert_first) { TEST_(u8); }
NF7TEST(nf7util_array_u16_test_insert_first) { TEST_(u16); }
NF7TEST(nf7util_array_u32_test_insert_first) { TEST_(u32); }
NF7TEST(nf7util_array_u64_test_insert_first) { TEST_(u64); }
NF7TEST(nf7util_array_s8_test_insert_first) { TEST_(s8); }
NF7TEST(nf7util_array_s16_test_insert_first) { TEST_(s16); }
NF7TEST(nf7util_array_s32_test_insert_first) { TEST_(s32); }
NF7TEST(nf7util_array_s64_test_insert_first) { TEST_(s64); }
#undef TEST_
#define TEST_(T) do { \
struct nf7_util_array_##T sut; \
nf7_util_array_##T##_init(&sut, test_->malloc); \
struct nf7util_array_##T sut; \
nf7util_array_##T##_init(&sut, test_->malloc); \
const bool ret = \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, 0, 66)) && \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, 0, 77)) && \
nf7_test_expect(2 == sut.n) && \
nf7_test_expect(77 == sut.ptr[0]) && \
nf7_test_expect(66 == sut.ptr[1]); \
nf7_util_array_##T##_deinit(&sut); \
nf7test_expect(nf7util_array_##T##_insert(&sut, 0, 66)) && \
nf7test_expect(nf7util_array_##T##_insert(&sut, 0, 77)) && \
nf7test_expect(2 == sut.n) && \
nf7test_expect(77 == sut.ptr[0]) && \
nf7test_expect(66 == sut.ptr[1]); \
nf7util_array_##T##_deinit(&sut); \
return ret; \
} while (0)
NF7_TEST(nf7_util_array_u8_test_insert_head) { TEST_(u8); }
NF7_TEST(nf7_util_array_u16_test_insert_head) { TEST_(u16); }
NF7_TEST(nf7_util_array_u32_test_insert_head) { TEST_(u32); }
NF7_TEST(nf7_util_array_u64_test_insert_head) { TEST_(u64); }
NF7_TEST(nf7_util_array_s8_test_insert_head) { TEST_(s8); }
NF7_TEST(nf7_util_array_s16_test_insert_head) { TEST_(s16); }
NF7_TEST(nf7_util_array_s32_test_insert_head) { TEST_(s32); }
NF7_TEST(nf7_util_array_s64_test_insert_head) { TEST_(s64); }
NF7TEST(nf7util_array_u8_test_insert_head) { TEST_(u8); }
NF7TEST(nf7util_array_u16_test_insert_head) { TEST_(u16); }
NF7TEST(nf7util_array_u32_test_insert_head) { TEST_(u32); }
NF7TEST(nf7util_array_u64_test_insert_head) { TEST_(u64); }
NF7TEST(nf7util_array_s8_test_insert_head) { TEST_(s8); }
NF7TEST(nf7util_array_s16_test_insert_head) { TEST_(s16); }
NF7TEST(nf7util_array_s32_test_insert_head) { TEST_(s32); }
NF7TEST(nf7util_array_s64_test_insert_head) { TEST_(s64); }
#undef TEST_
#define TEST_(T) do { \
struct nf7_util_array_##T sut; \
nf7_util_array_##T##_init(&sut, test_->malloc); \
struct nf7util_array_##T sut; \
nf7util_array_##T##_init(&sut, test_->malloc); \
const bool ret = \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
nf7_test_expect(2 == sut.n) && \
nf7_test_expect(66 == sut.ptr[0]) && \
nf7_test_expect(77 == sut.ptr[1]); \
nf7_util_array_##T##_deinit(&sut); \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
nf7test_expect(2 == sut.n) && \
nf7test_expect(66 == sut.ptr[0]) && \
nf7test_expect(77 == sut.ptr[1]); \
nf7util_array_##T##_deinit(&sut); \
return ret; \
} while (0)
NF7_TEST(nf7_util_array_u8_test_insert_tail) { TEST_(u8); }
NF7_TEST(nf7_util_array_u16_test_insert_tail) { TEST_(u16); }
NF7_TEST(nf7_util_array_u32_test_insert_tail) { TEST_(u32); }
NF7_TEST(nf7_util_array_u64_test_insert_tail) { TEST_(u64); }
NF7_TEST(nf7_util_array_s8_test_insert_tail) { TEST_(s8); }
NF7_TEST(nf7_util_array_s16_test_insert_tail) { TEST_(s16); }
NF7_TEST(nf7_util_array_s32_test_insert_tail) { TEST_(s32); }
NF7_TEST(nf7_util_array_s64_test_insert_tail) { TEST_(s64); }
NF7TEST(nf7util_array_u8_test_insert_tail) { TEST_(u8); }
NF7TEST(nf7util_array_u16_test_insert_tail) { TEST_(u16); }
NF7TEST(nf7util_array_u32_test_insert_tail) { TEST_(u32); }
NF7TEST(nf7util_array_u64_test_insert_tail) { TEST_(u64); }
NF7TEST(nf7util_array_s8_test_insert_tail) { TEST_(s8); }
NF7TEST(nf7util_array_s16_test_insert_tail) { TEST_(s16); }
NF7TEST(nf7util_array_s32_test_insert_tail) { TEST_(s32); }
NF7TEST(nf7util_array_s64_test_insert_tail) { TEST_(s64); }
#undef TEST_
#define TEST_(T) do { \
struct nf7_util_array_##T sut; \
nf7_util_array_##T##_init(&sut, test_->malloc); \
struct nf7util_array_##T sut; \
nf7util_array_##T##_init(&sut, test_->malloc); \
const bool ret = \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, 1, 77)) && \
nf7_test_expect(3 == sut.n) && \
nf7_test_expect(66 == sut.ptr[0]) && \
nf7_test_expect(77 == sut.ptr[1]) && \
nf7_test_expect(88 == sut.ptr[2]); \
nf7_util_array_##T##_deinit(&sut); \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
nf7test_expect(nf7util_array_##T##_insert(&sut, 1, 77)) && \
nf7test_expect(3 == sut.n) && \
nf7test_expect(66 == sut.ptr[0]) && \
nf7test_expect(77 == sut.ptr[1]) && \
nf7test_expect(88 == sut.ptr[2]); \
nf7util_array_##T##_deinit(&sut); \
return ret; \
} while (0)
NF7_TEST(nf7_util_array_u8_test_insert_mid) { TEST_(u8); }
NF7_TEST(nf7_util_array_u16_test_insert_mid) { TEST_(u16); }
NF7_TEST(nf7_util_array_u32_test_insert_mid) { TEST_(u32); }
NF7_TEST(nf7_util_array_u64_test_insert_mid) { TEST_(u64); }
NF7_TEST(nf7_util_array_s8_test_insert_mid) { TEST_(s8); }
NF7_TEST(nf7_util_array_s16_test_insert_mid) { TEST_(s16); }
NF7_TEST(nf7_util_array_s32_test_insert_mid) { TEST_(s32); }
NF7_TEST(nf7_util_array_s64_test_insert_mid) { TEST_(s64); }
NF7TEST(nf7util_array_u8_test_insert_mid) { TEST_(u8); }
NF7TEST(nf7util_array_u16_test_insert_mid) { TEST_(u16); }
NF7TEST(nf7util_array_u32_test_insert_mid) { TEST_(u32); }
NF7TEST(nf7util_array_u64_test_insert_mid) { TEST_(u64); }
NF7TEST(nf7util_array_s8_test_insert_mid) { TEST_(s8); }
NF7TEST(nf7util_array_s16_test_insert_mid) { TEST_(s16); }
NF7TEST(nf7util_array_s32_test_insert_mid) { TEST_(s32); }
NF7TEST(nf7util_array_s64_test_insert_mid) { TEST_(s64); }
#undef TEST_
#define TEST_(T) do { \
struct nf7_util_array_##T sut; \
nf7_util_array_##T##_init(&sut, test_->malloc); \
struct nf7util_array_##T sut; \
nf7util_array_##T##_init(&sut, test_->malloc); \
const bool ret = \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
(nf7_util_array_##T##_remove(&sut, 0), true) && \
nf7_test_expect(2 == sut.n) && \
nf7_test_expect(77 == sut.ptr[0]) && \
nf7_test_expect(88 == sut.ptr[1]); \
nf7_util_array_##T##_deinit(&sut); \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
(nf7util_array_##T##_remove(&sut, 0), true) && \
nf7test_expect(2 == sut.n) && \
nf7test_expect(77 == sut.ptr[0]) && \
nf7test_expect(88 == sut.ptr[1]); \
nf7util_array_##T##_deinit(&sut); \
return ret; \
} while (0)
NF7_TEST(nf7_util_array_u8_test_remove_head) { TEST_(u8); }
NF7_TEST(nf7_util_array_u16_test_remove_head) { TEST_(u16); }
NF7_TEST(nf7_util_array_u32_test_remove_head) { TEST_(u32); }
NF7_TEST(nf7_util_array_u64_test_remove_head) { TEST_(u64); }
NF7_TEST(nf7_util_array_s8_test_remove_head) { TEST_(s8); }
NF7_TEST(nf7_util_array_s16_test_remove_head) { TEST_(s16); }
NF7_TEST(nf7_util_array_s32_test_remove_head) { TEST_(s32); }
NF7_TEST(nf7_util_array_s64_test_remove_head) { TEST_(s64); }
NF7TEST(nf7util_array_u8_test_remove_head) { TEST_(u8); }
NF7TEST(nf7util_array_u16_test_remove_head) { TEST_(u16); }
NF7TEST(nf7util_array_u32_test_remove_head) { TEST_(u32); }
NF7TEST(nf7util_array_u64_test_remove_head) { TEST_(u64); }
NF7TEST(nf7util_array_s8_test_remove_head) { TEST_(s8); }
NF7TEST(nf7util_array_s16_test_remove_head) { TEST_(s16); }
NF7TEST(nf7util_array_s32_test_remove_head) { TEST_(s32); }
NF7TEST(nf7util_array_s64_test_remove_head) { TEST_(s64); }
#undef TEST_
#define TEST_(T) do { \
struct nf7_util_array_##T sut; \
nf7_util_array_##T##_init(&sut, test_->malloc); \
struct nf7util_array_##T sut; \
nf7util_array_##T##_init(&sut, test_->malloc); \
const bool ret = \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
(nf7_util_array_##T##_remove(&sut, UINT64_MAX), true) && \
nf7_test_expect(2 == sut.n) && \
nf7_test_expect(66 == sut.ptr[0]) && \
nf7_test_expect(77 == sut.ptr[1]); \
nf7_util_array_##T##_deinit(&sut); \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
(nf7util_array_##T##_remove(&sut, UINT64_MAX), true) && \
nf7test_expect(2 == sut.n) && \
nf7test_expect(66 == sut.ptr[0]) && \
nf7test_expect(77 == sut.ptr[1]); \
nf7util_array_##T##_deinit(&sut); \
return ret; \
} while (0)
NF7_TEST(nf7_util_array_u8_test_remove_tail) { TEST_(u8); }
NF7_TEST(nf7_util_array_u16_test_remove_tail) { TEST_(u16); }
NF7_TEST(nf7_util_array_u32_test_remove_tail) { TEST_(u32); }
NF7_TEST(nf7_util_array_u64_test_remove_tail) { TEST_(u64); }
NF7_TEST(nf7_util_array_s8_test_remove_tail) { TEST_(s8); }
NF7_TEST(nf7_util_array_s16_test_remove_tail) { TEST_(s16); }
NF7_TEST(nf7_util_array_s32_test_remove_tail) { TEST_(s32); }
NF7_TEST(nf7_util_array_s64_test_remove_tail) { TEST_(s64); }
NF7TEST(nf7util_array_u8_test_remove_tail) { TEST_(u8); }
NF7TEST(nf7util_array_u16_test_remove_tail) { TEST_(u16); }
NF7TEST(nf7util_array_u32_test_remove_tail) { TEST_(u32); }
NF7TEST(nf7util_array_u64_test_remove_tail) { TEST_(u64); }
NF7TEST(nf7util_array_s8_test_remove_tail) { TEST_(s8); }
NF7TEST(nf7util_array_s16_test_remove_tail) { TEST_(s16); }
NF7TEST(nf7util_array_s32_test_remove_tail) { TEST_(s32); }
NF7TEST(nf7util_array_s64_test_remove_tail) { TEST_(s64); }
#undef TEST_
#define TEST_(T) do { \
struct nf7_util_array_##T sut; \
nf7_util_array_##T##_init(&sut, test_->malloc); \
struct nf7util_array_##T sut; \
nf7util_array_##T##_init(&sut, test_->malloc); \
const bool ret = \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
(nf7_util_array_##T##_remove(&sut, 1), true) && \
nf7_test_expect(2 == sut.n) && \
nf7_test_expect(66 == sut.ptr[0]) && \
nf7_test_expect(88 == sut.ptr[1]); \
nf7_util_array_##T##_deinit(&sut); \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
(nf7util_array_##T##_remove(&sut, 1), true) && \
nf7test_expect(2 == sut.n) && \
nf7test_expect(66 == sut.ptr[0]) && \
nf7test_expect(88 == sut.ptr[1]); \
nf7util_array_##T##_deinit(&sut); \
return ret; \
} while (0)
NF7_TEST(nf7_util_array_u8_test_remove_mid) { TEST_(u8); }
NF7_TEST(nf7_util_array_u16_test_remove_mid) { TEST_(u16); }
NF7_TEST(nf7_util_array_u32_test_remove_mid) { TEST_(u32); }
NF7_TEST(nf7_util_array_u64_test_remove_mid) { TEST_(u64); }
NF7_TEST(nf7_util_array_s8_test_remove_mid) { TEST_(s8); }
NF7_TEST(nf7_util_array_s16_test_remove_mid) { TEST_(s16); }
NF7_TEST(nf7_util_array_s32_test_remove_mid) { TEST_(s32); }
NF7_TEST(nf7_util_array_s64_test_remove_mid) { TEST_(s64); }
NF7TEST(nf7util_array_u8_test_remove_mid) { TEST_(u8); }
NF7TEST(nf7util_array_u16_test_remove_mid) { TEST_(u16); }
NF7TEST(nf7util_array_u32_test_remove_mid) { TEST_(u32); }
NF7TEST(nf7util_array_u64_test_remove_mid) { TEST_(u64); }
NF7TEST(nf7util_array_s8_test_remove_mid) { TEST_(s8); }
NF7TEST(nf7util_array_s16_test_remove_mid) { TEST_(s16); }
NF7TEST(nf7util_array_s32_test_remove_mid) { TEST_(s32); }
NF7TEST(nf7util_array_s64_test_remove_mid) { TEST_(s64); }
#undef TEST_
#define TEST_(T) do { \
struct nf7_util_array_##T sut; \
nf7_util_array_##T##_init(&sut, test_->malloc); \
struct nf7util_array_##T sut; \
nf7util_array_##T##_init(&sut, test_->malloc); \
uint64_t idx; \
const bool ret = \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
nf7_test_expect(nf7_util_array_##T##_find(&sut, &idx, 77)) && \
nf7_test_expect(1 == idx); \
nf7_util_array_##T##_deinit(&sut); \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
nf7test_expect(nf7util_array_##T##_find(&sut, &idx, 77)) && \
nf7test_expect(1 == idx); \
nf7util_array_##T##_deinit(&sut); \
return ret; \
} while (0)
NF7_TEST(nf7_util_array_u8_test_find_found) { TEST_(u8); }
NF7_TEST(nf7_util_array_u16_test_find_found) { TEST_(u16); }
NF7_TEST(nf7_util_array_u32_test_find_found) { TEST_(u32); }
NF7_TEST(nf7_util_array_u64_test_find_found) { TEST_(u64); }
NF7_TEST(nf7_util_array_s8_test_find_found) { TEST_(s8); }
NF7_TEST(nf7_util_array_s16_test_find_found) { TEST_(s16); }
NF7_TEST(nf7_util_array_s32_test_find_found) { TEST_(s32); }
NF7_TEST(nf7_util_array_s64_test_find_found) { TEST_(s64); }
NF7TEST(nf7util_array_u8_test_find_found) { TEST_(u8); }
NF7TEST(nf7util_array_u16_test_find_found) { TEST_(u16); }
NF7TEST(nf7util_array_u32_test_find_found) { TEST_(u32); }
NF7TEST(nf7util_array_u64_test_find_found) { TEST_(u64); }
NF7TEST(nf7util_array_s8_test_find_found) { TEST_(s8); }
NF7TEST(nf7util_array_s16_test_find_found) { TEST_(s16); }
NF7TEST(nf7util_array_s32_test_find_found) { TEST_(s32); }
NF7TEST(nf7util_array_s64_test_find_found) { TEST_(s64); }
#undef TEST_
#define TEST_(T) do { \
struct nf7_util_array_##T sut; \
nf7_util_array_##T##_init(&sut, test_->malloc); \
struct nf7util_array_##T sut; \
nf7util_array_##T##_init(&sut, test_->malloc); \
uint64_t idx; \
const bool ret = \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
nf7_test_expect(!nf7_util_array_##T##_find(&sut, &idx, 99)); \
nf7_util_array_##T##_deinit(&sut); \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
nf7test_expect(!nf7util_array_##T##_find(&sut, &idx, 99)); \
nf7util_array_##T##_deinit(&sut); \
return ret; \
} while (0)
NF7_TEST(nf7_util_array_u8_test_find_notfound) { TEST_(u8); }
NF7_TEST(nf7_util_array_u16_test_find_notfound) { TEST_(u16); }
NF7_TEST(nf7_util_array_u32_test_find_notfound) { TEST_(u32); }
NF7_TEST(nf7_util_array_u64_test_find_notfound) { TEST_(u64); }
NF7_TEST(nf7_util_array_s8_test_find_notfound) { TEST_(s8); }
NF7_TEST(nf7_util_array_s16_test_find_notfound) { TEST_(s16); }
NF7_TEST(nf7_util_array_s32_test_find_notfound) { TEST_(s32); }
NF7_TEST(nf7_util_array_s64_test_find_notfound) { TEST_(s64); }
NF7TEST(nf7util_array_u8_test_find_notfound) { TEST_(u8); }
NF7TEST(nf7util_array_u16_test_find_notfound) { TEST_(u16); }
NF7TEST(nf7util_array_u32_test_find_notfound) { TEST_(u32); }
NF7TEST(nf7util_array_u64_test_find_notfound) { TEST_(u64); }
NF7TEST(nf7util_array_s8_test_find_notfound) { TEST_(s8); }
NF7TEST(nf7util_array_s16_test_find_notfound) { TEST_(s16); }
NF7TEST(nf7util_array_s32_test_find_notfound) { TEST_(s32); }
NF7TEST(nf7util_array_s64_test_find_notfound) { TEST_(s64); }
#undef TEST_

View File

@ -9,45 +9,45 @@
#include <uv.h>
#define NF7_UTIL_LOG_CURRENT_FILE \
#define NF7UTIL_LOG_CURRENT_FILE \
((const char*) __FILE__ + NF7_PROJECT_DIR_LEN)
#define nf7_util_log(level, file, line, func, fmt, ...) \
#define nf7util_log(level, file, line, func, fmt, ...) \
printf(level "|%s:%" PRIu64 "|%s|" fmt "\n", file, (uint64_t) line, func __VA_OPT__(,) __VA_ARGS__)
#define nf7_util_log_sugar(level, ...) \
nf7_util_log(level, NF7_UTIL_LOG_CURRENT_FILE, __LINE__, __func__, __VA_ARGS__)
#define nf7util_log_sugar(level, ...) \
nf7util_log(level, NF7UTIL_LOG_CURRENT_FILE, __LINE__, __func__, __VA_ARGS__)
#if !defined(NDEBUG)
# define nf7_util_log_debug(...) \
nf7_util_log_sugar("DBG", __VA_ARGS__)
# define nf7util_log_debug(...) \
nf7util_log_sugar("DBG", __VA_ARGS__)
#else
# define nf7_util_log_debug(fmt, ...) do { } while (0)
# define nf7util_log_debug(fmt, ...) do { } while (0)
#endif
#define nf7_util_log_info(...) \
nf7_util_log_sugar("INF", __VA_ARGS__)
#define nf7_util_log_warn(...) \
nf7_util_log_sugar("WRN", __VA_ARGS__)
#define nf7_util_log_error(...) \
nf7_util_log_sugar("ERR", __VA_ARGS__)
#define nf7util_log_info(...) \
nf7util_log_sugar("INF", __VA_ARGS__)
#define nf7util_log_warn(...) \
nf7util_log_sugar("WRN", __VA_ARGS__)
#define nf7util_log_error(...) \
nf7util_log_sugar("ERR", __VA_ARGS__)
// ---- libuv utils
#define nf7_util_log_uv(ret) \
nf7_util_log_uv_((ret), NF7_UTIL_LOG_CURRENT_FILE, __LINE__, __func__)
static inline int nf7_util_log_uv_(
#define nf7util_log_uv(ret) \
nf7util_log_uv_((ret), NF7UTIL_LOG_CURRENT_FILE, __LINE__, __func__)
static inline int nf7util_log_uv_(
int ret, const char* file, uint64_t line, const char* func) {
if (0 != ret) {
nf7_util_log("INF", file, line, func, "uv api error: %s", uv_strerror(ret));
nf7util_log("INF", file, line, func, "uv api error: %s", uv_strerror(ret));
}
return ret;
}
#define nf7_util_log_uv_assert(ret) \
nf7_util_log_uv_((ret), NF7_UTIL_LOG_CURRENT_FILE, __LINE__, __func__)
static inline int nf7_util_log_uv_assert_(
#define nf7util_log_uv_assert(ret) \
nf7util_log_uv_((ret), NF7UTIL_LOG_CURRENT_FILE, __LINE__, __func__)
static inline int nf7util_log_uv_assert_(
int ret, const char* file, uint64_t line, const char* func) {
nf7_util_log_uv_(ret, file, line, func);
nf7util_log_uv_(ret, file, line, func);
assert(0 == ret);
return ret;
}

View File

@ -4,14 +4,14 @@
#include <assert.h>
void* nf7_util_malloc_stack_new(struct nf7_util_malloc_stack* const this, const uint64_t n) {
void* nf7util_malloc_stack_new(struct nf7util_malloc_stack* const this, const uint64_t n) {
assert(nullptr != this);
if (this->end < this->tail + n) {
const uint64_t tail = this->tail - this->begin;
const uint64_t size = tail + n;
uint8_t* const ptr = nf7_util_malloc_renew(this->malloc, this->begin, size);
uint8_t* const ptr = nf7util_malloc_renew(this->malloc, this->begin, size);
if (nullptr == ptr) {
return nullptr;
}
@ -27,7 +27,7 @@ void* nf7_util_malloc_stack_new(struct nf7_util_malloc_stack* const this, const
return this->head;
}
void nf7_util_malloc_stack_del(struct nf7_util_malloc_stack* const this, void* const ptr) {
void nf7util_malloc_stack_del(struct nf7util_malloc_stack* const this, void* const ptr) {
assert(nullptr != this);
assert(0 < this->refcnt);

View File

@ -9,9 +9,9 @@
// ---- General Purpose Memory Allocator
// The current implementation is just a wrap of malloc/free.
struct nf7_util_malloc { atomic_uint_least64_t count; };
struct nf7util_malloc { atomic_uint_least64_t count; };
static inline void* nf7_util_malloc_new(struct nf7_util_malloc* this, uint64_t n) {
static inline void* nf7util_malloc_new(struct nf7util_malloc* this, uint64_t n) {
assert(nullptr != this);
if (0 == n) {
@ -27,7 +27,7 @@ static inline void* nf7_util_malloc_new(struct nf7_util_malloc* this, uint64_t n
assert(UINT64_MAX > prev_count);
return ret;
}
static inline void nf7_util_malloc_del(struct nf7_util_malloc* this, void* ptr) {
static inline void nf7util_malloc_del(struct nf7util_malloc* this, void* ptr) {
assert(nullptr != this);
if (nullptr != ptr) {
@ -37,25 +37,25 @@ static inline void nf7_util_malloc_del(struct nf7_util_malloc* this, void* ptr)
free(ptr);
}
}
static inline void* nf7_util_malloc_renew(struct nf7_util_malloc* this, void* ptr, uint64_t n) {
static inline void* nf7util_malloc_renew(struct nf7util_malloc* this, void* ptr, uint64_t n) {
assert(nullptr != this);
if (n > 0) {
return nullptr != ptr? realloc(ptr, n): nf7_util_malloc_new(this, n);
return nullptr != ptr? realloc(ptr, n): nf7util_malloc_new(this, n);
} else {
nf7_util_malloc_del(this, ptr);
nf7util_malloc_del(this, ptr);
return nullptr;
}
}
static inline uint64_t nf7_util_malloc_get_count(const struct nf7_util_malloc* this) {
static inline uint64_t nf7util_malloc_get_count(const struct nf7util_malloc* this) {
return atomic_load(&this->count);
}
// ---- Stack Allocator
struct nf7_util_malloc_stack {
struct nf7_util_malloc* malloc;
struct nf7util_malloc_stack {
struct nf7util_malloc* malloc;
uint8_t* begin;
uint8_t* end;
@ -64,5 +64,5 @@ struct nf7_util_malloc_stack {
uint64_t refcnt;
};
void* nf7_util_malloc_stack_new(struct nf7_util_malloc_stack* this, uint64_t n);
void nf7_util_malloc_stack_del(struct nf7_util_malloc_stack* this, void*);
void* nf7util_malloc_stack_new(struct nf7util_malloc_stack* this, uint64_t n);
void nf7util_malloc_stack_del(struct nf7util_malloc_stack* this, void*);

View File

@ -7,17 +7,19 @@
#include "util/malloc.h"
#define NF7_UTIL_REFCNT_DECL(ATTR, T) \
#define NF7UTIL_REFCNT_DECL(ATTR, T) \
ATTR void T##_ref(struct T*); \
ATTR bool T##_unref(struct T*); \
static_assert(true)
#define NF7_UTIL_REFCNT_IMPL(ATTR, T, DELETER) \
#define NF7UTIL_REFCNT_IMPL(ATTR, T, DELETER) \
ATTR void T##_ref(struct T* this) { \
assert(nullptr != this); \
++this->refcnt; \
} \
ATTR bool T##_unref(struct T* this) { \
assert(nullptr != this); \
assert(0 < this->refcnt); \
if (0 == --this->refcnt) { \
{DELETER}; \
@ -27,11 +29,13 @@
} \
static_assert(true)
#define NF7_UTIL_REFCNT_IMPL_ATOMIC(ATTR, T, DELETER) \
#define NF7UTIL_REFCNT_IMPL_ATOMIC(ATTR, T, DELETER) \
ATTR void T##_ref(struct T* this) { \
assert(nullptr != this); \
atomic_fetch_add(&this->refcnt, 1); \
} \
ATTR bool T##_unref(struct T* this) { \
assert(nullptr != this); \
assert(0 < this->refcnt); \
if (1 == atomic_fetch_sub(&this->refcnt, 1)) { \
{DELETER}; \

View File

@ -11,33 +11,33 @@ struct mystruct {
bool deleted;
uint64_t refcnt;
};
NF7_UTIL_REFCNT_IMPL(static inline, mystruct, {this->deleted = true;});
NF7UTIL_REFCNT_IMPL(static inline, mystruct, {this->deleted = true;});
struct mystruct_atomic {
bool deleted;
atomic_uint_least64_t refcnt;
};
NF7_UTIL_REFCNT_IMPL_ATOMIC(static inline, mystruct_atomic, {this->deleted = true;});
NF7UTIL_REFCNT_IMPL_ATOMIC(static inline, mystruct_atomic, {this->deleted = true;});
NF7_TEST(nf7_util_refcnt_test_delete) {
NF7TEST(nf7util_refcnt_test_delete) {
struct mystruct sut = {0};
mystruct_ref(&sut);
mystruct_ref(&sut);
return
nf7_test_expect(!mystruct_unref(&sut)) &&
nf7_test_expect(!sut.deleted) &&
nf7_test_expect(mystruct_unref(&sut)) &&
nf7_test_expect(sut.deleted);
nf7test_expect(!mystruct_unref(&sut)) &&
nf7test_expect(!sut.deleted) &&
nf7test_expect(mystruct_unref(&sut)) &&
nf7test_expect(sut.deleted);
}
NF7_TEST(nf7_util_refcnt_test_atomic_delete) {
NF7TEST(nf7util_refcnt_test_atomic_delete) {
struct mystruct_atomic sut = {0};
mystruct_atomic_ref(&sut);
mystruct_atomic_ref(&sut);
return
nf7_test_expect(!mystruct_atomic_unref(&sut)) &&
nf7_test_expect(!sut.deleted) &&
nf7_test_expect(mystruct_atomic_unref(&sut)) &&
nf7_test_expect(sut.deleted);
nf7test_expect(!mystruct_atomic_unref(&sut)) &&
nf7test_expect(!sut.deleted) &&
nf7test_expect(mystruct_atomic_unref(&sut)) &&
nf7test_expect(sut.deleted);
}

View File

@ -5,65 +5,65 @@
#include "util/malloc.h"
struct nf7_util_signal;
struct nf7_util_signal_recv;
struct nf7util_signal;
struct nf7util_signal_recv;
NF7_UTIL_ARRAY_INLINE(nf7_util_signal_recvs, struct nf7_util_signal_recv*);
NF7UTIL_ARRAY_INLINE(nf7util_signal_recvs, struct nf7util_signal_recv*);
struct nf7_util_signal {
struct nf7_util_malloc* malloc;
struct nf7util_signal {
struct nf7util_malloc* malloc;
bool emitting;
struct nf7_util_signal_recvs recvs;
struct nf7util_signal_recvs recvs;
};
struct nf7_util_signal_recv {
struct nf7_util_signal* signal;
struct nf7util_signal_recv {
struct nf7util_signal* signal;
void* data;
void (*func)(struct nf7_util_signal_recv*);
void (*func)(struct nf7util_signal_recv*);
};
static inline void nf7_util_signal_init(struct nf7_util_signal* this) {
static inline void nf7util_signal_init(struct nf7util_signal* this) {
assert(nullptr != this);
assert(nullptr != this->malloc);
nf7_util_signal_recvs_init(&this->recvs, this->malloc);
nf7util_signal_recvs_init(&this->recvs, this->malloc);
}
static inline void nf7_util_signal_deinit(struct nf7_util_signal* this) {
static inline void nf7util_signal_deinit(struct nf7util_signal* this) {
assert(nullptr != this);
for (uint64_t i = 0; i < this->recvs.n; ++i) {
this->recvs.ptr[i]->signal = nullptr;
}
nf7_util_signal_recvs_deinit(&this->recvs);
nf7util_signal_recvs_deinit(&this->recvs);
}
static inline void nf7_util_signal_emit(struct nf7_util_signal* this) {
static inline void nf7util_signal_emit(struct nf7util_signal* this) {
this->emitting = true;
for (uint64_t i = 0; i < this->recvs.n; ++i) {
struct nf7_util_signal_recv* recv = this->recvs.ptr[i];
struct nf7util_signal_recv* recv = this->recvs.ptr[i];
recv->func(recv);
}
this->emitting = false;
}
static inline void nf7_util_signal_recv_unset(struct nf7_util_signal_recv* this) {
static inline void nf7util_signal_recv_unset(struct nf7util_signal_recv* this) {
assert(nullptr != this);
if (nullptr == this->signal) {
return;
}
nf7_util_signal_recvs_find_and_remove(&this->signal->recvs, this);
nf7util_signal_recvs_find_and_remove(&this->signal->recvs, this);
}
static inline bool nf7_util_signal_recv_set(
struct nf7_util_signal_recv* this, struct nf7_util_signal* signal) {
static inline bool nf7util_signal_recv_set(
struct nf7util_signal_recv* this, struct nf7util_signal* signal) {
assert(nullptr != this);
assert(nullptr != this->func);
assert(!signal->emitting);
nf7_util_signal_recv_unset(this);
nf7util_signal_recv_unset(this);
if (!nf7_util_signal_recvs_insert(&signal->recvs, UINT64_MAX, this)) {
if (!nf7util_signal_recvs_insert(&signal->recvs, UINT64_MAX, this)) {
return false;
}
this->signal = signal;

View File

@ -3,73 +3,73 @@
#include "test/common.h"
static void on_recv_(struct nf7_util_signal_recv* recv) {
static void on_recv_(struct nf7util_signal_recv* recv) {
uint32_t* cnt = recv->data;
++*cnt;
}
NF7_TEST(nf7_util_signal_test_emit) {
NF7TEST(nf7util_signal_test_emit) {
uint32_t cnt = 0;
struct nf7_util_signal signal = {
struct nf7util_signal signal = {
.malloc = test_->malloc,
};
nf7_util_signal_init(&signal);
nf7util_signal_init(&signal);
struct nf7_util_signal_recv recv = {
struct nf7util_signal_recv recv = {
.data = &cnt,
.func = on_recv_,
};
nf7_util_signal_recv_set(&recv, &signal);
nf7util_signal_recv_set(&recv, &signal);
nf7_util_signal_emit(&signal);
if (!nf7_test_expect(1 == cnt)) {
nf7util_signal_emit(&signal);
if (!nf7test_expect(1 == cnt)) {
return false;
}
nf7_util_signal_deinit(&signal);
nf7util_signal_deinit(&signal);
return true;
}
NF7_TEST(nf7_util_signal_test_emit_after_unset) {
NF7TEST(nf7util_signal_test_emit_after_unset) {
uint32_t cnt = 0;
struct nf7_util_signal signal = {
struct nf7util_signal signal = {
.malloc = test_->malloc,
};
nf7_util_signal_init(&signal);
nf7util_signal_init(&signal);
struct nf7_util_signal_recv recv = {
struct nf7util_signal_recv recv = {
.data = &cnt,
.func = on_recv_,
};
nf7_util_signal_recv_set(&recv, &signal);
nf7_util_signal_recv_unset(&recv);
nf7util_signal_recv_set(&recv, &signal);
nf7util_signal_recv_unset(&recv);
nf7_util_signal_emit(&signal);
if (!nf7_test_expect(0 == cnt)) {
nf7util_signal_emit(&signal);
if (!nf7test_expect(0 == cnt)) {
return false;
}
nf7_util_signal_deinit(&signal);
nf7util_signal_deinit(&signal);
return true;
}
NF7_TEST(nf7_util_signal_test_del_after_set) {
NF7TEST(nf7util_signal_test_del_after_set) {
uint32_t cnt = 0;
struct nf7_util_signal signal = {
struct nf7util_signal signal = {
.malloc = test_->malloc,
};
nf7_util_signal_init(&signal);
nf7util_signal_init(&signal);
struct nf7_util_signal_recv recv = {
struct nf7util_signal_recv recv = {
.data = &cnt,
.func = on_recv_,
};
nf7_util_signal_recv_set(&recv, &signal);
nf7_util_signal_deinit(&signal);
nf7util_signal_recv_set(&recv, &signal);
nf7util_signal_deinit(&signal);
return nf7_test_expect(0 == cnt);
return nf7test_expect(0 == cnt);
}