mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-07-10 23:09:18 +00:00
Update kernel
This commit is contained in:
65
include_std/algorithm
Normal file
65
include_std/algorithm
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename InputIt, typename OutputIt>
|
||||
OutputIt copy(InputIt first, InputIt last, OutputIt result)
|
||||
{
|
||||
while (first != last)
|
||||
{
|
||||
*result = *first;
|
||||
++result;
|
||||
++first;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void swap(T &a, T &b)
|
||||
{
|
||||
T temp = move(a);
|
||||
a = move(b);
|
||||
b = move(temp);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr const T &min(const T &a, const T &b)
|
||||
{
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr const T &max(const T &a, const T &b)
|
||||
{
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
template <class InputIt, class T>
|
||||
InputIt find(InputIt first, InputIt last, const T &value)
|
||||
{
|
||||
while (first != last)
|
||||
{
|
||||
if (*first == value)
|
||||
return first;
|
||||
++first;
|
||||
}
|
||||
return last;
|
||||
}
|
||||
}
|
@ -20,31 +20,31 @@
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#define assert(x) \
|
||||
do \
|
||||
{ \
|
||||
if (!(x)) \
|
||||
{ \
|
||||
void *CallerAddress = __builtin_extract_return_addr(__builtin_return_address(0)); \
|
||||
error("Assertion failed! [%s] [%#lx => %s:%s:%d]", #x, CallerAddress, __FILE__, __FUNCTION__, __LINE__); \
|
||||
while (1) \
|
||||
; \
|
||||
} \
|
||||
} while (0)
|
||||
#define assert(x) \
|
||||
do \
|
||||
{ \
|
||||
if (!(x)) \
|
||||
{ \
|
||||
error("Assertion failed! [%s] [%s:%s:%d]", \
|
||||
#x, __FILE__, __FUNCTION__, __LINE__); \
|
||||
int3; \
|
||||
while (true) \
|
||||
; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define assert_allow_continue(x) \
|
||||
do \
|
||||
{ \
|
||||
if (!(x)) \
|
||||
{ \
|
||||
void *CallerAddress = __builtin_extract_return_addr(__builtin_return_address(0)); \
|
||||
error("Assertion failed! [%s] [%#lx => %s:%s:%d]", #x, CallerAddress, __FILE__, __FUNCTION__, __LINE__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define assert_allow_continue(x) \
|
||||
do \
|
||||
{ \
|
||||
if (!(x)) \
|
||||
{ \
|
||||
error("Assertion failed! [%s] [%s:%s:%d]", \
|
||||
#x, __FILE__, __FUNCTION__, __LINE__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define static_assert(x) \
|
||||
switch (x) \
|
||||
case 0: \
|
||||
case (x):
|
||||
#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
|
||||
#define static_assert _Static_assert
|
||||
#endif
|
||||
|
||||
#endif // !__FENNIX_KERNEL_ASSERT_H__
|
||||
|
@ -16,4 +16,651 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <std/atomic.hpp>
|
||||
|
||||
#include <types.h>
|
||||
#include <cstddef>
|
||||
#include <debug.h>
|
||||
|
||||
namespace std
|
||||
{
|
||||
#define _atomic(T) T
|
||||
#define builtin_atomic_n(name) __atomic_##name##_n
|
||||
#define builtin_atomic(name) __atomic_##name
|
||||
|
||||
/**
|
||||
* Specifies the memory ordering constraints for atomic operations.
|
||||
*
|
||||
* This enum specifies the possible values for the memory order
|
||||
* parameter of atomic operations.
|
||||
*
|
||||
* Possible values are:
|
||||
*
|
||||
* - memory_order_relaxed: There are no synchronization
|
||||
* or ordering constraints imposed on other reads or writes,
|
||||
* only this operation's atomicity is guaranteed.
|
||||
*
|
||||
* - memory_order_consume: A load operation with this
|
||||
* memory order performs a consume operation on the
|
||||
* affected memory location: no reads or writes in the
|
||||
* current thread dependent on the value currently loaded
|
||||
* can be reordered before this load.
|
||||
*
|
||||
* - memory_order_acquire: A load operation with this
|
||||
* memory order performs the acquire operation on the
|
||||
* affected memory location: no reads or writes in the
|
||||
* current thread can be reordered before this load.
|
||||
*
|
||||
* - memory_order_release: A store operation with this
|
||||
* memory order performs the release operation: no reads
|
||||
* or writes in the current thread can be reordered after
|
||||
* this store.
|
||||
*
|
||||
* - memory_order_acq_rel: A read-modify-write operation
|
||||
* with this memory order is both an acquire operation
|
||||
* and a release operation.
|
||||
*
|
||||
* - memory_order_seq_cst: A load operation with this
|
||||
* memory order performs an acquire operation, a store
|
||||
* performs a release operation, and read-modify-write
|
||||
* performs both an acquire operation and a release
|
||||
* operation, plus a single total order exists in which
|
||||
* all threads observe all modifications in the same order.
|
||||
*/
|
||||
enum class memory_order : int
|
||||
{
|
||||
relaxed,
|
||||
consume,
|
||||
acquire,
|
||||
release,
|
||||
acq_rel,
|
||||
seq_cst
|
||||
};
|
||||
|
||||
/**
|
||||
* Relaxed memory order
|
||||
*
|
||||
* No synchronization or ordering constraints
|
||||
* imposed on other reads or writes.
|
||||
* Only atomicity is guaranteed. */
|
||||
inline constexpr memory_order memory_order_relaxed =
|
||||
memory_order::relaxed;
|
||||
|
||||
/**
|
||||
* Consume memory order
|
||||
*
|
||||
* A load operation with this memory order
|
||||
* performs a consume operation on the affected
|
||||
* memory location. No reads or writes in the
|
||||
* current thread dependent on the value
|
||||
* currently loaded can be reordered before this
|
||||
* load. Writes to data-dependent variables in
|
||||
* other threads that release the same atomic
|
||||
* variable are visible in the current thread.
|
||||
*/
|
||||
inline constexpr memory_order memory_order_consume =
|
||||
memory_order::consume;
|
||||
|
||||
/** Acquire memory order
|
||||
*
|
||||
* A load operation with this memory order
|
||||
* performs the acquire operation on the affected
|
||||
* memory location. No reads or writes in the
|
||||
* current thread can be reordered before this
|
||||
* load. All writes in other threads that release
|
||||
* the same atomic variable are visible in the
|
||||
* current thread. */
|
||||
inline constexpr memory_order memory_order_acquire =
|
||||
memory_order::acquire;
|
||||
|
||||
/** Release memory order
|
||||
*
|
||||
* A store operation with this memory order
|
||||
* performs the release operation. No reads or
|
||||
* writes in the current thread can be reordered
|
||||
* after this store. All writes in the current
|
||||
* thread are visible in other threads that acquire
|
||||
* the same atomic variable, and writes that carry
|
||||
* a dependency into the atomic variable become
|
||||
* visible in other threads that consume the same
|
||||
* atomic. */
|
||||
inline constexpr memory_order memory_order_release =
|
||||
memory_order::release;
|
||||
|
||||
/** Acquire-release memory order
|
||||
*
|
||||
* A read-modify-write operation with this memory
|
||||
* order is both an acquire operation and a release
|
||||
* operation. No memory reads or writes in the
|
||||
* current thread can be reordered before the load,
|
||||
* nor after the store. All writes in other threads
|
||||
* that release the same atomic variable are visible
|
||||
* before the modification, and the modification is
|
||||
* visible in other threads that acquire the same
|
||||
* atomic variable. */
|
||||
inline constexpr memory_order memory_order_acq_rel =
|
||||
memory_order::acq_rel;
|
||||
|
||||
/** Sequentially-consistent memory order
|
||||
*
|
||||
* A load operation with this memory order performs
|
||||
* an acquire operation, a store performs a release
|
||||
* operation, and read-modify-write performs both an
|
||||
* acquire operation and a release operation.
|
||||
* Additionally, a single total order exists in which
|
||||
* all threads observe all modifications in the same
|
||||
* order. */
|
||||
inline constexpr memory_order memory_order_seq_cst =
|
||||
memory_order::seq_cst;
|
||||
|
||||
template <typename T>
|
||||
class atomic
|
||||
{
|
||||
_atomic(T) value;
|
||||
|
||||
public:
|
||||
atomic() : value(0) {}
|
||||
atomic(T desired) : value(desired) {}
|
||||
// atomic(const atomic &) = delete;
|
||||
|
||||
/**
|
||||
* Load the value of the atomic variable
|
||||
*
|
||||
* @note Order must be one of memory_order::relaxed,
|
||||
* memory_order::consume, memory_order::acquire or
|
||||
* memory_order::seq_cst
|
||||
*
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable
|
||||
*/
|
||||
T load(memory_order order = memory_order::seq_cst) const
|
||||
{
|
||||
return builtin_atomic_n(load)(&this->value,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc load()
|
||||
*/
|
||||
T load(memory_order order = memory_order::seq_cst) const volatile
|
||||
{
|
||||
return builtin_atomic_n(load)(&this->value,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the value of the atomic variable
|
||||
*
|
||||
* @note Order must be one of memory_order::relaxed,
|
||||
* memory_order::release or memory_order::seq_cst
|
||||
*
|
||||
* @param desired The value to store
|
||||
* @param order Memory order constraint to use
|
||||
*/
|
||||
void store(T desired, memory_order order = memory_order::seq_cst)
|
||||
{
|
||||
builtin_atomic_n(store)(&this->value, desired,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc store()
|
||||
*/
|
||||
void store(T desired,
|
||||
memory_order order = memory_order::seq_cst) volatile
|
||||
{
|
||||
builtin_atomic_n(store)(&this->value, desired,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exchange the value of the atomic variable
|
||||
*
|
||||
* @param desired The value to exchange
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable before the exchange
|
||||
*/
|
||||
T exchange(T desired, memory_order order = memory_order::seq_cst)
|
||||
{
|
||||
return builtin_atomic_n(exchange)(&this->value, desired,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc exchange()
|
||||
*/
|
||||
T exchange(T desired,
|
||||
memory_order order = memory_order::seq_cst) volatile
|
||||
{
|
||||
return builtin_atomic_n(exchange)(&this->value, desired,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare and exchange the value of the atomic variable
|
||||
*
|
||||
* @param expected The expected value
|
||||
* @param desired The desired value
|
||||
* @param success Memory order constraint to use if the exchange succeeds
|
||||
* @param failure Memory order constraint to use if the exchange fails
|
||||
* @return True if the exchange succeeded, false otherwise
|
||||
*/
|
||||
bool compare_exchange_weak(T &expected, T desired,
|
||||
memory_order success,
|
||||
memory_order failure)
|
||||
{
|
||||
return builtin_atomic(compare_exchange_weak)(&this->value, &expected,
|
||||
desired, false, success,
|
||||
failure);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc compare_exchange_weak()
|
||||
*/
|
||||
bool compare_exchange_weak(T &expected, T desired,
|
||||
memory_order success,
|
||||
memory_order failure) volatile
|
||||
{
|
||||
return builtin_atomic(compare_exchange_weak)(&this->value, &expected,
|
||||
desired, false, success,
|
||||
failure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare and exchange the value of the atomic variable
|
||||
*
|
||||
* @param expected The expected value
|
||||
* @param desired The desired value
|
||||
* @param order Memory order constraint to use
|
||||
* @return True if the exchange succeeded, false otherwise
|
||||
*/
|
||||
bool compare_exchange_weak(T &expected, T desired,
|
||||
memory_order order =
|
||||
memory_order_seq_cst)
|
||||
{
|
||||
return builtin_atomic(compare_exchange_weak)(&this->value, &expected,
|
||||
desired, false, order,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc compare_exchange_weak()
|
||||
*/
|
||||
bool compare_exchange_weak(T &expected, T desired,
|
||||
memory_order order =
|
||||
memory_order_seq_cst) volatile
|
||||
{
|
||||
return builtin_atomic(compare_exchange_weak)(&this->value, &expected,
|
||||
desired, false, order,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare and exchange the value of the atomic variable
|
||||
*
|
||||
* @param expected The expected value
|
||||
* @param desired The desired value
|
||||
* @param success Memory order constraint to use if the exchange succeeds
|
||||
* @param failure Memory order constraint to use if the exchange fails
|
||||
* @return True if the exchange succeeded, false otherwise
|
||||
*/
|
||||
bool compare_exchange_strong(T &expected, T desired,
|
||||
memory_order success,
|
||||
memory_order failure)
|
||||
{
|
||||
return builtin_atomic(compare_exchange_strong)(&this->value, &expected,
|
||||
desired, true, success,
|
||||
failure);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc compare_exchange_strong()
|
||||
*/
|
||||
bool compare_exchange_strong(T &expected, T desired,
|
||||
memory_order success,
|
||||
memory_order failure) volatile
|
||||
{
|
||||
return builtin_atomic(compare_exchange_strong)(&this->value, &expected,
|
||||
desired, true, success,
|
||||
failure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare and exchange the value of the atomic variable
|
||||
*
|
||||
* @param expected The expected value
|
||||
* @param desired The desired value
|
||||
* @param order Memory order constraint to use
|
||||
* @return True if the exchange succeeded, false otherwise
|
||||
*/
|
||||
bool compare_exchange_strong(T &expected, T desired,
|
||||
memory_order order =
|
||||
memory_order_seq_cst)
|
||||
{
|
||||
return builtin_atomic(compare_exchange_strong)(&this->value, &expected,
|
||||
desired, true, order,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc compare_exchange_strong()
|
||||
*/
|
||||
bool compare_exchange_strong(T &expected, T desired,
|
||||
memory_order order =
|
||||
memory_order_seq_cst) volatile
|
||||
{
|
||||
return builtin_atomic(compare_exchange_strong)(&this->value, &expected,
|
||||
desired, true, order,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch and add the value of the atomic variable
|
||||
*
|
||||
* @param arg The value to add
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable before the addition
|
||||
*/
|
||||
T fetch_add(T arg, memory_order order =
|
||||
memory_order_seq_cst)
|
||||
{
|
||||
return builtin_atomic(fetch_add)(&this->value, arg,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc fetch_add()
|
||||
*/
|
||||
T fetch_add(T arg, memory_order order =
|
||||
memory_order_seq_cst) volatile
|
||||
{
|
||||
return builtin_atomic(fetch_add)(&this->value, arg,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch and subtract the value of the atomic variable
|
||||
*
|
||||
* @param arg The value to subtract
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable before the subtraction
|
||||
*/
|
||||
T fetch_sub(T arg, memory_order order =
|
||||
memory_order_seq_cst)
|
||||
{
|
||||
return builtin_atomic(fetch_sub)(&this->value, arg,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc fetch_sub()
|
||||
*/
|
||||
T fetch_sub(T arg, memory_order order =
|
||||
memory_order_seq_cst) volatile
|
||||
{
|
||||
return builtin_atomic(fetch_sub)(&this->value, arg,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch and bitwise AND the value of the atomic variable
|
||||
*
|
||||
* @param arg The value to AND
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable before the AND
|
||||
*/
|
||||
T fetch_and(T arg, memory_order order =
|
||||
memory_order_seq_cst)
|
||||
{
|
||||
return builtin_atomic(fetch_and)(&this->value, arg,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc fetch_and()
|
||||
*/
|
||||
T fetch_and(T arg, memory_order order =
|
||||
memory_order_seq_cst) volatile
|
||||
{
|
||||
return builtin_atomic(fetch_and)(&this->value, arg,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch and bitwise OR the value of the atomic variable
|
||||
*
|
||||
* @param arg The value to OR
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable before the OR
|
||||
*/
|
||||
T fetch_or(T arg, memory_order order =
|
||||
memory_order_seq_cst)
|
||||
{
|
||||
return builtin_atomic(fetch_or)(&this->value, arg,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc fetch_or()
|
||||
*/
|
||||
T fetch_or(T arg, memory_order order =
|
||||
memory_order_seq_cst) volatile
|
||||
{
|
||||
return builtin_atomic(fetch_or)(&this->value, arg,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch and bitwise XOR the value of the atomic variable
|
||||
*
|
||||
* @param arg The value to XOR
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable before the XOR
|
||||
*/
|
||||
T fetch_xor(T arg, memory_order order =
|
||||
memory_order_seq_cst)
|
||||
{
|
||||
return builtin_atomic(fetch_xor)(&this->value, arg,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc fetch_xor()
|
||||
*/
|
||||
T fetch_xor(T arg, memory_order order =
|
||||
memory_order_seq_cst) volatile
|
||||
{
|
||||
return builtin_atomic(fetch_xor)(&this->value, arg,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch and bitwise NAND the value of the atomic variable
|
||||
*
|
||||
* @param arg The value to NAND
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable before the NAND
|
||||
*/
|
||||
T fetch_nand(T arg, memory_order order =
|
||||
memory_order_seq_cst)
|
||||
{
|
||||
return builtin_atomic(fetch_nand)(&this->value, arg,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc fetch_nand()
|
||||
*/
|
||||
T fetch_nand(T arg, memory_order order =
|
||||
memory_order_seq_cst) volatile
|
||||
{
|
||||
return builtin_atomic(fetch_nand)(&this->value, arg,
|
||||
static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all threads waiting on this atomic variable
|
||||
*/
|
||||
void notify_all() { stub; }
|
||||
|
||||
/**
|
||||
* @copydoc notify_all()
|
||||
*/
|
||||
void notify_all() volatile { stub; }
|
||||
|
||||
/**
|
||||
* Notify one thread waiting on this atomic variable
|
||||
*/
|
||||
void notify_one() { stub; }
|
||||
|
||||
/**
|
||||
* @copydoc notify_one()
|
||||
*/
|
||||
void notify_one() volatile { stub; }
|
||||
|
||||
/**
|
||||
* Wait for the atomic variable to change
|
||||
*
|
||||
* @param old The value to wait for
|
||||
* @param order Memory order constraint to use
|
||||
*/
|
||||
void wait(T old, memory_order order =
|
||||
memory_order::seq_cst) const
|
||||
{
|
||||
while (this->load(order) == old)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this atomic type is lock-free
|
||||
* @return True if this atomic type is lock-free
|
||||
*/
|
||||
bool is_lock_free() const
|
||||
{
|
||||
stub;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc is_lock_free()
|
||||
*/
|
||||
bool is_lock_free() const volatile
|
||||
{
|
||||
stub;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equals true if this atomic type is always lock-free
|
||||
*/
|
||||
static constexpr bool is_always_lock_free = true;
|
||||
|
||||
/************************************************/
|
||||
T operator++() { return this->fetch_add(1) + 1; }
|
||||
// T operator++() volatile { return this->fetch_add(1) + 1; }
|
||||
|
||||
T operator++(int) { return this->fetch_add(1); }
|
||||
// T operator++(int) volatile { return this->fetch_add(1); }
|
||||
/************************************************/
|
||||
T operator--() { return this->fetch_sub(1) - 1; }
|
||||
// T operator--() volatile { return this->fetch_sub(1) - 1; }
|
||||
|
||||
T operator--(int) { return this->fetch_sub(1); }
|
||||
// T operator--(int) volatile { return this->fetch_sub(1); }
|
||||
/************************************************/
|
||||
T operator+=(T arg) { return this->fetch_add(arg) + arg; }
|
||||
// T operator+=(T arg) volatile { return this->fetch_add(arg) + arg; }
|
||||
|
||||
// T operator+=(ptrdiff_t arg) { return this->fetch_add(arg) + arg; }
|
||||
// T operator+=(ptrdiff_t arg) volatile { return this->fetch_add(arg) + arg; }
|
||||
/************************************************/
|
||||
T operator-=(T arg) { return this->fetch_sub(arg) - arg; }
|
||||
// T operator-=(T arg) volatile { return this->fetch_sub(arg) - arg; }
|
||||
|
||||
// T operator-=(ptrdiff_t arg) { return this->fetch_sub(arg) - arg; }
|
||||
// T operator-=(ptrdiff_t arg) volatile { return this->fetch_sub(arg) - arg; }
|
||||
/************************************************/
|
||||
T operator&=(T arg) { return this->fetch_and(arg) & arg; }
|
||||
// T operator&=(T arg) volatile { return this->fetch_and(arg) & arg; }
|
||||
|
||||
T operator|=(T arg) { return this->fetch_or(arg) | arg; }
|
||||
// T operator|=(T arg) volatile { return this->fetch_or(arg) | arg; }
|
||||
|
||||
T operator^=(T arg) { return this->fetch_xor(arg) ^ arg; }
|
||||
// T operator^=(T arg) volatile { return this->fetch_xor(arg) ^ arg; }
|
||||
/************************************************/
|
||||
T operator=(T desired)
|
||||
{
|
||||
this->store(desired);
|
||||
return desired;
|
||||
}
|
||||
// T operator=(T desired) volatile
|
||||
// {
|
||||
// this->store(desired);
|
||||
// return desired;
|
||||
// }
|
||||
|
||||
atomic &operator=(const atomic &other) = delete;
|
||||
atomic &operator=(const atomic &other) volatile = delete;
|
||||
/************************************************/
|
||||
|
||||
/* non standard functions */
|
||||
|
||||
T operator->() { return this->load(); }
|
||||
T operator~() { return this->fetch_nand(-1); }
|
||||
|
||||
operator bool() { return this->load() != 0; }
|
||||
operator T() const { return this->load(); }
|
||||
|
||||
bool operator==(const atomic &other) const { return this->load() == other.load(); }
|
||||
bool operator==(T other) const { return this->load() == other; }
|
||||
};
|
||||
|
||||
typedef atomic<bool> atomic_bool;
|
||||
typedef atomic<char> atomic_char;
|
||||
typedef atomic<signed char> atomic_schar;
|
||||
typedef atomic<unsigned char> atomic_uchar;
|
||||
typedef atomic<short> atomic_short;
|
||||
typedef atomic<unsigned short> atomic_ushort;
|
||||
typedef atomic<int> atomic_int;
|
||||
typedef atomic<unsigned int> atomic_uint;
|
||||
typedef atomic<long> atomic_long;
|
||||
typedef atomic<unsigned long> atomic_ulong;
|
||||
typedef atomic<long long> atomic_llong;
|
||||
typedef atomic<unsigned long long> atomic_ullong;
|
||||
typedef atomic<char16_t> atomic_char16_t;
|
||||
typedef atomic<char32_t> atomic_char32_t;
|
||||
typedef atomic<wchar_t> atomic_wchar_t;
|
||||
typedef atomic<int8_t> atomic_int8_t;
|
||||
typedef atomic<uint8_t> atomic_uint8_t;
|
||||
typedef atomic<int16_t> atomic_int16_t;
|
||||
typedef atomic<uint16_t> atomic_uint16_t;
|
||||
typedef atomic<int32_t> atomic_int32_t;
|
||||
typedef atomic<uint32_t> atomic_uint32_t;
|
||||
typedef atomic<int64_t> atomic_int64_t;
|
||||
typedef atomic<uint64_t> atomic_uint64_t;
|
||||
typedef atomic<int_least8_t> atomic_int_least8_t;
|
||||
typedef atomic<uint_least8_t> atomic_uint_least8_t;
|
||||
typedef atomic<int_least16_t> atomic_int_least16_t;
|
||||
typedef atomic<uint_least16_t> atomic_uint_least16_t;
|
||||
typedef atomic<int_least32_t> atomic_int_least32_t;
|
||||
typedef atomic<uint_least32_t> atomic_uint_least32_t;
|
||||
typedef atomic<int_least64_t> atomic_int_least64_t;
|
||||
typedef atomic<uint_least64_t> atomic_uint_least64_t;
|
||||
typedef atomic<int_fast8_t> atomic_int_fast8_t;
|
||||
typedef atomic<uint_fast8_t> atomic_uint_fast8_t;
|
||||
typedef atomic<int_fast16_t> atomic_int_fast16_t;
|
||||
typedef atomic<uint_fast16_t> atomic_uint_fast16_t;
|
||||
typedef atomic<int_fast32_t> atomic_int_fast32_t;
|
||||
typedef atomic<uint_fast32_t> atomic_uint_fast32_t;
|
||||
typedef atomic<int_fast64_t> atomic_int_fast64_t;
|
||||
typedef atomic<uint_fast64_t> atomic_uint_fast64_t;
|
||||
typedef atomic<intptr_t> atomic_intptr_t;
|
||||
typedef atomic<uintptr_t> atomic_uintptr_t;
|
||||
typedef atomic<size_t> atomic_size_t;
|
||||
typedef atomic<ptrdiff_t> atomic_ptrdiff_t;
|
||||
typedef atomic<intmax_t> atomic_intmax_t;
|
||||
typedef atomic<uintmax_t> atomic_uintmax_t;
|
||||
}
|
||||
|
||||
#undef builtin_atomic_n
|
||||
#undef builtin_atomic
|
||||
|
@ -19,6 +19,6 @@
|
||||
|
||||
namespace std
|
||||
{
|
||||
typedef unsigned long size_t;
|
||||
typedef long ptrdiff_t;
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||
}
|
||||
|
@ -18,135 +18,392 @@
|
||||
#ifndef _ERRNO_H
|
||||
#define _ERRNO_H
|
||||
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* I/O error */
|
||||
#define ENXIO 6 /* No such device or address */
|
||||
#define E2BIG 7 /* Argument list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file number */
|
||||
#define ECHILD 10 /* No child processes */
|
||||
#define EAGAIN 11 /* Try again */
|
||||
#define ENOMEM 12 /* Out of memory */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#define EBUSY 16 /* Device or resource busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Cross-device link */
|
||||
#define ENODEV 19 /* No such device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* File table overflow */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Not a typewriter */
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read-only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
#define EDOM 33 /* Math argument out of domain of func */
|
||||
#define ERANGE 34 /* Math result not representable */
|
||||
#define EDEADLK 35 /* Resource deadlock would occur */
|
||||
#define ENAMETOOLONG 36 /* File name too long */
|
||||
#define ENOLCK 37 /* No record locks available */
|
||||
#define ENOSYS 38 /* Function not implemented */
|
||||
#define ENOTEMPTY 39 /* Directory not empty */
|
||||
#define ELOOP 40 /* Too many symbolic links encountered */
|
||||
#define ENOMSG 42 /* No message of desired type */
|
||||
#define EIDRM 43 /* Identifier removed */
|
||||
#define ECHRNG 44 /* Channel number out of range */
|
||||
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
||||
#define EL3HLT 46 /* Level 3 halted */
|
||||
#define EL3RST 47 /* Level 3 reset */
|
||||
#define ELNRNG 48 /* Link number out of range */
|
||||
#define EUNATCH 49 /* Protocol driver not attached */
|
||||
#define ENOCSI 50 /* No CSI structure available */
|
||||
#define EL2HLT 51 /* Level 2 halted */
|
||||
#define EBADE 52 /* Invalid exchange */
|
||||
#define EBADR 53 /* Invalid request descriptor */
|
||||
#define EXFULL 54 /* Exchange full */
|
||||
#define ENOANO 55 /* No anode */
|
||||
#define EBADRQC 56 /* Invalid request code */
|
||||
#define EBADSLT 57 /* Invalid slot */
|
||||
#define EBFONT 59 /* Bad font file format */
|
||||
#define ENOSTR 60 /* Device not a stream */
|
||||
#define ENODATA 61 /* No data available */
|
||||
#define ETIME 62 /* Timer expired */
|
||||
#define ENOSR 63 /* Out of streams resources */
|
||||
#define ENONET 64 /* Machine is not on the network */
|
||||
#define ENOPKG 65 /* Package not installed */
|
||||
#define EREMOTE 66 /* Object is remote */
|
||||
#define ENOLINK 67 /* Link has been severed */
|
||||
#define EADV 68 /* Advertise error */
|
||||
#define ESRMNT 69 /* Srmount error */
|
||||
#define ECOMM 70 /* Communication error on send */
|
||||
#define EPROTO 71 /* Protocol error */
|
||||
#define EMULTIHOP 72 /* Multihop attempted */
|
||||
#define EDOTDOT 73 /* RFS specific error */
|
||||
#define EBADMSG 74 /* Not a data message */
|
||||
#define EOVERFLOW 75 /* Value too large for defined data type */
|
||||
#define ENOTUNIQ 76 /* Name not unique on network */
|
||||
#define EBADFD 77 /* File descriptor in bad state */
|
||||
#define EREMCHG 78 /* Remote address changed */
|
||||
#define ELIBACC 79 /* Can not access a needed shared library */
|
||||
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
||||
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
||||
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
||||
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
||||
#define EILSEQ 84 /* Illegal byte sequence */
|
||||
#define ERESTART 85 /* Interrupted system call should be restarted */
|
||||
#define ESTRPIPE 86 /* Streams pipe error */
|
||||
#define EUSERS 87 /* Too many users */
|
||||
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
||||
#define EDESTADDRREQ 89 /* Destination address required */
|
||||
#define EMSGSIZE 90 /* Message too long */
|
||||
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
||||
#define ENOPROTOOPT 92 /* Protocol not available */
|
||||
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
||||
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||
#define EADDRINUSE 98 /* Address already in use */
|
||||
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
||||
#define ENETDOWN 100 /* Network is down */
|
||||
#define ENETUNREACH 101 /* Network is unreachable */
|
||||
#define ENETRESET 102 /* Network dropped connection because of reset */
|
||||
#define ECONNABORTED 103 /* Software caused connection abort */
|
||||
#define ECONNRESET 104 /* Connection reset by peer */
|
||||
#define ENOBUFS 105 /* No buffer space available */
|
||||
#define EISCONN 106 /* Transport endpoint is already connected */
|
||||
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
||||
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
||||
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
||||
#define ETIMEDOUT 110 /* Connection timed out */
|
||||
#define ECONNREFUSED 111 /* Connection refused */
|
||||
#define EHOSTDOWN 112 /* Host is down */
|
||||
#define EHOSTUNREACH 113 /* No route to host */
|
||||
#define EALREADY 114 /* Operation already in progress */
|
||||
#define EINPROGRESS 115 /* Operation now in progress */
|
||||
#define ESTALE 116 /* Stale NFS file handle */
|
||||
#define EUCLEAN 117 /* Structure needs cleaning */
|
||||
#define ENOTNAM 118 /* Not a XENIX named type file */
|
||||
#define ENAVAIL 119 /* No XENIX semaphores available */
|
||||
#define EISNAM 120 /* Is a named type file */
|
||||
#define EREMOTEIO 121 /* Remote I/O error */
|
||||
#define EDQUOT 122 /* Quota exceeded */
|
||||
#define ENOMEDIUM 123 /* No medium found */
|
||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||
#define ECANCELED 125 /* Operation Canceled */
|
||||
#define ENOKEY 126 /* Required key not available */
|
||||
#define EKEYEXPIRED 127 /* Key has expired */
|
||||
#define EKEYREVOKED 128 /* Key has been revoked */
|
||||
#define EKEYREJECTED 129 /* Key was rejected by service */
|
||||
#define EOWNERDEAD 130 /* Owner died */
|
||||
#define ENOTRECOVERABLE 131 /* State not recoverable */
|
||||
/** @brief Operation not permitted */
|
||||
#define EPERM 1
|
||||
|
||||
/** @brief No such file or directory */
|
||||
#define ENOENT 2
|
||||
|
||||
/** @brief No such process */
|
||||
#define ESRCH 3
|
||||
|
||||
/** @brief Interrupted system call */
|
||||
#define EINTR 4
|
||||
|
||||
/** @brief I/O error */
|
||||
#define EIO 5
|
||||
|
||||
/** @brief No such device or address */
|
||||
#define ENXIO 6
|
||||
|
||||
/** @brief Argument list too long */
|
||||
#define E2BIG 7
|
||||
|
||||
/** @brief Exec format error */
|
||||
#define ENOEXEC 8
|
||||
|
||||
/** @brief Bad file number */
|
||||
#define EBADF 9
|
||||
|
||||
/** @brief No child processes */
|
||||
#define ECHILD 10
|
||||
|
||||
/** @brief Try again */
|
||||
#define EAGAIN 11
|
||||
|
||||
/** @brief Out of memory */
|
||||
#define ENOMEM 12
|
||||
|
||||
/** @brief Permission denied */
|
||||
#define EACCES 13
|
||||
|
||||
/** @brief Bad address */
|
||||
#define EFAULT 14
|
||||
|
||||
/** @brief Block device required */
|
||||
#define ENOTBLK 15
|
||||
|
||||
/** @brief Device or resource busy */
|
||||
#define EBUSY 16
|
||||
|
||||
/** @brief File exists */
|
||||
#define EEXIST 17
|
||||
|
||||
/** @brief Cross-device link */
|
||||
#define EXDEV 18
|
||||
|
||||
/** @brief No such device */
|
||||
#define ENODEV 19
|
||||
|
||||
/** @brief Not a directory */
|
||||
#define ENOTDIR 20
|
||||
|
||||
/** @brief Is a directory */
|
||||
#define EISDIR 21
|
||||
|
||||
/** @brief Invalid argument */
|
||||
#define EINVAL 22
|
||||
|
||||
/** @brief File table overflow */
|
||||
#define ENFILE 23
|
||||
|
||||
/** @brief Too many open files */
|
||||
#define EMFILE 24
|
||||
|
||||
/** @brief Not a typewriter */
|
||||
#define ENOTTY 25
|
||||
|
||||
/** @brief Text file busy */
|
||||
#define ETXTBSY 26
|
||||
|
||||
/** @brief File too large */
|
||||
#define EFBIG 27
|
||||
|
||||
/** @brief No space left on device */
|
||||
#define ENOSPC 28
|
||||
|
||||
/** @brief Illegal seek */
|
||||
#define ESPIPE 29
|
||||
|
||||
/** @brief Read-only file system */
|
||||
#define EROFS 30
|
||||
|
||||
/** @brief Too many links */
|
||||
#define EMLINK 31
|
||||
|
||||
/** @brief Broken pipe */
|
||||
#define EPIPE 32
|
||||
|
||||
/** @brief Math argument out of domain of func */
|
||||
#define EDOM 33
|
||||
|
||||
/** @brief Math result not representable */
|
||||
#define ERANGE 34
|
||||
|
||||
/** @brief Resource deadlock would occur */
|
||||
#define EDEADLK 35
|
||||
|
||||
/** @brief File name too long */
|
||||
#define ENAMETOOLONG 36
|
||||
|
||||
/** @brief No record locks available */
|
||||
#define ENOLCK 37
|
||||
|
||||
/** @brief Function not implemented */
|
||||
#define ENOSYS 38
|
||||
|
||||
/** @brief Directory not empty */
|
||||
#define ENOTEMPTY 39
|
||||
|
||||
/** @brief Too many symbolic links encountered */
|
||||
#define ELOOP 40
|
||||
|
||||
/** @brief No message of desired type */
|
||||
#define ENOMSG 42
|
||||
|
||||
/** @brief Identifier removed */
|
||||
#define EIDRM 43
|
||||
|
||||
/** @brief Channel number out of range */
|
||||
#define ECHRNG 44
|
||||
|
||||
/** @brief Level 2 not synchronized */
|
||||
#define EL2NSYNC 45
|
||||
|
||||
/** @brief Level 3 halted */
|
||||
#define EL3HLT 46
|
||||
|
||||
/** @brief Level 3 reset */
|
||||
#define EL3RST 47
|
||||
|
||||
/** @brief Link number out of range */
|
||||
#define ELNRNG 48
|
||||
|
||||
/** @brief Protocol driver not attached */
|
||||
#define EUNATCH 49
|
||||
|
||||
/** @brief No CSI structure available */
|
||||
#define ENOCSI 50
|
||||
|
||||
/** @brief Level 2 halted */
|
||||
#define EL2HLT 51
|
||||
|
||||
/** @brief Invalid exchange */
|
||||
#define EBADE 52
|
||||
|
||||
/** @brief Invalid request descriptor */
|
||||
#define EBADR 53
|
||||
|
||||
/** @brief Exchange full */
|
||||
#define EXFULL 54
|
||||
|
||||
/** @brief No anode */
|
||||
#define ENOANO 55
|
||||
|
||||
/** @brief Invalid request code */
|
||||
#define EBADRQC 56
|
||||
|
||||
/** @brief Invalid slot */
|
||||
#define EBADSLT 57
|
||||
|
||||
/** @brief Bad font file format */
|
||||
#define EBFONT 59
|
||||
|
||||
/** @brief Device not a stream */
|
||||
#define ENOSTR 60
|
||||
|
||||
/** @brief No data available */
|
||||
#define ENODATA 61
|
||||
|
||||
/** @brief Timer expired */
|
||||
#define ETIME 62
|
||||
|
||||
/** @brief Out of streams resources */
|
||||
#define ENOSR 63
|
||||
|
||||
/** @brief Machine is not on the network */
|
||||
#define ENONET 64
|
||||
|
||||
/** @brief Package not installed */
|
||||
#define ENOPKG 65
|
||||
|
||||
/** @brief Object is remote */
|
||||
#define EREMOTE 66
|
||||
|
||||
/** @brief Link has been severed */
|
||||
#define ENOLINK 67
|
||||
|
||||
/** @brief Advertise error */
|
||||
#define EADV 68
|
||||
|
||||
/** @brief Srmount error */
|
||||
#define ESRMNT 69
|
||||
|
||||
/** @brief Communication error on send */
|
||||
#define ECOMM 70
|
||||
|
||||
/** @brief Protocol error */
|
||||
#define EPROTO 71
|
||||
|
||||
/** @brief Multihop attempted */
|
||||
#define EMULTIHOP 72
|
||||
|
||||
/** @brief RFS specific error */
|
||||
#define EDOTDOT 73
|
||||
|
||||
/** @brief Not a data message */
|
||||
#define EBADMSG 74
|
||||
|
||||
/** @brief Value too large for defined data type */
|
||||
#define EOVERFLOW 75
|
||||
|
||||
/** @brief Name not unique on network */
|
||||
#define ENOTUNIQ 76
|
||||
|
||||
/** @brief File descriptor in bad state */
|
||||
#define EBADFD 77
|
||||
|
||||
/** @brief Remote address changed */
|
||||
#define EREMCHG 78
|
||||
|
||||
/** @brief Can not access a needed shared library */
|
||||
#define ELIBACC 79
|
||||
|
||||
/** @brief Accessing a corrupted shared library */
|
||||
#define ELIBBAD 80
|
||||
|
||||
/** @brief .lib section in a.out corrupted */
|
||||
#define ELIBSCN 81
|
||||
|
||||
/** @brief Attempting to link in too many shared libraries */
|
||||
#define ELIBMAX 82
|
||||
|
||||
/** @brief Cannot exec a shared library directly */
|
||||
#define ELIBEXEC 83
|
||||
|
||||
/** @brief Illegal byte sequence */
|
||||
#define EILSEQ 84
|
||||
|
||||
/** @brief Interrupted system call should be restarted */
|
||||
#define ERESTART 85
|
||||
|
||||
/** @brief Streams pipe error */
|
||||
#define ESTRPIPE 86
|
||||
|
||||
/** @brief Too many users */
|
||||
#define EUSERS 87
|
||||
|
||||
/** @brief Socket operation on non-socket */
|
||||
#define ENOTSOCK 88
|
||||
|
||||
/** @brief Destination address required */
|
||||
#define EDESTADDRREQ 89
|
||||
|
||||
/** @brief Message too long */
|
||||
#define EMSGSIZE 90
|
||||
|
||||
/** @brief Protocol wrong type for socket */
|
||||
#define EPROTOTYPE 91
|
||||
|
||||
/** @brief Protocol not available */
|
||||
#define ENOPROTOOPT 92
|
||||
|
||||
/** @brief Protocol not supported */
|
||||
#define EPROTONOSUPPORT 93
|
||||
|
||||
/** @brief Socket type not supported */
|
||||
#define ESOCKTNOSUPPORT 94
|
||||
|
||||
/** @brief Operation not supported on transport endpoint */
|
||||
#define EOPNOTSUPP 95
|
||||
|
||||
/** @brief Protocol family not supported */
|
||||
#define EPFNOSUPPORT 96
|
||||
|
||||
/** @brief Address family not supported by protocol */
|
||||
#define EAFNOSUPPORT 97
|
||||
|
||||
/** @brief Address already in use */
|
||||
#define EADDRINUSE 98
|
||||
|
||||
/** @brief Cannot assign requested address */
|
||||
#define EADDRNOTAVAIL 99
|
||||
|
||||
/** @brief Network is down */
|
||||
#define ENETDOWN 100
|
||||
|
||||
/** @brief Network is unreachable */
|
||||
#define ENETUNREACH 101
|
||||
|
||||
/** @brief Network dropped connection because of reset */
|
||||
#define ENETRESET 102
|
||||
|
||||
/** @brief Software caused connection abort */
|
||||
#define ECONNABORTED 103
|
||||
|
||||
/** @brief Connection reset by peer */
|
||||
#define ECONNRESET 104
|
||||
|
||||
/** @brief No buffer space available */
|
||||
#define ENOBUFS 105
|
||||
|
||||
/** @brief Transport endpoint is already connected */
|
||||
#define EISCONN 106
|
||||
|
||||
/** @brief Transport endpoint is not connected */
|
||||
#define ENOTCONN 107
|
||||
|
||||
/** @brief Cannot send after transport endpoint shutdown */
|
||||
#define ESHUTDOWN 108
|
||||
|
||||
/** @brief Too many references: cannot splice */
|
||||
#define ETOOMANYREFS 109
|
||||
|
||||
/** @brief Connection timed out */
|
||||
#define ETIMEDOUT 110
|
||||
|
||||
/** @brief Connection refused */
|
||||
#define ECONNREFUSED 111
|
||||
|
||||
/** @brief Host is down */
|
||||
#define EHOSTDOWN 112
|
||||
|
||||
/** @brief No route to host */
|
||||
#define EHOSTUNREACH 113
|
||||
|
||||
/** @brief Operation already in progress */
|
||||
#define EALREADY 114
|
||||
|
||||
/** @brief Operation now in progress */
|
||||
#define EINPROGRESS 115
|
||||
|
||||
/** @brief Stale NFS file handle */
|
||||
#define ESTALE 116
|
||||
|
||||
/** @brief Structure needs cleaning */
|
||||
#define EUCLEAN 117
|
||||
|
||||
/** @brief Not a XENIX named type file */
|
||||
#define ENOTNAM 118
|
||||
|
||||
/** @brief No XENIX semaphores available */
|
||||
#define ENAVAIL 119
|
||||
|
||||
/** @brief Is a named type file */
|
||||
#define EISNAM 120
|
||||
|
||||
/** @brief Remote I/O error */
|
||||
#define EREMOTEIO 121
|
||||
|
||||
/** @brief Quota exceeded */
|
||||
#define EDQUOT 122
|
||||
|
||||
/** @brief No medium found */
|
||||
#define ENOMEDIUM 123
|
||||
|
||||
/** @brief Wrong medium type */
|
||||
#define EMEDIUMTYPE 124
|
||||
|
||||
/** @brief Operation Canceled */
|
||||
#define ECANCELED 125
|
||||
|
||||
/** @brief Required key not available */
|
||||
#define ENOKEY 126
|
||||
|
||||
/** @brief Key has expired */
|
||||
#define EKEYEXPIRED 127
|
||||
|
||||
/** @brief Key has been revoked */
|
||||
#define EKEYREVOKED 128
|
||||
|
||||
/** @brief Key was rejected by service */
|
||||
#define EKEYREJECTED 129
|
||||
|
||||
/** @brief Owner died */
|
||||
#define EOWNERDEAD 130
|
||||
|
||||
/** @brief State not recoverable */
|
||||
#define ENOTRECOVERABLE 131
|
||||
|
||||
extern int *__errno_location(void) __attribute__((const));
|
||||
#define errno (*__errno_location())
|
||||
|
30
include_std/float.h
Normal file
30
include_std/float.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/* Stubs */
|
||||
#define FLT_RADIX 2
|
||||
#if a64
|
||||
#define DBL_MANT_DIG 53
|
||||
#define DBL_MAX_10_EXP 308
|
||||
#define DBL_MAX 1.7976931348623157e+308
|
||||
#elif a32
|
||||
#define DBL_MANT_DIG 24
|
||||
#define DBL_MAX_10_EXP 38
|
||||
#define DBL_MAX 3.4028234663852886e+38
|
||||
#endif
|
30
include_std/functional
Normal file
30
include_std/functional
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename T>
|
||||
struct equal_to
|
||||
{
|
||||
bool operator()(const T &lhs, const T &rhs) const
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
};
|
||||
}
|
66
include_std/mutex
Normal file
66
include_std/mutex
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <task.hpp>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
|
||||
namespace std
|
||||
{
|
||||
/**
|
||||
* A mutex implementation.
|
||||
*
|
||||
* @note The TaskManager must be
|
||||
* initialized before using this class.
|
||||
*/
|
||||
class mutex
|
||||
{
|
||||
private:
|
||||
atomic_bool Locked = false;
|
||||
vector<Tasking::TCB *> Waiting;
|
||||
Tasking::TCB *Holder = nullptr;
|
||||
|
||||
public:
|
||||
void lock();
|
||||
bool try_lock();
|
||||
void unlock();
|
||||
|
||||
mutex() = default;
|
||||
mutex(const mutex &) = delete;
|
||||
~mutex() = default;
|
||||
};
|
||||
|
||||
template <class Mutex>
|
||||
class lock_guard
|
||||
{
|
||||
private:
|
||||
Mutex &m;
|
||||
|
||||
public:
|
||||
explicit lock_guard(Mutex &mutex)
|
||||
: m(mutex) { m.lock(); }
|
||||
|
||||
~lock_guard() { m.unlock(); }
|
||||
|
||||
lock_guard(const lock_guard &) = delete;
|
||||
lock_guard &operator=(const lock_guard &) = delete;
|
||||
};
|
||||
}
|
@ -22,7 +22,8 @@
|
||||
#define __FENNIX_KERNEL_STD_H__
|
||||
|
||||
#include <types.h>
|
||||
#include <std/atomic.hpp>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <std/functional.hpp>
|
||||
#include <std/list.hpp>
|
||||
#include <std/smart_ptr.hpp>
|
||||
@ -30,7 +31,6 @@
|
||||
#include <std/string.hpp>
|
||||
#include <std/unordered_map.hpp>
|
||||
#include <std/utility.hpp>
|
||||
#include <std/vector.hpp>
|
||||
|
||||
/**
|
||||
* @brief // stub namespace for std::align_val_t and new operator
|
||||
|
@ -1,521 +0,0 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_STD_ATOMIC_H__
|
||||
#define __FENNIX_KERNEL_STD_ATOMIC_H__
|
||||
|
||||
#include <types.h>
|
||||
#include <cstddef>
|
||||
#include <debug.h>
|
||||
|
||||
namespace std
|
||||
{
|
||||
#define _atomic(T) T
|
||||
#define builtin_atomic_n(name) __atomic_##name##_n
|
||||
#define builtin_atomic(name) __atomic_##name
|
||||
|
||||
/**
|
||||
* @brief Specifies the memory ordering constraints for atomic operations.
|
||||
*
|
||||
* This enum specifies the possible values for the memory order parameter of atomic operations.
|
||||
*
|
||||
* Possible values are:
|
||||
*
|
||||
* - memory_order_relaxed: There are no synchronization
|
||||
* or ordering constraints imposed on other reads or writes,
|
||||
* only this operation's atomicity is guaranteed.
|
||||
*
|
||||
* - memory_order_consume: A load operation with this
|
||||
* memory order performs a consume operation on the
|
||||
* affected memory location: no reads or writes in the
|
||||
* current thread dependent on the value currently loaded
|
||||
* can be reordered before this load.
|
||||
*
|
||||
* - memory_order_acquire: A load operation with this
|
||||
* memory order performs the acquire operation on the
|
||||
* affected memory location: no reads or writes in the
|
||||
* current thread can be reordered before this load.
|
||||
*
|
||||
* - memory_order_release: A store operation with this
|
||||
* memory order performs the release operation: no reads
|
||||
* or writes in the current thread can be reordered after
|
||||
* this store.
|
||||
*
|
||||
* - memory_order_acq_rel: A read-modify-write operation
|
||||
* with this memory order is both an acquire operation
|
||||
* and a release operation.
|
||||
*
|
||||
* - memory_order_seq_cst: A load operation with this
|
||||
* memory order performs an acquire operation, a store
|
||||
* performs a release operation, and read-modify-write
|
||||
* performs both an acquire operation and a release
|
||||
* operation, plus a single total order exists in which
|
||||
* all threads observe all modifications in the same order.
|
||||
*/
|
||||
enum class memory_order : int
|
||||
{
|
||||
relaxed,
|
||||
consume,
|
||||
acquire,
|
||||
release,
|
||||
acq_rel,
|
||||
seq_cst
|
||||
};
|
||||
|
||||
inline constexpr memory_order memory_order_relaxed = memory_order::relaxed;
|
||||
inline constexpr memory_order memory_order_consume = memory_order::consume;
|
||||
inline constexpr memory_order memory_order_acquire = memory_order::acquire;
|
||||
inline constexpr memory_order memory_order_release = memory_order::release;
|
||||
inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel;
|
||||
inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst;
|
||||
|
||||
template <typename T>
|
||||
class atomic
|
||||
{
|
||||
_atomic(T) value;
|
||||
|
||||
public:
|
||||
atomic() noexcept : value(0) {}
|
||||
atomic(T desired) noexcept : value(desired) {}
|
||||
// atomic(const atomic &) = delete;
|
||||
|
||||
/**
|
||||
* @brief Load the value of the atomic variable
|
||||
*
|
||||
* @note Order must be one of memory_order::relaxed, memory_order::consume, memory_order::acquire or memory_order::seq_cst
|
||||
*
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable
|
||||
*/
|
||||
T load(memory_order order = memory_order::seq_cst) const noexcept
|
||||
{
|
||||
return builtin_atomic_n(load)(&this->value, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc load()
|
||||
*/
|
||||
T load(memory_order order = memory_order::seq_cst) const volatile noexcept
|
||||
{
|
||||
return builtin_atomic_n(load)(&this->value, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Store the value of the atomic variable
|
||||
*
|
||||
* @note Order must be one of memory_order::relaxed, memory_order::release or memory_order::seq_cst
|
||||
*
|
||||
* @param desired The value to store
|
||||
* @param order Memory order constraint to use
|
||||
*/
|
||||
void store(T desired, memory_order order = memory_order::seq_cst) noexcept
|
||||
{
|
||||
builtin_atomic_n(store)(&this->value, desired, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc store()
|
||||
*/
|
||||
void store(T desired, memory_order order = memory_order::seq_cst) volatile noexcept
|
||||
{
|
||||
builtin_atomic_n(store)(&this->value, desired, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exchange the value of the atomic variable
|
||||
*
|
||||
* @param desired The value to exchange
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable before the exchange
|
||||
*/
|
||||
T exchange(T desired, memory_order order = memory_order::seq_cst) noexcept
|
||||
{
|
||||
return builtin_atomic_n(exchange)(&this->value, desired, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc exchange()
|
||||
*/
|
||||
T exchange(T desired, memory_order order = memory_order::seq_cst) volatile noexcept
|
||||
{
|
||||
return builtin_atomic_n(exchange)(&this->value, desired, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare and exchange the value of the atomic variable
|
||||
*
|
||||
* @param expected The expected value
|
||||
* @param desired The desired value
|
||||
* @param success Memory order constraint to use if the exchange succeeds
|
||||
* @param failure Memory order constraint to use if the exchange fails
|
||||
* @return True if the exchange succeeded, false otherwise
|
||||
*/
|
||||
bool compare_exchange_weak(T &expected, T desired, std::memory_order success, std::memory_order failure) noexcept
|
||||
{
|
||||
return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, success, failure);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc compare_exchange_weak()
|
||||
*/
|
||||
bool compare_exchange_weak(T &expected, T desired, std::memory_order success, std::memory_order failure) volatile noexcept
|
||||
{
|
||||
return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, success, failure);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare and exchange the value of the atomic variable
|
||||
*
|
||||
* @param expected The expected value
|
||||
* @param desired The desired value
|
||||
* @param order Memory order constraint to use
|
||||
* @return True if the exchange succeeded, false otherwise
|
||||
*/
|
||||
bool compare_exchange_weak(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) noexcept
|
||||
{
|
||||
return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, order, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc compare_exchange_weak()
|
||||
*/
|
||||
bool compare_exchange_weak(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
|
||||
{
|
||||
return builtin_atomic(compare_exchange_weak)(&this->value, &expected, desired, false, order, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare and exchange the value of the atomic variable
|
||||
*
|
||||
* @param expected The expected value
|
||||
* @param desired The desired value
|
||||
* @param success Memory order constraint to use if the exchange succeeds
|
||||
* @param failure Memory order constraint to use if the exchange fails
|
||||
* @return True if the exchange succeeded, false otherwise
|
||||
*/
|
||||
bool compare_exchange_strong(T &expected, T desired, std::memory_order success, std::memory_order failure) noexcept
|
||||
{
|
||||
return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, success, failure);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc compare_exchange_strong()
|
||||
*/
|
||||
bool compare_exchange_strong(T &expected, T desired, std::memory_order success, std::memory_order failure) volatile noexcept
|
||||
{
|
||||
return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, success, failure);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare and exchange the value of the atomic variable
|
||||
*
|
||||
* @param expected The expected value
|
||||
* @param desired The desired value
|
||||
* @param order Memory order constraint to use
|
||||
* @return True if the exchange succeeded, false otherwise
|
||||
*/
|
||||
bool compare_exchange_strong(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) noexcept
|
||||
{
|
||||
return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, order, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc compare_exchange_strong()
|
||||
*/
|
||||
bool compare_exchange_strong(T &expected, T desired, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
|
||||
{
|
||||
return builtin_atomic(compare_exchange_strong)(&this->value, &expected, desired, true, order, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fetch and add the value of the atomic variable
|
||||
*
|
||||
* @param arg The value to add
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable before the addition
|
||||
*/
|
||||
T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept
|
||||
{
|
||||
return builtin_atomic(fetch_add)(&this->value, arg, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc fetch_add()
|
||||
*/
|
||||
T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
|
||||
{
|
||||
return builtin_atomic(fetch_add)(&this->value, arg, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fetch and subtract the value of the atomic variable
|
||||
*
|
||||
* @param arg The value to subtract
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable before the subtraction
|
||||
*/
|
||||
T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept
|
||||
{
|
||||
return builtin_atomic(fetch_sub)(&this->value, arg, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc fetch_sub()
|
||||
*/
|
||||
T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
|
||||
{
|
||||
return builtin_atomic(fetch_sub)(&this->value, arg, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fetch and bitwise AND the value of the atomic variable
|
||||
*
|
||||
* @param arg The value to AND
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable before the AND
|
||||
*/
|
||||
T fetch_and(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept
|
||||
{
|
||||
return builtin_atomic(fetch_and)(&this->value, arg, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc fetch_and()
|
||||
*/
|
||||
T fetch_and(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
|
||||
{
|
||||
return builtin_atomic(fetch_and)(&this->value, arg, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fetch and bitwise OR the value of the atomic variable
|
||||
*
|
||||
* @param arg The value to OR
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable before the OR
|
||||
*/
|
||||
T fetch_or(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept
|
||||
{
|
||||
return builtin_atomic(fetch_or)(&this->value, arg, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc fetch_or()
|
||||
*/
|
||||
T fetch_or(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
|
||||
{
|
||||
return builtin_atomic(fetch_or)(&this->value, arg, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fetch and bitwise XOR the value of the atomic variable
|
||||
*
|
||||
* @param arg The value to XOR
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable before the XOR
|
||||
*/
|
||||
T fetch_xor(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept
|
||||
{
|
||||
return builtin_atomic(fetch_xor)(&this->value, arg, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc fetch_xor()
|
||||
*/
|
||||
T fetch_xor(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
|
||||
{
|
||||
return builtin_atomic(fetch_xor)(&this->value, arg, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fetch and bitwise NAND the value of the atomic variable
|
||||
*
|
||||
* @param arg The value to NAND
|
||||
* @param order Memory order constraint to use
|
||||
* @return The value of the atomic variable before the NAND
|
||||
*/
|
||||
T fetch_nand(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept
|
||||
{
|
||||
return builtin_atomic(fetch_nand)(&this->value, arg, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc fetch_nand()
|
||||
*/
|
||||
T fetch_nand(T arg, std::memory_order order = std::memory_order_seq_cst) volatile noexcept
|
||||
{
|
||||
return builtin_atomic(fetch_nand)(&this->value, arg, static_cast<int>(order));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notify all threads waiting on this atomic variable
|
||||
*/
|
||||
void notify_all() noexcept
|
||||
{
|
||||
fixme("not implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc notify_all()
|
||||
*/
|
||||
void notify_all() volatile noexcept
|
||||
{
|
||||
fixme("not implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notify one thread waiting on this atomic variable
|
||||
*/
|
||||
void notify_one() noexcept
|
||||
{
|
||||
fixme("not implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc notify_one()
|
||||
*/
|
||||
void notify_one() volatile noexcept
|
||||
{
|
||||
fixme("not implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait for the atomic variable to change
|
||||
*
|
||||
* @param old The value to wait for
|
||||
* @param order Memory order constraint to use
|
||||
*/
|
||||
void wait(T old, std::memory_order order = std::memory_order::seq_cst) const noexcept
|
||||
{
|
||||
fixme("not implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc wait()
|
||||
*/
|
||||
void wait(T old, std::memory_order order = std::memory_order::seq_cst) const volatile noexcept
|
||||
{
|
||||
fixme("not implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether this atomic type is lock-free
|
||||
* @return True if this atomic type is lock-free
|
||||
*/
|
||||
bool is_lock_free() const noexcept
|
||||
{
|
||||
fixme("not implemented");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc is_lock_free()
|
||||
*/
|
||||
bool is_lock_free() const volatile noexcept
|
||||
{
|
||||
fixme("not implemented");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Equals true if this atomic type is always lock-free
|
||||
*/
|
||||
static constexpr bool is_always_lock_free = true;
|
||||
|
||||
T operator++() noexcept { return this->fetch_add(1) + 1; }
|
||||
T operator--() noexcept { return this->fetch_sub(1) - 1; }
|
||||
T operator++(int) noexcept { return this->fetch_add(1); }
|
||||
T operator--(int) noexcept { return this->fetch_sub(1); }
|
||||
|
||||
T operator+=(T desired) noexcept { return this->fetch_add(desired) + desired; }
|
||||
T operator-=(T desired) noexcept { return this->fetch_sub(desired) - desired; }
|
||||
// T operator+=(std::ptrdiff_t desired) noexcept { return this->fetch_add(desired) + desired; }
|
||||
// T operator-=(std::ptrdiff_t desired) noexcept { return this->fetch_sub(desired) - desired; }
|
||||
|
||||
T operator&=(T desired) noexcept { return this->fetch_and(desired) & desired; }
|
||||
T operator|=(T desired) noexcept { return this->fetch_or(desired) | desired; }
|
||||
T operator^=(T desired) noexcept { return this->fetch_xor(desired) ^ desired; }
|
||||
|
||||
T operator->() noexcept { return this->load(); }
|
||||
T operator~() noexcept { return this->fetch_nand(-1); }
|
||||
|
||||
bool operator==(const atomic &other) const noexcept { return this->load() == other.load(); }
|
||||
bool operator==(T other) const noexcept { return this->load() == other; }
|
||||
|
||||
atomic &operator=(const atomic &) = delete;
|
||||
T operator=(T desired) noexcept
|
||||
{
|
||||
this->store(desired);
|
||||
return desired;
|
||||
}
|
||||
|
||||
operator bool() noexcept { return this->load() != 0; }
|
||||
// operator T() noexcept { return this->load(); }
|
||||
operator T() const noexcept { return this->load(); }
|
||||
};
|
||||
|
||||
typedef atomic<bool> atomic_bool;
|
||||
typedef atomic<char> atomic_char;
|
||||
typedef atomic<signed char> atomic_schar;
|
||||
typedef atomic<unsigned char> atomic_uchar;
|
||||
typedef atomic<short> atomic_short;
|
||||
typedef atomic<unsigned short> atomic_ushort;
|
||||
typedef atomic<int> atomic_int;
|
||||
typedef atomic<unsigned int> atomic_uint;
|
||||
typedef atomic<long> atomic_long;
|
||||
typedef atomic<unsigned long> atomic_ulong;
|
||||
typedef atomic<long long> atomic_llong;
|
||||
typedef atomic<unsigned long long> atomic_ullong;
|
||||
typedef atomic<char16_t> atomic_char16_t;
|
||||
typedef atomic<char32_t> atomic_char32_t;
|
||||
typedef atomic<wchar_t> atomic_wchar_t;
|
||||
typedef atomic<int8_t> atomic_int8_t;
|
||||
typedef atomic<uint8_t> atomic_uint8_t;
|
||||
typedef atomic<int16_t> atomic_int16_t;
|
||||
typedef atomic<uint16_t> atomic_uint16_t;
|
||||
typedef atomic<int32_t> atomic_int32_t;
|
||||
typedef atomic<uint32_t> atomic_uint32_t;
|
||||
typedef atomic<int64_t> atomic_int64_t;
|
||||
typedef atomic<uint64_t> atomic_uint64_t;
|
||||
typedef atomic<int_least8_t> atomic_int_least8_t;
|
||||
typedef atomic<uint_least8_t> atomic_uint_least8_t;
|
||||
typedef atomic<int_least16_t> atomic_int_least16_t;
|
||||
typedef atomic<uint_least16_t> atomic_uint_least16_t;
|
||||
typedef atomic<int_least32_t> atomic_int_least32_t;
|
||||
typedef atomic<uint_least32_t> atomic_uint_least32_t;
|
||||
typedef atomic<int_least64_t> atomic_int_least64_t;
|
||||
typedef atomic<uint_least64_t> atomic_uint_least64_t;
|
||||
typedef atomic<int_fast8_t> atomic_int_fast8_t;
|
||||
typedef atomic<uint_fast8_t> atomic_uint_fast8_t;
|
||||
typedef atomic<int_fast16_t> atomic_int_fast16_t;
|
||||
typedef atomic<uint_fast16_t> atomic_uint_fast16_t;
|
||||
typedef atomic<int_fast32_t> atomic_int_fast32_t;
|
||||
typedef atomic<uint_fast32_t> atomic_uint_fast32_t;
|
||||
typedef atomic<int_fast64_t> atomic_int_fast64_t;
|
||||
typedef atomic<uint_fast64_t> atomic_uint_fast64_t;
|
||||
typedef atomic<intptr_t> atomic_intptr_t;
|
||||
typedef atomic<uintptr_t> atomic_uintptr_t;
|
||||
typedef atomic<size_t> atomic_size_t;
|
||||
typedef atomic<ptrdiff_t> atomic_ptrdiff_t;
|
||||
typedef atomic<intmax_t> atomic_intmax_t;
|
||||
typedef atomic<uintmax_t> atomic_uintmax_t;
|
||||
}
|
||||
|
||||
#undef builtin_atomic_n
|
||||
#undef builtin_atomic
|
||||
|
||||
#endif // !__FENNIX_KERNEL_STD_ATOMIC_H__
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <type_trails>
|
||||
#include <debug.h>
|
||||
|
||||
// show debug messages
|
||||
@ -249,24 +250,6 @@ namespace std
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct remove_reference
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct remove_reference<T &>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct remove_reference<T &&>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using remove_reference_t = typename remove_reference<T>::type;
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
// show debug messages
|
||||
// #define DEBUG_CPP_STRING 1
|
||||
// #define DEBUG_CPP_STRING_VERBOSE 1
|
||||
|
||||
#ifdef DEBUG_CPP_STRING
|
||||
#define strdbg(m, ...) debug(m, ##__VA_ARGS__)
|
||||
@ -31,6 +32,12 @@
|
||||
#define strdbg(m, ...)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_CPP_STRING_VERBOSE
|
||||
#define v_strdbg(m, ...) debug(m, ##__VA_ARGS__)
|
||||
#else
|
||||
#define v_strdbg(m, ...)
|
||||
#endif
|
||||
|
||||
// TODO: Somewhere the delete is called twice, causing a double free error.
|
||||
|
||||
namespace std
|
||||
@ -55,51 +62,65 @@ namespace std
|
||||
this->Capacity = this->Length + 1;
|
||||
this->Data = new char[this->Capacity];
|
||||
strcpy(this->Data, Str);
|
||||
strdbg("New string created: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("New string created: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
}
|
||||
|
||||
~string()
|
||||
{
|
||||
strdbg("String deleted: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("String deleted: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
delete[] this->Data, this->Data = nullptr;
|
||||
}
|
||||
|
||||
size_t length() const
|
||||
{
|
||||
strdbg("String length: %d", this->Length);
|
||||
v_strdbg("String length: %d",
|
||||
this->Length);
|
||||
return this->Length;
|
||||
}
|
||||
|
||||
size_t capacity() const
|
||||
{
|
||||
strdbg("String capacity: %d", this->Capacity);
|
||||
v_strdbg("String capacity: %d",
|
||||
this->Capacity);
|
||||
return this->Capacity;
|
||||
}
|
||||
|
||||
const char *c_str() const
|
||||
{
|
||||
strdbg("String data: \"%s\"", this->Data);
|
||||
v_strdbg("String data: \"%s\"",
|
||||
this->Data);
|
||||
return this->Data;
|
||||
}
|
||||
|
||||
void resize(size_t NewLength)
|
||||
{
|
||||
strdbg("String resize: %d", NewLength);
|
||||
if (NewLength > this->Capacity)
|
||||
if (NewLength < this->Capacity)
|
||||
{
|
||||
size_t newCapacity = NewLength + 1;
|
||||
char *newData = new char[newCapacity];
|
||||
this->Length = NewLength;
|
||||
this->Data[this->Length] = '\0';
|
||||
|
||||
strcpy(newData, this->Data);
|
||||
|
||||
strdbg("old: %#lx, new: %#lx", this->Data, newData);
|
||||
delete[] this->Data;
|
||||
this->Data = newData;
|
||||
this->Capacity = newCapacity;
|
||||
strdbg("String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t newCapacity = NewLength + 1;
|
||||
char *newData = new char[newCapacity];
|
||||
strcpy(newData, this->Data);
|
||||
|
||||
strdbg("old: %#lx, new: %#lx",
|
||||
this->Data, newData);
|
||||
|
||||
delete[] this->Data;
|
||||
this->Data = newData;
|
||||
this->Length = NewLength;
|
||||
this->Data[this->Length] = '\0';
|
||||
strdbg("String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
|
||||
this->Capacity = newCapacity;
|
||||
|
||||
strdbg("String resized: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
}
|
||||
|
||||
void concat(const string &Other)
|
||||
@ -108,7 +129,8 @@ namespace std
|
||||
this->resize(NewLength);
|
||||
|
||||
strcat(this->Data, Other.Data);
|
||||
strdbg("String concatenated: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("String concatenated: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
@ -392,14 +414,26 @@ namespace std
|
||||
for (size_t i = 0; i < Str.Length; i++)
|
||||
this->Data[Pos + i] = Str.Data[i];
|
||||
|
||||
strdbg("String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("String replaced: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
strdbg("String pop_back");
|
||||
if (this->Length > 0)
|
||||
{
|
||||
this->Data[this->Length - 1] = '\0';
|
||||
this->Length--;
|
||||
}
|
||||
}
|
||||
|
||||
string operator+(const string &Other) const
|
||||
{
|
||||
string result = *this;
|
||||
result.concat(Other);
|
||||
strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", result.Data, result.Data, result.Length, result.Capacity);
|
||||
strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
result.Data, result.Data, result.Length, result.Capacity);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -407,21 +441,33 @@ namespace std
|
||||
{
|
||||
string result = *this;
|
||||
result.concat(Other);
|
||||
strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)", result.Data, result.Data, result.Length, result.Capacity);
|
||||
strdbg("String added: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
result.Data, result.Data, result.Length, result.Capacity);
|
||||
return result;
|
||||
}
|
||||
|
||||
string &operator+=(const string &Other)
|
||||
{
|
||||
this->concat(Other);
|
||||
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &operator+=(const char *Other)
|
||||
{
|
||||
this->concat(Other);
|
||||
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &operator+=(char Other)
|
||||
{
|
||||
const char str[2] = {Other, '\0'};
|
||||
this->concat(str);
|
||||
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -430,15 +476,16 @@ namespace std
|
||||
|
||||
// string &operator=(const string &Other)
|
||||
// {
|
||||
// if (this != &Other)
|
||||
// {
|
||||
// delete[] this->Data;
|
||||
// this->Data = Other.Data;
|
||||
// this->Length = Other.Length;
|
||||
// this->Capacity = Other.Capacity;
|
||||
// strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
|
||||
// }
|
||||
// return *this;
|
||||
// if (this != &Other)
|
||||
// {
|
||||
// delete[] this->Data;
|
||||
// this->Data = Other.Data;
|
||||
// this->Length = Other.Length;
|
||||
// this->Capacity = Other.Capacity;
|
||||
// strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
// this->Data, this->Data, this->Length, this->Capacity);
|
||||
// }
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
string &operator=(const char *Other)
|
||||
@ -448,21 +495,24 @@ namespace std
|
||||
delete[] this->Data;
|
||||
this->Data = new char[this->Capacity];
|
||||
strcpy(this->Data, Other);
|
||||
strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("String assigned: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &operator<<(const string &Other)
|
||||
{
|
||||
this->concat(Other);
|
||||
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &operator<<(const char *Other)
|
||||
{
|
||||
this->concat(Other);
|
||||
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)", this->Data, this->Data, this->Length, this->Capacity);
|
||||
strdbg("String appended: \"%s\" (data: %#lx, length: %d, capacity: %d)",
|
||||
this->Data, this->Data, this->Length, this->Capacity);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -478,6 +528,18 @@ namespace std
|
||||
return this->Data[Index];
|
||||
}
|
||||
|
||||
char &operator[](size_t Index)
|
||||
{
|
||||
strdbg("String index: %d", Index);
|
||||
return this->Data[Index];
|
||||
}
|
||||
|
||||
const char &operator[](size_t Index) const
|
||||
{
|
||||
strdbg("String index: %d", Index);
|
||||
return this->Data[Index];
|
||||
}
|
||||
|
||||
bool operator==(const string &Other) const
|
||||
{
|
||||
strdbg("String compared: \"%s\" == \"%s\"", this->Data, Other.Data);
|
||||
@ -513,25 +575,29 @@ namespace std
|
||||
iterator &operator++()
|
||||
{
|
||||
++this->Pointer;
|
||||
strdbg("String iterator incremented: %#lx", this->Pointer);
|
||||
strdbg("String iterator incremented: %#lx",
|
||||
this->Pointer);
|
||||
return *this;
|
||||
}
|
||||
|
||||
char &operator*()
|
||||
{
|
||||
strdbg("String iterator dereferenced: %#lx", this->Pointer);
|
||||
strdbg("String iterator dereferenced: %#lx",
|
||||
this->Pointer);
|
||||
return *this->Pointer;
|
||||
}
|
||||
|
||||
bool operator!=(const iterator &Other) const
|
||||
{
|
||||
strdbg("String iterator compared: %#lx != %#lx", this->Pointer, Other.Pointer);
|
||||
strdbg("String iterator compared: %#lx != %#lx",
|
||||
this->Pointer, Other.Pointer);
|
||||
return this->Pointer != Other.Pointer;
|
||||
}
|
||||
|
||||
bool operator==(const iterator &Other) const
|
||||
{
|
||||
strdbg("String iterator compared: %#lx == %#lx", this->Pointer, Other.Pointer);
|
||||
strdbg("String iterator compared: %#lx == %#lx",
|
||||
this->Pointer, Other.Pointer);
|
||||
return this->Pointer == Other.Pointer;
|
||||
}
|
||||
};
|
||||
|
@ -21,111 +21,111 @@
|
||||
#include <types.h>
|
||||
#include <std/functional.hpp>
|
||||
#include <std/utility.hpp>
|
||||
#include <std/vector.hpp>
|
||||
#include <std/list.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename key_type, typename value_type>
|
||||
class unordered_map
|
||||
{
|
||||
public:
|
||||
typedef std::pair<key_type, value_type> key_value_pair;
|
||||
typedef std::list<key_value_pair> bucket;
|
||||
typedef typename std::vector<bucket>::iterator iterator;
|
||||
typedef typename std::vector<bucket>::const_iterator const_iterator;
|
||||
template <typename key_type, typename value_type>
|
||||
class unordered_map
|
||||
{
|
||||
public:
|
||||
typedef std::pair<key_type, value_type> key_value_pair;
|
||||
typedef std::list<key_value_pair> bucket;
|
||||
typedef typename std::vector<bucket>::iterator iterator;
|
||||
typedef typename std::vector<bucket>::const_iterator const_iterator;
|
||||
|
||||
private:
|
||||
static const size_t DEFAULT_NUM_BUCKETS = 10;
|
||||
std::vector<bucket> bkts;
|
||||
private:
|
||||
static const size_t DEFAULT_NUM_BUCKETS = 10;
|
||||
std::vector<bucket> bkts;
|
||||
|
||||
size_t hash(const key_type &key) const
|
||||
{
|
||||
std::hash<key_type> hash_function;
|
||||
return hash_function(key) % this->bkts.size();
|
||||
}
|
||||
size_t hash(const key_type &key) const
|
||||
{
|
||||
std::hash<key_type> hash_function;
|
||||
return hash_function(key) % this->bkts.size();
|
||||
}
|
||||
|
||||
public:
|
||||
unordered_map() : bkts(DEFAULT_NUM_BUCKETS) {}
|
||||
unordered_map(size_t num_buckets) : bkts(num_buckets) {}
|
||||
public:
|
||||
unordered_map() : bkts(DEFAULT_NUM_BUCKETS) {}
|
||||
unordered_map(size_t num_buckets) : bkts(num_buckets) {}
|
||||
|
||||
void insert(const key_value_pair &pair)
|
||||
{
|
||||
size_t bucket_index = hash(pair.first);
|
||||
bucket &bkt = this->bkts[bucket_index];
|
||||
for (auto it = bkt.begin(); it != bkt.end(); ++it)
|
||||
{
|
||||
if (it->first == pair.first)
|
||||
{
|
||||
it->second = pair.second;
|
||||
return;
|
||||
}
|
||||
}
|
||||
bkt.push_back(pair);
|
||||
}
|
||||
void insert(const key_value_pair &pair)
|
||||
{
|
||||
size_t bucket_index = hash(pair.first);
|
||||
bucket &bkt = this->bkts[bucket_index];
|
||||
for (auto it = bkt.begin(); it != bkt.end(); ++it)
|
||||
{
|
||||
if (it->first == pair.first)
|
||||
{
|
||||
it->second = pair.second;
|
||||
return;
|
||||
}
|
||||
}
|
||||
bkt.push_back(pair);
|
||||
}
|
||||
|
||||
bool contains(const key_type &key) const
|
||||
{
|
||||
size_t bucket_index = hash(key);
|
||||
const bucket &bkt = this->bkts[bucket_index];
|
||||
for (auto it = bkt.begin(); it != bkt.end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool contains(const key_type &key) const
|
||||
{
|
||||
size_t bucket_index = hash(key);
|
||||
const bucket &bkt = this->bkts[bucket_index];
|
||||
for (auto it = bkt.begin(); it != bkt.end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
iterator find(const key_type &k)
|
||||
{
|
||||
size_t bucket_index = hash(k);
|
||||
bucket &bkt = this->bkts[bucket_index];
|
||||
for (auto it = bkt.begin(); it != bkt.end(); ++it)
|
||||
{
|
||||
if (it->first == k)
|
||||
return it;
|
||||
}
|
||||
return bkt.end();
|
||||
}
|
||||
iterator find(const key_type &k)
|
||||
{
|
||||
size_t bucket_index = hash(k);
|
||||
bucket &bkt = this->bkts[bucket_index];
|
||||
for (auto it = bkt.begin(); it != bkt.end(); ++it)
|
||||
{
|
||||
if (it->first == k)
|
||||
return it;
|
||||
}
|
||||
return bkt.end();
|
||||
}
|
||||
|
||||
const_iterator find(const key_type &k) const
|
||||
{
|
||||
size_t bucket_index = hash(k);
|
||||
const bucket &bkt = this->bkts[bucket_index];
|
||||
for (auto it = bkt.begin(); it != bkt.end(); ++it)
|
||||
{
|
||||
if (it->first == k)
|
||||
return it;
|
||||
}
|
||||
return bkt.end();
|
||||
}
|
||||
const_iterator find(const key_type &k) const
|
||||
{
|
||||
size_t bucket_index = hash(k);
|
||||
const bucket &bkt = this->bkts[bucket_index];
|
||||
for (auto it = bkt.begin(); it != bkt.end(); ++it)
|
||||
{
|
||||
if (it->first == k)
|
||||
return it;
|
||||
}
|
||||
return bkt.end();
|
||||
}
|
||||
|
||||
iterator end() noexcept { return this->bkts.end(); }
|
||||
iterator end() { return this->bkts.end(); }
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
size_t count = 0;
|
||||
foreach (const auto &bkt in this->bkts)
|
||||
count += bkt.size();
|
||||
size_t size() const
|
||||
{
|
||||
size_t count = 0;
|
||||
foreach (const auto &bkt in this->bkts)
|
||||
count += bkt.size();
|
||||
|
||||
return count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
value_type &operator[](const key_type &key)
|
||||
{
|
||||
size_t bucket_index = hash(key);
|
||||
bucket &bkt = this->bkts[bucket_index];
|
||||
for (auto it = bkt.begin(); it != bkt.end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
return it->second;
|
||||
}
|
||||
bkt.emplace_back(key, value_type());
|
||||
return bkt.back().second;
|
||||
}
|
||||
};
|
||||
value_type &operator[](const key_type &key)
|
||||
{
|
||||
size_t bucket_index = hash(key);
|
||||
bucket &bkt = this->bkts[bucket_index];
|
||||
for (auto it = bkt.begin(); it != bkt.end(); ++it)
|
||||
{
|
||||
if (it->first == key)
|
||||
return it->second;
|
||||
}
|
||||
bkt.emplace_back(key, value_type());
|
||||
return bkt.back().second;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_STD_UNORDERED_MAP_H__
|
||||
|
@ -1,286 +0,0 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_STD_VECTOR_H__
|
||||
#define __FENNIX_KERNEL_STD_VECTOR_H__
|
||||
|
||||
#include <types.h>
|
||||
#include <assert.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <class T>
|
||||
class vector
|
||||
{
|
||||
private:
|
||||
size_t VectorSize = 0;
|
||||
size_t VectorCapacity = 0;
|
||||
T *VectorBuffer = nullptr;
|
||||
|
||||
public:
|
||||
typedef T *iterator;
|
||||
typedef const T *const_iterator;
|
||||
|
||||
NIF vector()
|
||||
{
|
||||
#ifdef DEBUG_MEM_ALLOCATION
|
||||
debug("VECTOR INIT: vector( )");
|
||||
#endif
|
||||
VectorCapacity = 0;
|
||||
VectorSize = 0;
|
||||
VectorBuffer = 0;
|
||||
}
|
||||
|
||||
NIF vector(size_t Size)
|
||||
{
|
||||
VectorCapacity = Size;
|
||||
VectorSize = Size;
|
||||
#ifdef DEBUG_MEM_ALLOCATION
|
||||
debug("VECTOR INIT: vector( %lld )", Size);
|
||||
#endif
|
||||
VectorBuffer = new T[Size];
|
||||
}
|
||||
|
||||
NIF vector(size_t Size, const T &Initial)
|
||||
{
|
||||
VectorSize = Size;
|
||||
VectorCapacity = Size;
|
||||
#ifdef DEBUG_MEM_ALLOCATION
|
||||
debug("VECTOR INIT: vector( %lld %llx )", Size, Initial);
|
||||
#endif
|
||||
assert(Size > 0);
|
||||
VectorBuffer = new T[Size];
|
||||
for (size_t i = 0; i < Size; i++)
|
||||
VectorBuffer[i] = Initial;
|
||||
}
|
||||
|
||||
NIF vector(const vector<T> &v)
|
||||
{
|
||||
VectorSize = v.VectorSize;
|
||||
VectorCapacity = v.VectorCapacity;
|
||||
#ifdef DEBUG_MEM_ALLOCATION
|
||||
debug("VECTOR INIT: vector( <vector> )->Size: %lld", VectorSize);
|
||||
#endif
|
||||
if (!v.VectorBuffer || VectorSize <= 0)
|
||||
return;
|
||||
|
||||
VectorBuffer = new T[VectorSize];
|
||||
for (size_t i = 0; i < VectorSize; i++)
|
||||
VectorBuffer[i] = v.VectorBuffer[i];
|
||||
}
|
||||
|
||||
NIF ~vector()
|
||||
{
|
||||
#ifdef DEBUG_MEM_ALLOCATION
|
||||
debug("VECTOR INIT: ~vector( ~%lx )", VectorBuffer);
|
||||
#endif
|
||||
VectorSize = 0;
|
||||
VectorCapacity = 0;
|
||||
if (VectorBuffer != nullptr)
|
||||
{
|
||||
delete[] VectorBuffer, VectorBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NIF void remove(size_t Position)
|
||||
{
|
||||
if (Position >= VectorSize)
|
||||
return;
|
||||
memset(&*(VectorBuffer + Position), 0, sizeof(T));
|
||||
for (size_t i = 0; i < VectorSize - 1; i++)
|
||||
{
|
||||
*(VectorBuffer + Position + i) = *(VectorBuffer + Position + i + 1);
|
||||
}
|
||||
VectorSize--;
|
||||
}
|
||||
|
||||
NIF void remove(const T &Value)
|
||||
{
|
||||
for (size_t i = 0; i < VectorSize; i++)
|
||||
{
|
||||
if (VectorBuffer[i] == Value)
|
||||
{
|
||||
remove(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NIF T &null_elem()
|
||||
{
|
||||
static T null_elem{};
|
||||
return null_elem;
|
||||
}
|
||||
|
||||
NIF bool null_elem(size_t Index)
|
||||
{
|
||||
if (!reinterpret_cast<uintptr_t>(&VectorBuffer[Index]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
NIF T &next(size_t Position)
|
||||
{
|
||||
if (Position + 1 < VectorSize && reinterpret_cast<uintptr_t>(&VectorBuffer[Position + 1]))
|
||||
return VectorBuffer[Position + 1];
|
||||
warn("next( %lld ) is null (requested by %#lx)", Position, __builtin_return_address(0));
|
||||
return this->null_elem();
|
||||
}
|
||||
|
||||
NIF T &prev(size_t Position)
|
||||
{
|
||||
if (Position > 0 && reinterpret_cast<uintptr_t>(&VectorBuffer[Position - 1]))
|
||||
return VectorBuffer[Position - 1];
|
||||
warn("prev( %lld ) is null (requested by %#lx)", Position, __builtin_return_address(0));
|
||||
return this->null_elem();
|
||||
}
|
||||
|
||||
NIF T &next(const T &Value)
|
||||
{
|
||||
for (size_t i = 0; i < VectorSize; i++)
|
||||
{
|
||||
if (VectorBuffer[i] == Value)
|
||||
{
|
||||
if (i + 1 < VectorSize && reinterpret_cast<uintptr_t>(&VectorBuffer[i + 1]))
|
||||
return VectorBuffer[i + 1];
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
warn("next( %#lx ) is null (requested by %#lx)", Value, __builtin_return_address(0));
|
||||
return this->null_elem();
|
||||
}
|
||||
|
||||
NIF T &prev(const T &Value)
|
||||
{
|
||||
for (size_t i = 0; i < VectorSize; i++)
|
||||
{
|
||||
if (VectorBuffer[i] == Value)
|
||||
{
|
||||
if (i > 0 && reinterpret_cast<uintptr_t>(&VectorBuffer[i - 1]))
|
||||
return VectorBuffer[i - 1];
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
warn("prev( %#lx ) is null (requested by %#lx)", Value, __builtin_return_address(0));
|
||||
return this->null_elem();
|
||||
}
|
||||
|
||||
NIF size_t capacity() const { return VectorCapacity; }
|
||||
|
||||
NIF size_t size() const { return VectorSize; }
|
||||
|
||||
NIF bool empty() const;
|
||||
|
||||
NIF iterator begin() { return VectorBuffer; }
|
||||
|
||||
NIF iterator end() { return VectorBuffer + size(); }
|
||||
|
||||
NIF T &front() { return VectorBuffer[0]; }
|
||||
|
||||
NIF T &back() { return VectorBuffer[VectorSize - 1]; }
|
||||
|
||||
NIF void push_back(const T &Value)
|
||||
{
|
||||
if (VectorSize >= VectorCapacity)
|
||||
reserve(VectorCapacity + 5);
|
||||
VectorBuffer[VectorSize++] = Value;
|
||||
}
|
||||
|
||||
NIF void pop_back() { VectorSize--; }
|
||||
|
||||
NIF void reverse()
|
||||
{
|
||||
if (VectorSize <= 1)
|
||||
return;
|
||||
for (size_t i = 0, j = VectorSize - 1; i < j; i++, j--)
|
||||
{
|
||||
T c = *(VectorBuffer + i);
|
||||
*(VectorBuffer + i) = *(VectorBuffer + j);
|
||||
*(VectorBuffer + j) = c;
|
||||
}
|
||||
}
|
||||
|
||||
NIF void reserve(size_t Capacity)
|
||||
{
|
||||
if (VectorBuffer == 0)
|
||||
{
|
||||
VectorSize = 0;
|
||||
VectorCapacity = 0;
|
||||
}
|
||||
#ifdef DEBUG_MEM_ALLOCATION
|
||||
debug("VECTOR ALLOCATION: reverse( %lld )", Capacity);
|
||||
#endif
|
||||
T *NewBuffer = new T[Capacity];
|
||||
size_t _Size = Capacity < VectorSize ? Capacity : VectorSize;
|
||||
for (size_t i = 0; i < _Size; i++)
|
||||
NewBuffer[i] = VectorBuffer[i];
|
||||
VectorCapacity = Capacity;
|
||||
#ifdef DEBUG_MEM_ALLOCATION
|
||||
debug("VECTOR ALLOCATION: reverse( <Capacity> )->Buffer:~%lld", VectorBuffer);
|
||||
#endif
|
||||
delete[] VectorBuffer;
|
||||
VectorBuffer = NewBuffer;
|
||||
}
|
||||
|
||||
NIF void resize(size_t Size)
|
||||
{
|
||||
reserve(Size);
|
||||
VectorSize = Size;
|
||||
}
|
||||
|
||||
NIF void clear()
|
||||
{
|
||||
VectorCapacity = 0;
|
||||
VectorSize = 0;
|
||||
if (VectorBuffer != nullptr)
|
||||
{
|
||||
delete[] VectorBuffer, VectorBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NIF T *data() { return VectorBuffer; }
|
||||
|
||||
NIF T &operator[](size_t Index)
|
||||
{
|
||||
if (!reinterpret_cast<uintptr_t>(&VectorBuffer[Index]))
|
||||
{
|
||||
warn("operator[]( %lld ) is null (requested by %#lx)", Index, __builtin_return_address(0));
|
||||
return this->null_elem();
|
||||
}
|
||||
return VectorBuffer[Index];
|
||||
}
|
||||
|
||||
NIF vector<T> &operator=(const vector<T> &v)
|
||||
{
|
||||
delete[] VectorBuffer;
|
||||
VectorSize = v.VectorSize;
|
||||
VectorCapacity = v.VectorCapacity;
|
||||
#ifdef DEBUG_MEM_ALLOCATION
|
||||
debug("VECTOR ALLOCATION: operator=( <vector> )->Size:%lld", VectorSize);
|
||||
#endif
|
||||
VectorBuffer = new T[VectorSize];
|
||||
for (size_t i = 0; i < VectorSize; i++)
|
||||
VectorBuffer[i] = v.VectorBuffer[i];
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_STD_VECTOR_H__
|
@ -20,6 +20,4 @@
|
||||
|
||||
#include <types.h>
|
||||
|
||||
|
||||
|
||||
#endif // !__FENNIX_KERNEL_STDARG_H__
|
||||
|
45
include_std/type_trails
Normal file
45
include_std/type_trails
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename T>
|
||||
struct is_trivially_copyable
|
||||
{
|
||||
static constexpr bool value = __is_trivially_copyable(T);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct remove_reference
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct remove_reference<T &>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct remove_reference<T &&>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
}
|
29
include_std/utility
Normal file
29
include_std/utility
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_trails>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename T>
|
||||
typename std::remove_reference<T>::type &&move(T &&arg)
|
||||
{
|
||||
return static_cast<typename std::remove_reference<T>::type &&>(arg);
|
||||
}
|
||||
}
|
@ -16,4 +16,288 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <std/vector.hpp>
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <type_trails>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
// #define DEBUG_VECTOR_MESSAGES 1
|
||||
|
||||
#ifdef DEBUG_VECTOR_MESSAGES
|
||||
#define vDebug(m, ...) debug(m, ##__VA_ARGS__)
|
||||
#else
|
||||
#define vDebug(m, ...)
|
||||
#endif
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <class T>
|
||||
class vector
|
||||
{
|
||||
private:
|
||||
size_t VectorSize = 0;
|
||||
size_t VectorCapacity = 0;
|
||||
T *VectorBuffer = nullptr;
|
||||
|
||||
public:
|
||||
typedef T *iterator;
|
||||
typedef const T *const_iterator;
|
||||
|
||||
vector() { vDebug("%#lx: ( empty init )", this); }
|
||||
|
||||
vector(size_t Size)
|
||||
: VectorSize(Size),
|
||||
VectorCapacity(Size),
|
||||
VectorBuffer(new T[Size])
|
||||
{
|
||||
vDebug("%#lx: ( init w/size: %lld )", this, Size);
|
||||
}
|
||||
|
||||
vector(size_t Size, const T &Initial)
|
||||
: VectorSize(Size),
|
||||
VectorCapacity(Size),
|
||||
VectorBuffer(new T[Size])
|
||||
{
|
||||
vDebug("%#lx: ( init w/size: %lld, initial vector: %llx )", this,
|
||||
Size, Initial);
|
||||
|
||||
assert(Size > 0);
|
||||
for (size_t i = 0; i < Size; i++)
|
||||
VectorBuffer[i] = Initial;
|
||||
}
|
||||
|
||||
vector(const vector<T> &v)
|
||||
: VectorSize(v.VectorSize),
|
||||
VectorCapacity(v.VectorCapacity),
|
||||
VectorBuffer(nullptr)
|
||||
{
|
||||
vDebug("%#lx: ( vector copy: %#lx )", this, &v);
|
||||
|
||||
if (!v.VectorBuffer || VectorSize <= 0)
|
||||
return;
|
||||
|
||||
VectorBuffer = new T[VectorSize];
|
||||
std::copy(v.VectorBuffer, v.VectorBuffer + VectorSize, VectorBuffer);
|
||||
}
|
||||
|
||||
~vector()
|
||||
{
|
||||
vDebug("%#lx: ( deinit )", this);
|
||||
|
||||
VectorSize = 0;
|
||||
VectorCapacity = 0;
|
||||
if (VectorBuffer != nullptr)
|
||||
{
|
||||
delete[] VectorBuffer;
|
||||
VectorBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void erase(iterator Position)
|
||||
{
|
||||
vDebug("%#lx: Erasing element at position %lld (v. size: %lld)", this,
|
||||
Position - this->VectorBuffer, this->VectorSize);
|
||||
|
||||
if (Position == this->end())
|
||||
{
|
||||
warn("%#lx: Cannot erase element at end of vector", this);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(Position >= this->VectorBuffer);
|
||||
assert(Position < this->VectorBuffer + this->VectorSize);
|
||||
|
||||
size_t index = Position - this->VectorBuffer;
|
||||
|
||||
if (std::is_trivially_copyable<T>::value)
|
||||
{
|
||||
this->VectorBuffer[index] = T();
|
||||
vDebug("%#lx: %#lx is trivially copyable", this,
|
||||
&this->VectorBuffer[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->VectorBuffer[index].~T();
|
||||
vDebug("%#lx: %#lx is not trivially copyable", this,
|
||||
&this->VectorBuffer[index]);
|
||||
}
|
||||
|
||||
for (size_t i = index; i < this->VectorSize - 1; ++i)
|
||||
{
|
||||
this->VectorBuffer[i] = std::move(this->VectorBuffer[i + 1]);
|
||||
}
|
||||
this->VectorSize--;
|
||||
}
|
||||
|
||||
T &next(size_t Position)
|
||||
{
|
||||
if (Position + 1 < this->VectorSize)
|
||||
return this->VectorBuffer[Position + 1];
|
||||
|
||||
warn("%#lx: next( %lld ) is null (requested by %#lx)", this,
|
||||
Position, __builtin_return_address(0));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
T &prev(size_t Position)
|
||||
{
|
||||
if (Position > 0)
|
||||
return this->VectorBuffer[Position - 1];
|
||||
|
||||
warn("%#lx: prev( %lld ) is null (requested by %#lx)", this,
|
||||
Position, __builtin_return_address(0));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
T &next(const T &Value)
|
||||
{
|
||||
for (size_t i = 0; i < this->VectorSize; i++)
|
||||
{
|
||||
if (std::equal_to<T>()(this->VectorBuffer[i], Value))
|
||||
{
|
||||
if (i + 1 < this->VectorSize)
|
||||
return this->VectorBuffer[i + 1];
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
warn("%#lx: next( %#lx ) is null (requested by %#lx)", this,
|
||||
Value, __builtin_return_address(0));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
T &prev(const T &Value)
|
||||
{
|
||||
for (size_t i = 0; i < this->VectorSize; i++)
|
||||
{
|
||||
if (std::equal_to<T>()(this->VectorBuffer[i], Value))
|
||||
{
|
||||
if (i > 0)
|
||||
return this->VectorBuffer[i - 1];
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
warn("%#lx: prev( %#lx ) is null (requested by %#lx)", this,
|
||||
Value, __builtin_return_address(0));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void push_back(const T &Value)
|
||||
{
|
||||
vDebug("%#lx: push_back( %#lx )", this, Value);
|
||||
|
||||
if (this->VectorSize >= this->VectorCapacity)
|
||||
{
|
||||
size_t newCapacity = this->VectorCapacity == 0
|
||||
? 1
|
||||
: this->VectorCapacity * 2;
|
||||
reserve(newCapacity);
|
||||
}
|
||||
|
||||
this->VectorBuffer[this->VectorSize++] = Value;
|
||||
}
|
||||
|
||||
void reverse()
|
||||
{
|
||||
if (this->VectorSize <= 1)
|
||||
return;
|
||||
|
||||
for (size_t i = 0, j = this->VectorSize - 1; i < j; i++, j--)
|
||||
{
|
||||
T &elem1 = this->VectorBuffer[i];
|
||||
T &elem2 = this->VectorBuffer[j];
|
||||
std::swap(elem1, elem2);
|
||||
}
|
||||
}
|
||||
|
||||
void reserve(size_t Capacity)
|
||||
{
|
||||
assert(!(Capacity <= VectorCapacity));
|
||||
|
||||
T *NewBuffer = new T[Capacity];
|
||||
size_t Size = std::min(Capacity, this->VectorSize);
|
||||
for (size_t i = 0; i < Size; i++)
|
||||
NewBuffer[i] = std::move(this->VectorBuffer[i]);
|
||||
|
||||
vDebug("%#lx: reserve( %lld )->Buffer:~%#lx", this,
|
||||
Capacity, this->VectorBuffer);
|
||||
|
||||
delete[] this->VectorBuffer;
|
||||
this->VectorBuffer = NewBuffer;
|
||||
this->VectorCapacity = Capacity;
|
||||
}
|
||||
|
||||
void resize(size_t Size)
|
||||
{
|
||||
reserve(Size);
|
||||
this->VectorSize = Size;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
this->VectorCapacity = 0;
|
||||
this->VectorSize = 0;
|
||||
if (VectorBuffer != nullptr)
|
||||
{
|
||||
delete[] this->VectorBuffer;
|
||||
this->VectorBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
T &operator[](size_t Index)
|
||||
{
|
||||
if (Index >= this->VectorSize || !this->VectorBuffer)
|
||||
{
|
||||
warn("%#lx: operator[]( %lld ) is null (requested by %#lx)", this,
|
||||
Index, __builtin_return_address(0));
|
||||
|
||||
static T null_elem{};
|
||||
return null_elem;
|
||||
}
|
||||
return this->VectorBuffer[Index];
|
||||
}
|
||||
|
||||
vector<T> &operator=(const vector<T> &v)
|
||||
{
|
||||
if (this == &v)
|
||||
return *this;
|
||||
|
||||
delete[] this->VectorBuffer;
|
||||
this->VectorSize = v.VectorSize;
|
||||
this->VectorCapacity = v.VectorCapacity;
|
||||
|
||||
vDebug("%#lx: operator=( <vector> )->Size:%lld", this,
|
||||
this->VectorSize);
|
||||
|
||||
this->VectorBuffer = new T[this->VectorSize];
|
||||
for (size_t i = 0; i < this->VectorSize; i++)
|
||||
this->VectorBuffer[i] = v.VectorBuffer[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void pop_back() { this->VectorSize--; }
|
||||
T &front() { return this->VectorBuffer[0]; }
|
||||
T &back() { return this->VectorBuffer[this->VectorSize - 1]; }
|
||||
T *data() { return this->VectorBuffer; }
|
||||
bool empty() const { return this->VectorSize == 0; }
|
||||
size_t capacity() const { return this->VectorCapacity; }
|
||||
size_t size() const { return this->VectorSize; }
|
||||
iterator begin() { return this->VectorBuffer; }
|
||||
iterator end() { return this->VectorBuffer + size(); }
|
||||
const_iterator begin() const { return this->VectorBuffer; }
|
||||
const_iterator end() const { return this->VectorBuffer + size(); }
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user