Skip to content

Commit

Permalink
Merge pull request #74 from iboB/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
iboB authored Apr 4, 2023
2 parents e40e55e + f35903f commit 0136b71
Show file tree
Hide file tree
Showing 28 changed files with 486 additions and 27 deletions.
4 changes: 3 additions & 1 deletion code/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,10 @@ target_sources(dynamix PRIVATE
dynamix/exception.hpp
dynamix/exception.cpp

dnmx/type_class.h
dynamix/type_class.hpp
dynamix/type_class.cpp
dynamix/declare_type_class.hpp
dynamix/define_type_class.hpp

dynamix/type_mutation.hpp
dynamix/type_mutation.cpp
Expand Down
3 changes: 2 additions & 1 deletion code/dnmx/basic_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#pragma once
#include "object_mixin_data.h"
#include "mixin_index.h"
#include "type_handle.h"

#include <splat/inline.h>

Expand All @@ -17,7 +18,7 @@ struct dnmx_basic_object {
// object data visible to C so that queries can be inlined there too

// type. never null
const struct dnmx_basic_type* m_type;
dnmx_type_handle m_type;

// multi-purpose pointer
// first, it points to the unified buffer for this object
Expand Down
5 changes: 5 additions & 0 deletions code/dnmx/domain.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ extern "C" {
typedef struct dnmx_feature_info dnmx_feature_info;
typedef struct dnmx_mixin_info dnmx_mixin_info;
typedef struct dnmx_mutation_rule_info dnmx_mutation_rule_info;
typedef struct dnmx_type_class dnmx_type_class;

DYNAMIX_API dnmx_domain_handle dnmx_create_domain(dnmx_sv name, dnmx_domain_settings settings, uintptr_t user_data, void* context);
DYNAMIX_API void dnmx_destroy_domain(dnmx_domain_handle hd);
Expand Down Expand Up @@ -52,6 +53,10 @@ DYNAMIX_API const dnmx_feature_info* dnmx_get_feature_info_by_name(dnmx_domain_h
DYNAMIX_API const dnmx_mixin_info* dnmx_get_mixin_info_by_id(dnmx_domain_handle hd, dnmx_mixin_id id);
DYNAMIX_API const dnmx_mixin_info* dnmx_get_mixin_info_by_name(dnmx_domain_handle hd, dnmx_sv name);

DYNAMIX_API dnmx_error_return_t dnmx_register_type_class(dnmx_domain_handle hd, const dnmx_type_class* tc);
DYNAMIX_API void dnmx_unregister_type_class(dnmx_domain_handle hd, const dnmx_type_class* tc);
DYNAMIX_API const dnmx_type_class* dnmx_get_type_class_by_name(dnmx_domain_handle hd, dnmx_sv name);

DYNAMIX_API dnmx_error_return_t dnmx_add_mutation_rule(dnmx_domain_handle hd, const dnmx_mutation_rule_info* info);
DYNAMIX_API void dnmx_remove_mutation_rule(dnmx_domain_handle hd, const dnmx_mutation_rule_info* info);

Expand Down
1 change: 0 additions & 1 deletion code/dnmx/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

#include "error_return.h"
#include "domain_handle.h"
#include "type_handle.h"

#if defined(__cplusplus)
extern "C" {
Expand Down
4 changes: 3 additions & 1 deletion code/dnmx/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ extern "C" {

typedef struct dnmx_feature_info dnmx_feature_info;
typedef struct dnmx_mixin_info dnmx_mixin_info;
typedef struct dnmx_type_class dnmx_type_class;

DYNAMIX_API size_t dnmx_type_num_objects(dnmx_type_handle ht);
DYNAMIX_API dnmx_mixin_index_t dnmx_type_num_mixins(dnmx_type_handle ht);
Expand All @@ -31,7 +32,8 @@ DYNAMIX_API bool dnmx_type_implements_strong_by_name(dnmx_type_handle ht, dnmx_s

DYNAMIX_API bool dnmx_type_implements(dnmx_type_handle ht, const dnmx_feature_info* info);

//DYNAMIX_API dnmx_mixin_index_t dnmx_type_is_of();
DYNAMIX_API bool dnmx_type_is_of(dnmx_type_handle ht, const dnmx_type_class* tc);
DYNAMIX_API bool dnmx_type_is_of_name(dnmx_type_handle ht, dnmx_sv name);

DYNAMIX_API bool dnmx_type_is_default_constructible(dnmx_type_handle ht);
DYNAMIX_API bool dnmx_type_is_copy_constructible(dnmx_type_handle ht);
Expand Down
17 changes: 17 additions & 0 deletions code/dnmx/type_class.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) Borislav Stanimirov
// SPDX-License-Identifier: MIT
//
#pragma once
#include "bits/sv.h"
#include "bits/noexcept.h"
#include "type_handle.h"

typedef bool (*dnmx_type_class_match_func)(dnmx_type_handle) DNMX_NOEXCEPT;

typedef struct dnmx_type_class {
// may be left empty, but in such a case the type class cannot be registered in a domain
dnmx_sv name;

// this must not be left null: it's always assumed to not be null
dnmx_type_class_match_func matches;
} dnmx_type_class;
9 changes: 9 additions & 0 deletions code/dynamix/declare_type_class.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) Borislav Stanimirov
// SPDX-License-Identifier: MIT
//
#pragma once
#include "../dnmx/bits/pp.h"
#include "type_class.hpp"

#define DYNAMIX_DECLARE_EXPORTED_TYPE_CLASS(export, tc) struct export tc { static const dynamix::type_class m_dynamix_type_class; }
#define DYNAMIX_DECLARE_TYPE_CLASS(tc) DYNAMIX_DECLARE_EXPORTED_TYPE_CLASS(I_DNMX_PP_EMPTY(), tc)
26 changes: 26 additions & 0 deletions code/dynamix/define_type_class.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) Borislav Stanimirov
// SPDX-License-Identifier: MIT
//
#pragma once
#include "declare_type_class.hpp"
#include "globals.hpp"
#include "domain.hpp"
#include "type.hpp"

namespace dynamix::impl {
struct registered_type_class_instance {
domain& dom;
const type_class& tc;
registered_type_class_instance(domain& dom, const type_class& tc) : dom(dom), tc(tc) {
dom.register_type_class(tc);
}
~registered_type_class_instance() {
dom.unregister_type_class(tc);
}
};
}

// define a type class with bool(const type&);
#define DYNAMIX_DEFINE_TYPE_CLASS_WITH(domain_tag, tc, func) \
const dynamix::type_class tc::m_dynamix_type_class = {dnmx_make_sv_lit(#tc), func}; \
static ::dynamix::impl::registered_type_class_instance I_DNMX_PP_CAT(_dynamix_type_class_, tc)(::dynamix::g::get_domain<domain_tag>(), tc::m_dynamix_type_class)
18 changes: 18 additions & 0 deletions code/dynamix/domain-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,24 @@ const dnmx_mixin_info* dnmx_get_mixin_info_by_name(dnmx_domain_handle hd, dnmx_s
return self->get_mixin_info(name.to_std());
}

dnmx_error_return_t dnmx_register_type_class(dnmx_domain_handle hd, const dnmx_type_class* tc) {
try {
self->register_type_class(*tc);
return dnmx_result_success;
}
catch (std::exception&) {
return -1;
}
}

void dnmx_unregister_type_class(dnmx_domain_handle hd, const dnmx_type_class* tc) {
self->unregister_type_class(*tc);
}

const dnmx_type_class* dnmx_get_type_class_by_name(dnmx_domain_handle hd, dnmx_sv name) {
return self->get_type_class(name.to_std());
}

dnmx_error_return_t dnmx_add_mutation_rule(dnmx_domain_handle hd, const dnmx_mutation_rule_info* info) {
try {
self->add_mutation_rule(*info);
Expand Down
54 changes: 54 additions & 0 deletions code/dynamix/domain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class domain::impl {
// null elements have been unregistered and are free slots for future registers
compat::pmr::vector<const feature_info*> sparse_features;
compat::pmr::vector<const mixin_info*> sparse_mixins;
compat::pmr::vector<const type_class*> sparse_type_classes;

// sorted rules with their refcounts
mutation_rule_map mutation_rules;
Expand Down Expand Up @@ -265,6 +266,41 @@ class domain::impl {
info.dom = nullptr;
}

void register_type_class(const type_class& new_tc) {
if (new_tc.name.empty()) throw domain_error("empty type_class name");
if (!new_tc.matches) throw domain_error("type_class missing matches func");

auto reg = m_registry.unique_lock();

// search in reverse order while also checking for name clashes
const type_class** free_slot = nullptr;
for (auto i = reg->sparse_type_classes.rbegin(); i != reg->sparse_type_classes.rend(); ++i) {
auto tc = *i;
if (tc) {
if (tc->name == new_tc.name) throw domain_error("duplicate type_class name");
}
else {
free_slot = &tc;
}
}

if (!free_slot) {
free_slot = &reg->sparse_type_classes.emplace_back();
}

*free_slot = &new_tc;
}

void unregister_type_class(const type_class& tc) {
auto reg = m_registry.unique_lock();

for (auto& rtc : reg->sparse_type_classes) {
if (rtc == &tc) {
rtc = nullptr;
return;
}
}
}

template <typename Id, typename T>
static const T* basic_get_by_id_l(Id id, const compat::pmr::vector<const T*>& sparse) noexcept {
Expand Down Expand Up @@ -294,6 +330,10 @@ class domain::impl {
return basic_get_by_name_l(name, m_registry.shared_lock()->sparse_features);
}

const type_class* get_type_class(std::string_view name) noexcept {
return basic_get_by_name_l(name, m_registry.shared_lock()->sparse_type_classes);
}

void add_mutation_rule(const mutation_rule_info& info) {
if (!info.apply) throw domain_error("bad mutation rule");

Expand Down Expand Up @@ -629,6 +669,8 @@ class domain::impl {
}();
const byte_size_t sparse_mixin_indices_buf_size = num_sparse * sizeof(mixin_index_t);

//const byte_size_t type_classes_buf_size = byte_size_t(m_domain.m_type_classes.size() * sizeof(bool));

// alloc and fill buf
const byte_size_t total_obj_type_buf_size =
type_size
Expand Down Expand Up @@ -789,6 +831,18 @@ const feature_info* domain::get_feature_info(std::string_view name) noexcept {
return m_impl->get_feature_info(name);
}

void domain::register_type_class(const type_class& tc) {
m_impl->register_type_class(tc);
}

void domain::unregister_type_class(const type_class& tc) {
m_impl->unregister_type_class(tc);
}

const type_class* domain::get_type_class(std::string_view name) noexcept {
return m_impl->get_type_class(name);
}

void domain::add_mutation_rule(const mutation_rule_info& info) {
m_impl->add_mutation_rule(info);
}
Expand Down
6 changes: 6 additions & 0 deletions code/dynamix/domain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "mixin_id.hpp"
#include "mixin_info_fwd.hpp"
#include "mutation_rule_info_fwd.hpp"
#include "type_class.hpp"

#include "allocator.hpp"

Expand Down Expand Up @@ -58,6 +59,10 @@ class DYNAMIX_API domain : private dnmx_basic_domain {
void unregister_mixin(mixin_info& info);
void unregister_feature(feature_info& info);

// type classes don't have to be registered, but if they are, they can be queried by name
void register_type_class(const type_class& tc);
void unregister_type_class(const type_class& tc);

// get registered infos
// return nullptr if nothing matches the arg
// these functions are not const, as they are not safe to use where a const domain
Expand All @@ -66,6 +71,7 @@ class DYNAMIX_API domain : private dnmx_basic_domain {
const mixin_info* get_mixin_info(std::string_view name) noexcept;
const feature_info* get_feature_info(feature_id id) noexcept;
const feature_info* get_feature_info(std::string_view name) noexcept;
const type_class* get_type_class(std::string_view name) noexcept;

// mutation rules
// adding and removing the same mutation rule is safe (it is managed by an internal ref count)
Expand Down
4 changes: 4 additions & 0 deletions code/dynamix/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ const type& object::get_type() const noexcept {
return *type::from_c_handle(m_type);
}

bool object::is_of(std::string_view name) const {
return get_type().is_of(name);
}

object object::copy(const allocator& alloc) const {
object ret(nullptr, alloc);

Expand Down
11 changes: 9 additions & 2 deletions code/dynamix/object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "allocator.hpp"
#include "object_mixin_data.hpp"
#include "mixin_info_fwd.hpp"
#include "type_class.hpp"
#include "globals.hpp"

#include <splat/inline.h>
Expand All @@ -22,7 +23,6 @@ namespace dynamix {

class domain;
class type;
class type_class;
class object_mutation;
class mutation;

Expand Down Expand Up @@ -113,7 +113,14 @@ class DYNAMIX_API object : private dnmx_basic_object {

const type& get_type() const noexcept;

bool is_of(const type_class& tc) const noexcept;
bool is_of(const type_class& tc) const noexcept {
return tc.matches(m_type);
}
bool is_of(std::string_view name) const; // will throw if type class is not registered
template <typename TypeClass>
bool is_of() const noexcept {
return TypeClass::m_dynamix_type_class.matches(m_type);
}

//////////////////////////
// mixin queries
Expand Down
15 changes: 14 additions & 1 deletion code/dynamix/type-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "type.hpp"
#include "mixin_info.hpp"

#include <exception>

using namespace dynamix;

extern "C" {
Expand Down Expand Up @@ -45,7 +47,18 @@ bool dnmx_type_implements(dnmx_type_handle ht, const dnmx_feature_info* info) {
return self->implements(*info);
}

//dnmx_mixin_index_t dnmx_type_is_of() {}
bool dnmx_type_is_of(dnmx_type_handle ht, const dnmx_type_class* tc) {
return self->is_of(*tc);
}

bool dnmx_type_is_of_name(dnmx_type_handle ht, dnmx_sv name) {
try {
return self->is_of(name.to_std());
}
catch (std::exception&) {
return false;
}
}

bool dnmx_type_is_default_constructible(dnmx_type_handle ht) {
return self->default_constructible();
Expand Down
9 changes: 9 additions & 0 deletions code/dynamix/type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#include "mixin_info.hpp"
#include "feature_info.hpp"
#include "feature_for_mixin.hpp"
#include "domain.hpp"
#include "type_class.hpp"
#include "exception.hpp"

#include <itlib/qalgorithm.hpp>

Expand Down Expand Up @@ -77,6 +80,12 @@ itlib::span<const type::ftable_payload> type::find_next_bidder_set(const feature
return {begin, end};
}

bool type::is_of(std::string_view name) const {
auto tc = dom.get_type_class(name);
if (!tc) throw domain_error("unknown type class");
return is_of(*tc);
}

int type::compare(const type& other) const noexcept {
if (this == &other) return 0;
if (&dom != &other.dom) return &dom < &other.dom ? -1 : 1;
Expand Down
10 changes: 9 additions & 1 deletion code/dynamix/type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: MIT
//
#pragma once
#include "../dnmx/api.h"
#include "../dnmx/basic_type.h"
#include "../dnmx/type_handle.h"

Expand Down Expand Up @@ -115,7 +116,14 @@ class DYNAMIX_API type : public dnmx_basic_type {

// type class
[[nodiscard]] bool is_of(const type_class& tc) const noexcept {
return tc.matches(*this);
return tc.matches(this);
}
// check by registered type class from domain
// will throw domain_error if no such type class is registered
[[nodiscard]] bool is_of(std::string_view name) const;
template <typename TypeClass>
[[nodiscard]] bool is_of() const noexcept {
return is_of(TypeClass::m_dynamix_type_class);
}

// compare types
Expand Down
9 changes: 0 additions & 9 deletions code/dynamix/type_class.cpp

This file was deleted.

Loading

0 comments on commit 0136b71

Please sign in to comment.