First
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
#pragma once
|
||||
|
||||
#include "tl/detail/prologue.h"
|
||||
#include <EASTL/vector.h>
|
||||
#include <EASTL/array.h>
|
||||
#include <EASTL/unique_ptr.h>
|
||||
#include <atomic>
|
||||
#include <shared_mutex>
|
||||
#include "tl/plain_crash.h"
|
||||
|
||||
//disable the 'strdup' warning
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning( disable : 4996 )
|
||||
#endif
|
||||
|
||||
#ifndef _SCL_SECURE_NO_WARNINGS
|
||||
# define _SCL_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
namespace tl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class string_db;
|
||||
}
|
||||
|
||||
TL_API detail::string_db*& get_shared_string_db_instance_ptr() noexcept;
|
||||
}
|
||||
|
||||
namespace tl
|
||||
{
|
||||
class string;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct TL_API string_cell
|
||||
{
|
||||
friend class string_db_map;
|
||||
|
||||
using length_t = uint32_t; //uint32_t was chosen to avoid the cell to gain 4 bytes in 64 bit configs. We'll never have strings bigger than 4 billion chars (for the foreseeable future)
|
||||
using hash_t = uint32_t;
|
||||
|
||||
length_t length;
|
||||
hash_t hash; //hash for key
|
||||
std::atomic_int counter;
|
||||
// uint32_t padding;
|
||||
|
||||
//this increments the ref_count and returns true IF the cell was not resurrected. So true means the cell was alive before the increment
|
||||
void inc_ref_counter() noexcept { counter.fetch_add(1, std::memory_order_relaxed); }
|
||||
|
||||
//this decrements the ref_count and returns true if the cell is still alive
|
||||
bool dec_ref_counter() noexcept { const int oldRef = counter.fetch_sub(1, std::memory_order_relaxed); TL_PLAIN_ASSERT(oldRef > 0); return oldRef == 1; }
|
||||
};
|
||||
|
||||
static_assert(sizeof(string_cell) % sizeof(uint32_t) == 0);
|
||||
|
||||
class TL_API string_db_map
|
||||
{
|
||||
public:
|
||||
using cell_t = string_cell;
|
||||
|
||||
string_db_map() noexcept;
|
||||
~string_db_map() noexcept;
|
||||
|
||||
//this returns a new or existing cell with the string in the argument
|
||||
cell_t* find(cell_t::hash_t hash, cell_t::length_t length, const char* string) noexcept;
|
||||
cell_t* find_or_add(cell_t::hash_t hash, cell_t::length_t length, const char* string) noexcept;
|
||||
cell_t* allocate_cell(const char* string, cell_t::length_t length, cell_t::hash_t hash) noexcept;
|
||||
|
||||
void free_cell(cell_t* cell) noexcept;
|
||||
void mark_cell_as_unused(cell_t& cell) noexcept;
|
||||
|
||||
void lock() noexcept { m_mutex.lock(); }
|
||||
void unlock() noexcept { m_mutex.unlock(); }
|
||||
|
||||
private:
|
||||
std::mutex m_mutex;
|
||||
uint32_t m_hashmap_size = 0;
|
||||
uint32_t m_hashmap_size_mask = m_hashmap_size - 1;
|
||||
|
||||
eastl::vector<cell_t*> m_buckets;
|
||||
|
||||
std::atomic_int m_used_cell_count = { 0 };
|
||||
|
||||
void rehash(uint32_t new_size) noexcept;
|
||||
|
||||
//size_t m_garbage_size = 0;
|
||||
};
|
||||
|
||||
class TL_API string_db
|
||||
{
|
||||
public:
|
||||
string_db() noexcept;
|
||||
~string_db() noexcept;
|
||||
using cell_t = string_cell;
|
||||
|
||||
static string_db*& get_instance_ptr() noexcept;
|
||||
static string_db& get_instance() noexcept;
|
||||
static void free_instance() noexcept;
|
||||
|
||||
void internalize(const char* str_start, const char* str_end, cell_t*& dst_cell) noexcept;
|
||||
void internalize(const char* str, cell_t*& dst_cell) noexcept;
|
||||
void append_internalize(cell_t& src_cell, const char* str, size_t str_size, cell_t*& dst_cell) noexcept;
|
||||
void free_cell(cell_t& cell) noexcept;
|
||||
|
||||
private:
|
||||
string_db_map m_map;
|
||||
};
|
||||
|
||||
inline string_db*& string_db::get_instance_ptr() noexcept
|
||||
{
|
||||
static string_db*& s_instance = get_shared_string_db_instance_ptr();
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
inline string_db& string_db::get_instance() noexcept
|
||||
{
|
||||
string_db* db = get_instance_ptr();
|
||||
if (!db)
|
||||
TL_PLAIN_CRASH("String DB was deleted");
|
||||
return *db;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user