Compare commits
5 Commits
3a2fa32ce1
...
9549a7b61a
| Author | SHA1 | Date | |
|---|---|---|---|
|
9549a7b61a
|
|||
|
51483db283
|
|||
|
3759c0361f
|
|||
|
1ead2f6592
|
|||
|
b6d3387388
|
@@ -36,7 +36,7 @@ public:
|
|||||||
* Call frame.
|
* Call frame.
|
||||||
*/
|
*/
|
||||||
struct frame {
|
struct frame {
|
||||||
mod_h mod; /**< Shared pointer to a module with the bytecode. */
|
mod_h mod; /**< Handle to the frame's module. */
|
||||||
std::size_t position; /**< Cursor to a current instruction in the bytecode. */
|
std::size_t position; /**< Cursor to a current instruction in the bytecode. */
|
||||||
std::size_t stackBase; /**< Snapshot of the stack size before this frame. */
|
std::size_t stackBase; /**< Snapshot of the stack size before this frame. */
|
||||||
|
|
||||||
@@ -83,8 +83,8 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Pushes a new frame.
|
* @brief Pushes a new frame.
|
||||||
*
|
*
|
||||||
* @param mod Module.
|
* @param mod Handle to the frame's module.
|
||||||
* @param function Function handle.
|
* @param function Frame's function.
|
||||||
*/
|
*/
|
||||||
void push_frame(const mod_h& mod, function function);
|
void push_frame(const mod_h& mod, function function);
|
||||||
|
|
||||||
@@ -102,6 +102,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
frame frame() const;
|
frame frame() const;
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Pushes a thing handle onto the stack.
|
||||||
|
*
|
||||||
|
* @param handle Thing handle.
|
||||||
|
*/
|
||||||
template <typename HandleFwd>
|
template <typename HandleFwd>
|
||||||
void push_thing(HandleFwd&& handle) {
|
void push_thing(HandleFwd&& handle) {
|
||||||
m_stack.emplace(std::forward<HandleFwd>(handle));
|
m_stack.emplace(std::forward<HandleFwd>(handle));
|
||||||
@@ -110,45 +115,48 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Pushes a thing onto the stack.
|
* @brief Pushes a thing onto the stack.
|
||||||
*
|
*
|
||||||
* @param thing The thing to push.
|
* Registers a new thing and pushes its handle onto the stack.
|
||||||
|
*
|
||||||
|
* @param thing Thing.
|
||||||
|
* @return The pushed handle.
|
||||||
*/
|
*/
|
||||||
thing_h push_thing(class thing<>&& thing);
|
thing_h push_thing(class thing<>&& thing);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Pops a thing from the stack.
|
* @brief Pops a thing from the stack.
|
||||||
*
|
*
|
||||||
* @return The popped thing.
|
* @return A handle to the popped thing.
|
||||||
*/
|
*/
|
||||||
thing_h pop_thing();
|
thing_h pop_thing();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the top thing on the stack.
|
* @brief Returns the top thing on the stack.
|
||||||
*
|
*
|
||||||
* @return The thing.
|
* @return A handle to the top thing.
|
||||||
*/
|
*/
|
||||||
thing_h thing() const;
|
thing_h thing() const;
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Stores a thing in a variable.
|
* @brief Stores a thing in a frame variable.
|
||||||
*
|
*
|
||||||
* @param variable Variable to store the thing in.
|
* @param variable Id of the variable in which the handle will be put.
|
||||||
* @param thing Thing to store.
|
* @param thing Thing handle.
|
||||||
*/
|
*/
|
||||||
void store_thing(variable_t variable, const thing_h& thing);
|
void store_thing(variable_t variable, const thing_h& thing);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stores a thing in a variable.
|
* @brief Stores a thing in a frame variable.
|
||||||
*
|
*
|
||||||
* @param variable Variable to store the thing in.
|
* @param variable Id of the variable in which the handle will be put.
|
||||||
* @param thing Thing to store.
|
* @param thing Thing handle.
|
||||||
*/
|
*/
|
||||||
void store_thing(variable_t variable, thing_h&& thing);
|
void store_thing(variable_t variable, thing_h&& thing);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a thing stored in a variable.
|
* @brief Returns a thing stored in a variable.
|
||||||
*
|
*
|
||||||
* @param variable Variable where the thing is stored.
|
* @param variable Id of the variable from which the handle will be fetched.
|
||||||
* @return The thing stored in the variable.
|
* @return A handle stored in the variable.
|
||||||
*/
|
*/
|
||||||
thing_h load_thing(variable_t variable) const;
|
thing_h load_thing(variable_t variable) const;
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -16,8 +16,14 @@ enum class function_t : std::uint8_t {
|
|||||||
Import, /**< A function imported from another module. */
|
Import, /**< A function imported from another module. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A native function.
|
||||||
|
*/
|
||||||
using native_function = std::function<void(executor&)>;
|
using native_function = std::function<void(executor&)>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A function import.
|
||||||
|
*/
|
||||||
struct import_function {
|
struct import_function {
|
||||||
mod_id mod;
|
mod_id mod;
|
||||||
function_id function;
|
function_id function;
|
||||||
@@ -25,18 +31,39 @@ struct import_function {
|
|||||||
|
|
||||||
class function {
|
class function {
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructs a normal function.
|
||||||
|
*
|
||||||
|
* @param name Name of the function.
|
||||||
|
* @param position Offset in bytecode of the function.
|
||||||
|
*/
|
||||||
template <typename Name>
|
template <typename Name>
|
||||||
function(Name&& name, bytecode_pos position)
|
function(Name&& name, bytecode_pos position)
|
||||||
: m_name(std::forward<Name>(name)), m_type(function_t::Normal), m_value(position) {}
|
: m_name(std::forward<Name>(name)), m_type(function_t::Normal), m_value(position) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructs a native function.
|
||||||
|
*
|
||||||
|
* @param name Name of the function.
|
||||||
|
* @param native Native function.
|
||||||
|
*/
|
||||||
template <typename Name>
|
template <typename Name>
|
||||||
function(Name&& name, const native_function& native)
|
function(Name&& name, const native_function& native)
|
||||||
: m_name(std::forward<Name>(name)), m_type(function_t::Native), m_value(native) {}
|
: m_name(std::forward<Name>(name)), m_type(function_t::Native), m_value(native) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructs an import function.
|
||||||
|
*
|
||||||
|
* @param name Name of the function.
|
||||||
|
* @param imp Import function.
|
||||||
|
*/
|
||||||
template <typename Name>
|
template <typename Name>
|
||||||
function(Name&& name, const import_function& imp)
|
function(Name&& name, const import_function& imp)
|
||||||
: m_name(std::forward<Name>(name)), m_type(function_t::Import), m_value(imp) {}
|
: m_name(std::forward<Name>(name)), m_type(function_t::Import), m_value(imp) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructs a function.
|
||||||
|
*/
|
||||||
~function();
|
~function();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,7 +101,7 @@ public:
|
|||||||
constexpr function_t type() const { return m_type; }
|
constexpr function_t type() const { return m_type; }
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Returns a value for normal function.
|
* @brief Returns normal function's value.
|
||||||
*
|
*
|
||||||
* @return The value.
|
* @return The value.
|
||||||
*/
|
*/
|
||||||
@@ -84,7 +111,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a value for native function.
|
* @brief Returns native function's value.
|
||||||
*
|
*
|
||||||
* @return The value.
|
* @return The value.
|
||||||
*/
|
*/
|
||||||
@@ -94,7 +121,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a name of the function's module.
|
* @brief Returns import function's value.
|
||||||
*
|
*
|
||||||
* @return The name.
|
* @return The name.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -36,11 +36,22 @@ template <typename Id>
|
|||||||
class generic_header;
|
class generic_header;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Handle.
|
* @brief Generic furvm object handle.
|
||||||
|
*
|
||||||
|
* @tparam Value Type of the handle's value.
|
||||||
|
* @tparam Header Type of the handle's header.
|
||||||
*/
|
*/
|
||||||
template <typename Value, typename Header>
|
template <typename Value, typename Header>
|
||||||
class handle;
|
class handle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Container for the handles.
|
||||||
|
*
|
||||||
|
* @tparam Handle Type of the container's handle.
|
||||||
|
*/
|
||||||
|
template <typename Handle, typename = void>
|
||||||
|
class handle_container;
|
||||||
|
|
||||||
// constant.hpp
|
// constant.hpp
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+180
-25
@@ -14,30 +14,52 @@
|
|||||||
|
|
||||||
namespace furvm {
|
namespace furvm {
|
||||||
|
|
||||||
template <typename Handle, typename = void>
|
|
||||||
class handle_container;
|
|
||||||
|
|
||||||
// TODO: Implement generational indexes
|
// TODO: Implement generational indexes
|
||||||
|
|
||||||
template <typename Id>
|
template <typename Id>
|
||||||
class refcount_header {
|
class refcount_header {
|
||||||
public:
|
public:
|
||||||
using id_type = Id;
|
using id_type = Id; /**< Id type. */
|
||||||
using refcount_type = std::uint32_t;
|
using refcount_type = std::uint32_t; /**< Reference count type. */
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructs a reference counting header.
|
||||||
|
*
|
||||||
|
* @param id Identifier of the handle's value.
|
||||||
|
* @param refCount Handle's reference count.
|
||||||
|
* @param onRelease Callback function.
|
||||||
|
*/
|
||||||
template <typename IdFwd, typename Func>
|
template <typename IdFwd, typename Func>
|
||||||
refcount_header(IdFwd&& id, refcount_type refCount, Func&& onRelease)
|
refcount_header(IdFwd&& id, refcount_type refCount, Func&& onRelease)
|
||||||
: m_id(std::forward<IdFwd>(id)), m_refCount(refCount), m_onRelease(std::forward<Func>(onRelease)) {}
|
: m_id(std::forward<IdFwd>(id)), m_refCount(refCount), m_onRelease(std::forward<Func>(onRelease)) {}
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Returns the header's reference count.
|
||||||
|
*
|
||||||
|
* @return The reference count.
|
||||||
|
*/
|
||||||
refcount_type reference_count() const { return m_refCount; }
|
refcount_type reference_count() const { return m_refCount; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Increments the header's reference count.
|
||||||
|
*/
|
||||||
void acquire() { ++m_refCount; }
|
void acquire() { ++m_refCount; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Decrements the header's reference count.
|
||||||
|
*
|
||||||
|
* If the reference count reaches 0, the onRelease callback passed in the constructor will be called.
|
||||||
|
*/
|
||||||
void release() {
|
void release() {
|
||||||
--m_refCount;
|
--m_refCount;
|
||||||
if (m_refCount == 0) m_onRelease(m_id);
|
if (m_refCount == 0) m_onRelease(m_id);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Returns the header's identifier.
|
||||||
|
*
|
||||||
|
* @return The identifier.
|
||||||
|
*/
|
||||||
id_type id() const { return m_id; }
|
id_type id() const { return m_id; }
|
||||||
private:
|
private:
|
||||||
id_type m_id;
|
id_type m_id;
|
||||||
@@ -48,11 +70,19 @@ private:
|
|||||||
template <typename Id>
|
template <typename Id>
|
||||||
class generic_header {
|
class generic_header {
|
||||||
public:
|
public:
|
||||||
using id_type = Id;
|
using id_type = Id; /**< Id type. */
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructs a generic header.
|
||||||
|
*
|
||||||
|
* @param id Identifier of the handle.
|
||||||
|
*/
|
||||||
generic_header(id_type id)
|
generic_header(id_type id)
|
||||||
: m_id(id) {}
|
: m_id(id) {}
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Returns the header's identifier.
|
||||||
|
*/
|
||||||
id_type id() const { return m_id; }
|
id_type id() const { return m_id; }
|
||||||
private:
|
private:
|
||||||
id_type m_id;
|
id_type m_id;
|
||||||
@@ -61,18 +91,23 @@ private:
|
|||||||
template <typename Value, typename Header = refcount_header<std::uint32_t>>
|
template <typename Value, typename Header = refcount_header<std::uint32_t>>
|
||||||
class handle {
|
class handle {
|
||||||
public:
|
public:
|
||||||
using value_type = Value;
|
using value_type = Value; /** Value type. */
|
||||||
using reference = Value&;
|
using reference = Value&; /** Reference type. */
|
||||||
using const_reference = const Value&;
|
using const_reference = const Value&; /** Constant reference type. */
|
||||||
using pointer = Value*;
|
using pointer = Value*; /** Pointer type. */
|
||||||
using const_pointer = const Value*;
|
using const_pointer = const Value*; /** Constant pointer type. */
|
||||||
public:
|
public:
|
||||||
using id_type = typename Header::id_type;
|
using id_type = typename Header::id_type; /** Id type of the header. */
|
||||||
public:
|
public:
|
||||||
using pair_type = std::pair<Header, Value>;
|
using pair_type = std::pair<Header, Value>; /** Type of a header-value pair. */
|
||||||
public:
|
public:
|
||||||
handle() = default;
|
handle() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructs a handle.
|
||||||
|
*
|
||||||
|
* @param value A pointer to the header-value pair.
|
||||||
|
*/
|
||||||
handle(pair_type* value)
|
handle(pair_type* value)
|
||||||
: m_value(value) {
|
: m_value(value) {
|
||||||
if constexpr (detail::header_has_refcount_v<Header>) {
|
if constexpr (detail::header_has_refcount_v<Header>) {
|
||||||
@@ -80,6 +115,9 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructs a handle.
|
||||||
|
*/
|
||||||
~handle() {
|
~handle() {
|
||||||
if constexpr (detail::header_has_refcount_v<Header>) {
|
if constexpr (detail::header_has_refcount_v<Header>) {
|
||||||
if (m_value != nullptr) m_value->first.release();
|
if (m_value != nullptr) m_value->first.release();
|
||||||
@@ -87,11 +125,17 @@ public:
|
|||||||
m_value = nullptr;
|
m_value = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Move constructor.
|
||||||
|
*/
|
||||||
handle(handle&& other) noexcept
|
handle(handle&& other) noexcept
|
||||||
: m_value(other.m_value) {
|
: m_value(other.m_value) {
|
||||||
other.m_value = nullptr;
|
other.m_value = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Move constructor.
|
||||||
|
*/
|
||||||
handle& operator=(handle&& other) noexcept {
|
handle& operator=(handle&& other) noexcept {
|
||||||
if (this == &other) return *this;
|
if (this == &other) return *this;
|
||||||
m_value = other.m_value;
|
m_value = other.m_value;
|
||||||
@@ -99,11 +143,17 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copy constructor.
|
||||||
|
*/
|
||||||
handle(const handle& other)
|
handle(const handle& other)
|
||||||
: m_value(other.m_value) {
|
: m_value(other.m_value) {
|
||||||
m_value->first.acquire();
|
m_value->first.acquire();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copy constructor.
|
||||||
|
*/
|
||||||
handle& operator=(const handle& other) {
|
handle& operator=(const handle& other) {
|
||||||
if (this == &other) return *this;
|
if (this == &other) return *this;
|
||||||
m_value = other.m_value;
|
m_value = other.m_value;
|
||||||
@@ -111,22 +161,70 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Returns an identifier of the handle's header.
|
||||||
|
*
|
||||||
|
* @return The header's identifier.
|
||||||
|
*/
|
||||||
id_type id() const { return m_value->first.id(); }
|
id_type id() const { return m_value->first.id(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns whether the handle is empty.
|
||||||
|
*
|
||||||
|
* @return true if the handle is empty.
|
||||||
|
*/
|
||||||
bool empty() const { return m_value == nullptr; }
|
bool empty() const { return m_value == nullptr; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the handle's header reference count.
|
||||||
|
*
|
||||||
|
* @return The reference count.
|
||||||
|
*/
|
||||||
template <typename ReferenceCount = typename Header::refcount_type>
|
template <typename ReferenceCount = typename Header::refcount_type>
|
||||||
ReferenceCount reference_count() const {
|
ReferenceCount reference_count() const {
|
||||||
return m_value->first.reference_count();
|
return m_value->first.reference_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer operator->() { return &m_value->second; }
|
/**
|
||||||
|
* @brief Returns a pointer to the handle's value.
|
||||||
|
*
|
||||||
|
* @return The value pointer.
|
||||||
|
*/
|
||||||
|
pointer operator->() { return &m_value->second; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a pointer to the handle's value.
|
||||||
|
*
|
||||||
|
* @return The value pointer.
|
||||||
|
*/
|
||||||
const_pointer operator->() const { return &m_value->second; }
|
const_pointer operator->() const { return &m_value->second; }
|
||||||
|
|
||||||
reference operator*() { return m_value->second; }
|
/**
|
||||||
|
* @brief Returns a reference to the handle's value.
|
||||||
|
*
|
||||||
|
* @return The value reference.
|
||||||
|
*/
|
||||||
|
reference operator*() { return m_value->second; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a reference to the handle's value.
|
||||||
|
*
|
||||||
|
* @return The value reference.
|
||||||
|
*/
|
||||||
const_reference operator*() const { return m_value->second; }
|
const_reference operator*() const { return m_value->second; }
|
||||||
|
|
||||||
reference value() { return m_value->second; }
|
/**
|
||||||
|
* @brief Returns a reference to the handle's value.
|
||||||
|
*
|
||||||
|
* @return The value reference.
|
||||||
|
*/
|
||||||
|
reference value() { return m_value->second; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a reference to the handle's value.
|
||||||
|
*
|
||||||
|
* @return The value reference.
|
||||||
|
*/
|
||||||
const_reference value() const { return m_value->second; }
|
const_reference value() const { return m_value->second; }
|
||||||
private:
|
private:
|
||||||
pair_type* m_value = nullptr;
|
pair_type* m_value = nullptr;
|
||||||
@@ -135,12 +233,12 @@ private:
|
|||||||
template <typename Handle>
|
template <typename Handle>
|
||||||
class handle_container<Handle, std::enable_if_t<!std::is_integral_v<typename Handle::id_type>>> {
|
class handle_container<Handle, std::enable_if_t<!std::is_integral_v<typename Handle::id_type>>> {
|
||||||
private:
|
private:
|
||||||
using pair_type = typename Handle::pair_type;
|
using pair_type = typename Handle::pair_type; /**< Handle's pair type. */
|
||||||
public:
|
public:
|
||||||
using value_type = std::remove_cv_t<std::remove_reference_t<Handle>>;
|
using value_type = std::remove_cv_t<std::remove_reference_t<Handle>>; /**< Handle type. */
|
||||||
using const_value = std::add_const_t<value_type>;
|
using const_value = std::add_const_t<value_type>; /**< Constant handle type. */
|
||||||
|
|
||||||
using id_type = typename Handle::id_type;
|
using id_type = typename Handle::id_type; /**< Handle's header identifier type. */
|
||||||
public:
|
public:
|
||||||
handle_container() = default;
|
handle_container() = default;
|
||||||
~handle_container() = default;
|
~handle_container() = default;
|
||||||
@@ -151,6 +249,13 @@ public:
|
|||||||
handle_container(const handle_container&) = delete;
|
handle_container(const handle_container&) = delete;
|
||||||
handle_container& operator=(const handle_container&) = delete;
|
handle_container& operator=(const handle_container&) = delete;
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Emplaces a new value.
|
||||||
|
*
|
||||||
|
* @param id Identifier of the emplaced value.
|
||||||
|
* @param args Arguments passed to the Handle's value type constructor.
|
||||||
|
* @return A handle to the emplaced value.
|
||||||
|
*/
|
||||||
template <typename IdFwd,
|
template <typename IdFwd,
|
||||||
typename... Args,
|
typename... Args,
|
||||||
typename = std::enable_if_t<std::is_constructible_v<typename pair_type::second_type, Args...>>>
|
typename = std::enable_if_t<std::is_constructible_v<typename pair_type::second_type, Args...>>>
|
||||||
@@ -164,16 +269,33 @@ public:
|
|||||||
return { pair };
|
return { pair };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a handle to the container's value.
|
||||||
|
*
|
||||||
|
* @param id Idenfifier of the value.
|
||||||
|
* @return The value.
|
||||||
|
*/
|
||||||
template <typename IdFwd>
|
template <typename IdFwd>
|
||||||
value_type at(IdFwd&& id) {
|
value_type at(IdFwd&& id) {
|
||||||
return { m_pairs.at(std::forward<IdFwd>(id)) };
|
return { m_pairs.at(std::forward<IdFwd>(id)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a handle to the container's value.
|
||||||
|
*
|
||||||
|
* @param id Idenfifier of the value.
|
||||||
|
* @return The value.
|
||||||
|
*/
|
||||||
template <typename IdFwd>
|
template <typename IdFwd>
|
||||||
const_value at(IdFwd&& id) const {
|
const_value at(IdFwd&& id) const {
|
||||||
return { m_pairs.at(std::forward<IdFwd>(id)) };
|
return { m_pairs.at(std::forward<IdFwd>(id)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Erases a value from the container.
|
||||||
|
*
|
||||||
|
* @param id Identifier of the value.
|
||||||
|
*/
|
||||||
template <typename IdFwd>
|
template <typename IdFwd>
|
||||||
void erase(IdFwd&& id) {
|
void erase(IdFwd&& id) {
|
||||||
auto it = m_pairs.find(std::forward<IdFwd>(id));
|
auto it = m_pairs.find(std::forward<IdFwd>(id));
|
||||||
@@ -188,12 +310,12 @@ private:
|
|||||||
template <typename Handle>
|
template <typename Handle>
|
||||||
class handle_container<Handle, std::enable_if_t<std::is_integral_v<typename Handle::id_type>>> {
|
class handle_container<Handle, std::enable_if_t<std::is_integral_v<typename Handle::id_type>>> {
|
||||||
private:
|
private:
|
||||||
using pair_type = typename Handle::pair_type;
|
using pair_type = typename Handle::pair_type; /**< Handle's pair type. */
|
||||||
public:
|
public:
|
||||||
using value_type = std::remove_cv_t<std::remove_reference_t<Handle>>;
|
using value_type = std::remove_cv_t<std::remove_reference_t<Handle>>; /**< Handle type. */
|
||||||
using const_value = std::add_const_t<value_type>;
|
using const_value = std::add_const_t<value_type>; /**< Constant handle type. */
|
||||||
|
|
||||||
using id_type = typename Handle::id_type;
|
using id_type = typename Handle::id_type; /**< Handle's header identifier type. */
|
||||||
public:
|
public:
|
||||||
handle_container() = default;
|
handle_container() = default;
|
||||||
~handle_container() = default;
|
~handle_container() = default;
|
||||||
@@ -204,6 +326,13 @@ public:
|
|||||||
handle_container(const handle_container&) = delete;
|
handle_container(const handle_container&) = delete;
|
||||||
handle_container& operator=(const handle_container&) = delete;
|
handle_container& operator=(const handle_container&) = delete;
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Emplaces a new value.
|
||||||
|
*
|
||||||
|
* @param id Identifier of the emplaced value.
|
||||||
|
* @param args Arguments passed to the Handle's value type constructor.
|
||||||
|
* @return A handle to the emplaced value.
|
||||||
|
*/
|
||||||
template <typename... Args,
|
template <typename... Args,
|
||||||
typename = std::enable_if_t<std::is_constructible_v<typename pair_type::second_type, Args...>>>
|
typename = std::enable_if_t<std::is_constructible_v<typename pair_type::second_type, Args...>>>
|
||||||
value_type emplace(id_type id, Args&&... args) {
|
value_type emplace(id_type id, Args&&... args) {
|
||||||
@@ -221,15 +350,41 @@ public:
|
|||||||
return { newPair };
|
return { newPair };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Emplaces a new value.
|
||||||
|
*
|
||||||
|
* Emplaces a new value with an automatically-assigned identifier.
|
||||||
|
*
|
||||||
|
* @param args Arguments passed to the Handle's value type constructor.
|
||||||
|
* @return A handle to the emplaced value.
|
||||||
|
*/
|
||||||
template <typename... Args,
|
template <typename... Args,
|
||||||
typename = std::enable_if_t<std::is_constructible_v<typename Handle::pair_type::second_type, Args...>>>
|
typename = std::enable_if_t<std::is_constructible_v<typename Handle::pair_type::second_type, Args...>>>
|
||||||
value_type emplace_back(Args&&... args) {
|
value_type emplace_back(Args&&... args) {
|
||||||
return emplace(static_cast<id_type>(m_pairs.size()), std::forward<Args>(args)...);
|
return emplace(static_cast<id_type>(m_pairs.size()), std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
value_type at(id_type id) { return { m_pairs.at(id) }; }
|
/**
|
||||||
|
* @brief Returns a handle to a value.
|
||||||
|
*
|
||||||
|
* @param id Identifier of the value.
|
||||||
|
* @return The value.
|
||||||
|
*/
|
||||||
|
value_type at(id_type id) { return { m_pairs.at(id) }; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a handle to a value.
|
||||||
|
*
|
||||||
|
* @param id Identifier of the value.
|
||||||
|
* @return The value.
|
||||||
|
*/
|
||||||
const_value at(id_type id) const { return { m_pairs.at(id) }; }
|
const_value at(id_type id) const { return { m_pairs.at(id) }; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Erases a value from the container.
|
||||||
|
*
|
||||||
|
* @param id Identifier of the value.
|
||||||
|
*/
|
||||||
void erase(id_type id) {
|
void erase(id_type id) {
|
||||||
if (id >= m_pairs.size()) return;
|
if (id >= m_pairs.size()) return;
|
||||||
delete m_pairs[id];
|
delete m_pairs[id];
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ public:
|
|||||||
static constexpr char MAGIC[4] = { 'F', 'u', 'r', 'M' }; /** Furvm module file magic. */
|
static constexpr char MAGIC[4] = { 'F', 'u', 'r', 'M' }; /** Furvm module file magic. */
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Construct a new module.
|
* @brief Constructs a module.
|
||||||
*
|
*
|
||||||
* @param name Name of this module.
|
* @param name Name of the module.
|
||||||
* @param args Arguments to forward to bytecode's constructor.
|
* @param args Arguments forwarded to bytecode's constructor.
|
||||||
*/
|
*/
|
||||||
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<bytecode_t, Args...>>>
|
template <typename... Args, typename = std::enable_if_t<std::is_constructible_v<bytecode_t, Args...>>>
|
||||||
mod(Args&&... args)
|
mod(Args&&... args)
|
||||||
@@ -55,19 +55,25 @@ public:
|
|||||||
constexpr byte byte(std::size_t offset) const { return m_bytecode.at(offset); }
|
constexpr byte byte(std::size_t offset) const { return m_bytecode.at(offset); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a reference to the module's bytecode.
|
* @brief Returns the module's bytecode.
|
||||||
*
|
*
|
||||||
* @return The reference to bytecode.
|
* @return A reference to the bytecode.
|
||||||
*/
|
*/
|
||||||
constexpr bytecode_t& bytecode() { return m_bytecode; }
|
constexpr bytecode_t& bytecode() { return m_bytecode; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a const reference to the module's bytecode.
|
* @brief Returns the module's bytecode.
|
||||||
*
|
*
|
||||||
* @return The reference to bytecode.
|
* @return A constant reference to the bytecode.
|
||||||
*/
|
*/
|
||||||
constexpr const bytecode_t& bytecode() const { return m_bytecode; }
|
constexpr const bytecode_t& bytecode() const { return m_bytecode; }
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Emplaces a function in the module's function container.
|
||||||
|
*
|
||||||
|
* @param args Arguments forwarded into the container's emplace_back function.
|
||||||
|
* @return A handle to the emplaced function.
|
||||||
|
*/
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
function_h emplace_function(Args&&... args) {
|
function_h emplace_function(Args&&... args) {
|
||||||
function_h function = m_functions.emplace_back(std::forward<Args>(args)...);
|
function_h function = m_functions.emplace_back(std::forward<Args>(args)...);
|
||||||
@@ -75,26 +81,67 @@ public:
|
|||||||
return std::move(function);
|
return std::move(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename FunctionHandle>
|
/**
|
||||||
void push_back(FunctionHandle&& handle) {
|
* @brief Inserts a function in the module's function container.
|
||||||
m_functions.emplace_back(std::forward<FunctionHandle>(handle));
|
*
|
||||||
|
* @param function Function to insert.
|
||||||
|
*/
|
||||||
|
template <typename Function>
|
||||||
|
void push_back(Function&& function) {
|
||||||
|
m_functions.emplace_back(std::forward<Function>(function));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a function from the module.
|
||||||
|
*
|
||||||
|
* @param id Identifier of the function.
|
||||||
|
* @return A handle to the function.
|
||||||
|
*/
|
||||||
auto function_at(function_id id) { return m_functions.at(id); }
|
auto function_at(function_id id) { return m_functions.at(id); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a function from the module.
|
||||||
|
*
|
||||||
|
* @param id Identifier of the function.
|
||||||
|
* @return A handle to the function.
|
||||||
|
*/
|
||||||
auto function_at(function_id id) const { return m_functions.at(id); }
|
auto function_at(function_id id) const { return m_functions.at(id); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a function from the module.
|
||||||
|
*
|
||||||
|
* @param name Name of the function.
|
||||||
|
* @return A handle to the function.
|
||||||
|
*/
|
||||||
template <typename NameFwd>
|
template <typename NameFwd>
|
||||||
auto function_at(NameFwd&& name) {
|
auto function_at(NameFwd&& name) {
|
||||||
return function_at(m_functionMap.at(std::forward<NameFwd>(name)));
|
return function_at(m_functionMap.at(std::forward<NameFwd>(name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a function from the module.
|
||||||
|
*
|
||||||
|
* @param name Name of the function.
|
||||||
|
* @return A handle to the function.
|
||||||
|
*/
|
||||||
template <typename NameFwd>
|
template <typename NameFwd>
|
||||||
auto function_at(NameFwd&& name) const {
|
auto function_at(NameFwd&& name) const {
|
||||||
return function_at(m_functionMap.at(std::forward<NameFwd>(name)));
|
return function_at(m_functionMap.at(std::forward<NameFwd>(name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Erases a function from the module's function container.
|
||||||
|
*
|
||||||
|
* @param id Identifier of the function.
|
||||||
|
*/
|
||||||
void erase_function(function_id id) { m_functions.erase(id); }
|
void erase_function(function_id id) { m_functions.erase(id); }
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Prints the module in a bytecode form to an output stream.
|
||||||
|
*
|
||||||
|
* @param os Output stream.
|
||||||
|
* @return The output stream.
|
||||||
|
*/
|
||||||
std::ostream& serialize(std::ostream& os) const;
|
std::ostream& serialize(std::ostream& os) const;
|
||||||
private:
|
private:
|
||||||
bytecode_t m_bytecode;
|
bytecode_t m_bytecode;
|
||||||
|
|||||||
+130
-20
@@ -19,10 +19,10 @@ enum class thing_t : std::uint8_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns data size of a thing.
|
* @brief Returns how many bytes a thing would take up.
|
||||||
*
|
*
|
||||||
* @param type Type of the thing.
|
* @param type Type of the thing.
|
||||||
* @return The data size of the thing.
|
* @return The byte count.
|
||||||
*/
|
*/
|
||||||
static inline std::size_t thing_type_size(thing_t type) {
|
static inline std::size_t thing_type_size(thing_t type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -35,13 +35,22 @@ template <template <typename> typename Allocator>
|
|||||||
class thing final {
|
class thing final {
|
||||||
friend class executor;
|
friend class executor;
|
||||||
public:
|
public:
|
||||||
using allocator_type = Allocator<std::byte>;
|
using allocator_type = Allocator<std::byte>; /**< Allocator type. */
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructs a thing.
|
||||||
|
*
|
||||||
|
* @param type Type of the thing.
|
||||||
|
* @param allocator Allocator for the thing's data.
|
||||||
|
*/
|
||||||
thing(thing_t type, const allocator_type& allocator = {})
|
thing(thing_t type, const allocator_type& allocator = {})
|
||||||
: m_type(type), m_allocator(allocator) {
|
: m_type(type), m_allocator(allocator) {
|
||||||
m_data = m_allocator.allocate(thing_type_size(type));
|
m_data = m_allocator.allocate(thing_type_size(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructs a thing.
|
||||||
|
*/
|
||||||
~thing() {
|
~thing() {
|
||||||
if (m_data != nullptr) m_allocator.deallocate(m_data, thing_type_size(thing_t::Int32));
|
if (m_data != nullptr) m_allocator.deallocate(m_data, thing_type_size(thing_t::Int32));
|
||||||
}
|
}
|
||||||
@@ -74,8 +83,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Returns a clone of the thing.
|
* @brief Returns a clone of the thing.
|
||||||
*
|
*
|
||||||
* @param thing Thing to clone.
|
* @return A clone of this thing.
|
||||||
* @return Shared pointer to a clone of the thing.
|
|
||||||
*/
|
*/
|
||||||
thing clone() const {
|
thing clone() const {
|
||||||
class thing res(m_type, m_allocator);
|
class thing res(m_type, m_allocator);
|
||||||
@@ -88,7 +96,7 @@ public:
|
|||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Returns an int32 value from this thing.
|
* @brief Returns the thing's int32 value.
|
||||||
*
|
*
|
||||||
* @return The value.
|
* @return The value.
|
||||||
*/
|
*/
|
||||||
@@ -98,7 +106,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns an int32 value from this thing.
|
* @brief Returns the thing's int32 value.
|
||||||
*
|
*
|
||||||
* @return The value.
|
* @return The value.
|
||||||
*/
|
*/
|
||||||
@@ -107,66 +115,132 @@ public:
|
|||||||
return *reinterpret_cast<std::int32_t*>(m_data);
|
return *reinterpret_cast<std::int32_t*>(m_data);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Returns a sum of two things.
|
||||||
|
*
|
||||||
|
* @param rhs Thing to sum with this thing (right-hand-side).
|
||||||
|
* @return The sum.
|
||||||
|
*/
|
||||||
thing add(const thing& rhs) const {
|
thing add(const thing& rhs) const {
|
||||||
thing res(m_type, m_allocator);
|
thing res(m_type, m_allocator);
|
||||||
res.int32() = int32() + rhs.int32();
|
res.int32() = int32() + rhs.int32();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a difference of two things.
|
||||||
|
*
|
||||||
|
* @param rhs Thing to subtract from this thing (right-hand-side).
|
||||||
|
* @return The sum.
|
||||||
|
*/
|
||||||
thing sub(const thing& rhs) const {
|
thing sub(const thing& rhs) const {
|
||||||
thing res(m_type, m_allocator);
|
thing res(m_type, m_allocator);
|
||||||
res.int32() = int32() - rhs.int32();
|
res.int32() = int32() - rhs.int32();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a product of two things.
|
||||||
|
*
|
||||||
|
* @param rhs Thing to multiply with this thing (right-hand-side).
|
||||||
|
* @return The product.
|
||||||
|
*/
|
||||||
thing mul(const thing& rhs) const {
|
thing mul(const thing& rhs) const {
|
||||||
thing res(m_type, m_allocator);
|
thing res(m_type, m_allocator);
|
||||||
res.int32() = int32() * rhs.int32();
|
res.int32() = int32() * rhs.int32();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a quotient of two things.
|
||||||
|
*
|
||||||
|
* @param rhs Thing to divide this thing by (right-hand-side).
|
||||||
|
* @return The quotient.
|
||||||
|
*/
|
||||||
thing div(const thing& rhs) const {
|
thing div(const thing& rhs) const {
|
||||||
thing res(m_type, m_allocator);
|
thing res(m_type, m_allocator);
|
||||||
res.int32() = int32() / rhs.int32();
|
res.int32() = int32() / rhs.int32();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a remainder of two things.
|
||||||
|
*
|
||||||
|
* @param rhs Thing to divide this thing by (right-hand-side).
|
||||||
|
* @return The remainder.
|
||||||
|
*/
|
||||||
thing mod(const thing& rhs) const {
|
thing mod(const thing& rhs) const {
|
||||||
thing res(m_type, m_allocator);
|
thing res(m_type, m_allocator);
|
||||||
res.int32() = int32() % rhs.int32();
|
res.int32() = int32() % rhs.int32();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares two things for equality.
|
||||||
|
*
|
||||||
|
* @param rhs Thing to compare this thing with (right-hand-side).
|
||||||
|
* @return A boolean result of the comparison in a thing form.
|
||||||
|
*/
|
||||||
thing equals(const thing& rhs) const {
|
thing equals(const thing& rhs) const {
|
||||||
thing res(m_type, m_allocator);
|
thing res(m_type, m_allocator);
|
||||||
res.int32() = int32() == rhs.int32();
|
res.int32() = int32() == rhs.int32();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares two things for inequality.
|
||||||
|
*
|
||||||
|
* @param rhs Thing to compare this thing with (right-hand-side).
|
||||||
|
* @return A boolean result of the comparison in a thing form.
|
||||||
|
*/
|
||||||
thing not_equals(const thing& rhs) const {
|
thing not_equals(const thing& rhs) const {
|
||||||
thing res(m_type, m_allocator);
|
thing res(m_type, m_allocator);
|
||||||
res.int32() = int32() != rhs.int32();
|
res.int32() = int32() != rhs.int32();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares if this thing is less than an another thing.
|
||||||
|
*
|
||||||
|
* @param rhs The another thing.
|
||||||
|
* @return A boolean result of the comparison in a thing form.
|
||||||
|
*/
|
||||||
thing less_than(const thing& rhs) const {
|
thing less_than(const thing& rhs) const {
|
||||||
thing res(m_type, m_allocator);
|
thing res(m_type, m_allocator);
|
||||||
res.int32() = int32() < rhs.int32();
|
res.int32() = int32() < rhs.int32();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares if this thing is greater than an another thing.
|
||||||
|
*
|
||||||
|
* @param rhs The another thing.
|
||||||
|
* @return A boolean result of the comparison in a thing form.
|
||||||
|
*/
|
||||||
thing greater_than(const thing& rhs) const {
|
thing greater_than(const thing& rhs) const {
|
||||||
thing res(m_type, m_allocator);
|
thing res(m_type, m_allocator);
|
||||||
res.int32() = int32() > rhs.int32();
|
res.int32() = int32() > rhs.int32();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares if this thing is less than or equal to an another thing.
|
||||||
|
*
|
||||||
|
* @param rhs The another thing.
|
||||||
|
* @return A boolean result of the comparison in a thing form.
|
||||||
|
*/
|
||||||
thing less_equals(const thing& rhs) const {
|
thing less_equals(const thing& rhs) const {
|
||||||
thing res(m_type, m_allocator);
|
thing res(m_type, m_allocator);
|
||||||
res.int32() = int32() <= rhs.int32();
|
res.int32() = int32() <= rhs.int32();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares if this thing is greater than or equal to an another thing.
|
||||||
|
*
|
||||||
|
* @param rhs The another thing.
|
||||||
|
* @return A boolean result of the comparison in a thing form.
|
||||||
|
*/
|
||||||
thing greater_equals(const thing& rhs) const {
|
thing greater_equals(const thing& rhs) const {
|
||||||
thing res(m_type, m_allocator);
|
thing res(m_type, m_allocator);
|
||||||
res.int32() = int32() >= rhs.int32();
|
res.int32() = int32() >= rhs.int32();
|
||||||
@@ -186,27 +260,26 @@ class thing_allocator {
|
|||||||
|
|
||||||
using dead_things = std::vector<std::pair<T*, std::size_t>>;
|
using dead_things = std::vector<std::pair<T*, std::size_t>>;
|
||||||
public:
|
public:
|
||||||
using value_type = T;
|
using value_type = T; /**< Value type. */
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructs a thing allocator.
|
||||||
|
*
|
||||||
|
* @param arena Base arena allocator.
|
||||||
|
*/
|
||||||
explicit thing_allocator(furlang::arena& arena) noexcept
|
explicit thing_allocator(furlang::arena& arena) noexcept
|
||||||
: m_arena(&arena), m_deadThings(std::make_shared<dead_things>()) {}
|
: m_arena(&arena), m_deadThings(std::make_shared<dead_things>()) {}
|
||||||
|
|
||||||
template <typename U>
|
/**
|
||||||
thing_allocator(const thing_allocator<U>& other) noexcept
|
* @brief Move constructor.
|
||||||
: m_arena(other.m_arena), m_deadThings(other.m_deadThings) {}
|
*/
|
||||||
|
|
||||||
template <typename U>
|
|
||||||
thing_allocator& operator=(const thing_allocator<U>& other) noexcept {
|
|
||||||
if (this == &other) return *this;
|
|
||||||
m_arena = other.m_arena;
|
|
||||||
m_deadThings = other.m_deadThings;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
thing_allocator(thing_allocator<U>&& other) noexcept
|
thing_allocator(thing_allocator<U>&& other) noexcept
|
||||||
: m_arena(std::move(other.m_arena)), m_deadThings(std::move(other.m_deadThings)) {}
|
: m_arena(std::move(other.m_arena)), m_deadThings(std::move(other.m_deadThings)) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Move constructor.
|
||||||
|
*/
|
||||||
template <typename U>
|
template <typename U>
|
||||||
thing_allocator& operator=(thing_allocator<U>&& other) noexcept {
|
thing_allocator& operator=(thing_allocator<U>&& other) noexcept {
|
||||||
if (this == &other) return *this;
|
if (this == &other) return *this;
|
||||||
@@ -214,7 +287,31 @@ public:
|
|||||||
m_deadThings = std::move(other.m_deadThings);
|
m_deadThings = std::move(other.m_deadThings);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copy constructor.
|
||||||
|
*/
|
||||||
|
template <typename U>
|
||||||
|
thing_allocator(const thing_allocator<U>& other) noexcept
|
||||||
|
: m_arena(other.m_arena), m_deadThings(other.m_deadThings) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copy constructor.
|
||||||
|
*/
|
||||||
|
template <typename U>
|
||||||
|
thing_allocator& operator=(const thing_allocator<U>& other) noexcept {
|
||||||
|
if (this == &other) return *this;
|
||||||
|
m_arena = other.m_arena;
|
||||||
|
m_deadThings = other.m_deadThings;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Returns a free chunk of memory.
|
||||||
|
*
|
||||||
|
* @param count Count of the things that must fit inside the chunk.
|
||||||
|
* @return The chunk.
|
||||||
|
*/
|
||||||
[[nodiscard]] T* allocate(std::size_t count = 1) {
|
[[nodiscard]] T* allocate(std::size_t count = 1) {
|
||||||
for (auto it = m_deadThings->begin(); it != m_deadThings->end(); ++it) {
|
for (auto it = m_deadThings->begin(); it != m_deadThings->end(); ++it) {
|
||||||
if (it->second != count) continue;
|
if (it->second != count) continue;
|
||||||
@@ -224,13 +321,26 @@ public:
|
|||||||
return m_arena->allocate<T>(count);
|
return m_arena->allocate<T>(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Recycles the pointer.
|
||||||
|
*/
|
||||||
void deallocate(T* ptr, std::size_t count) noexcept { m_deadThings->emplace_back(ptr, count); }
|
void deallocate(T* ptr, std::size_t count) noexcept { m_deadThings->emplace_back(ptr, count); }
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Compares two thing allocators for equality.
|
||||||
|
*
|
||||||
|
* @return true if the two things are equal.
|
||||||
|
*/
|
||||||
template <typename U>
|
template <typename U>
|
||||||
bool operator==(const thing_allocator<U>& other) const noexcept {
|
bool operator==(const thing_allocator<U>& other) const noexcept {
|
||||||
return m_arena == other.m_arena && m_deadThings == other.m_deadThings;
|
return m_arena == other.m_arena && m_deadThings == other.m_deadThings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compares two thing allocators for inequality.
|
||||||
|
*
|
||||||
|
* @return true if the two things are not equal.
|
||||||
|
*/
|
||||||
template <typename U>
|
template <typename U>
|
||||||
bool operator!=(const thing_allocator<U>& other) const noexcept {
|
bool operator!=(const thing_allocator<U>& other) const noexcept {
|
||||||
return m_arena != other.m_arena || m_deadThings != other.m_deadThings;
|
return m_arena != other.m_arena || m_deadThings != other.m_deadThings;
|
||||||
|
|||||||
Reference in New Issue
Block a user