intial commit

This commit is contained in:
2023-05-29 14:51:44 +02:00
commit da781b87f2
38 changed files with 4842 additions and 0 deletions

128
source/mijin/types/name.cpp Normal file
View File

@@ -0,0 +1,128 @@
#include "./name.hpp"
#include <algorithm>
#include <mutex>
#include <shared_mutex>
#include <unordered_map>
#include <string>
#include <vector>
// note: the implementation assumes that std::vector moves the strings on resize and that strings don't reallocate when moved
// while that should be the case for any sane STL implementation it may cause dangling pointers if it's not
namespace mijin
{
//
// internal defines
//
//
// internal constants
//
//
// internal types
//
//
// internal variables
//
//
// internal functions
//
static std::vector<std::string>& getGlobalNames()
{
static std::vector<std::string> names;
return names;
}
static std::vector<std::string>& getLocalNames()
{
static thread_local std::vector<std::string> names;
return names;
}
static std::shared_mutex& getGlobalNamesMutex()
{
static std::shared_mutex mutex;
return mutex;
}
static std::unordered_map<std::string_view, std::size_t>& getLocalNameCache()
{
static std::unordered_map<std::string_view, std::size_t> cache;
return cache;
}
static void copyNamesToLocal()
{
const std::size_t oldSize = getLocalNames().size();
getLocalNames().resize(getGlobalNames().size());
std::copy(getGlobalNames().begin() + static_cast<long>(oldSize), getGlobalNames().end(), getLocalNames().begin() + static_cast<long>(oldSize));
}
static std::size_t getOrCreateStringID(std::string_view string)
{
// 1. check the cache
auto it = getLocalNameCache().find(std::string(string));
if (it != getLocalNameCache().end()) {
return it->second;
}
// 2. check the local state
for (std::size_t idx = 0; idx < getLocalNames().size(); ++idx)
{
if (getLocalNames()[idx] == string)
{
getLocalNameCache()[std::string(string)] = idx;
return idx;
}
}
// 3. copy global state and check local again
{
std::shared_lock lock(getGlobalNamesMutex());
copyNamesToLocal();
}
for (std::size_t idx = 0; idx < getLocalNames().size(); ++idx)
{
if (getLocalNames()[idx] == string)
{
getLocalNameCache()[std::string(string)] = idx;
return idx;
}
}
// 4. insert a new ID
std::unique_lock lock(getGlobalNamesMutex());
const std::size_t idx = getGlobalNames().size();
getGlobalNames().emplace_back(string);
copyNamesToLocal();
getLocalNameCache()[std::string(string)] = idx;
return idx;
}
//
// public functions
//
Name::Name(std::string_view string) : id_(getOrCreateStringID(string))
{
}
std::string_view Name::stringView() const
{
if (id_ == std::numeric_limits<std::size_t>::max()) {
return {};
}
return getLocalNames().at(id_);
}
} // namespace mijin

View File

@@ -0,0 +1,63 @@
#pragma once
#if !defined(MIJIN_TYPES_NAME_HPP_INCLUDED)
#define MIJIN_TYPES_NAME_HPP_INCLUDED 1
#include <limits>
#include <string_view>
namespace mijin
{
//
// public defines
//
//
// public constants
//
//
// public types
//
class Name
{
private:
std::size_t id_ = std::numeric_limits<std::size_t>::max();
public:
Name() = default;
Name(const Name&) = default;
Name(std::string_view string);
Name(const char* cStr) : Name(std::string_view(cStr)) {}
Name& operator=(const Name&) = default;
auto operator<=>(const Name&) const = default;
[[nodiscard]] std::string_view stringView() const;
[[nodiscard]] const char* c_str() const {
return stringView().data();
}
[[nodiscard]] std::size_t getID() const { return id_; }
};
//
// public functions
//
} // namespace mijin
namespace std
{
template<>
struct hash<mijin::Name> : hash<std::size_t>
{
std::size_t operator()(mijin::Name name) const noexcept {
return hash<std::size_t>::operator()(name.getID());
}
};
}
#endif // !defined(MIJIN_TYPES_NAME_HPP_INCLUDED)