Fixed font atlas, feature completed garbage collection, and fix math.

This commit is contained in:
Arron David Nelson 2024-06-29 22:20:53 -07:00
parent f030ac62ae
commit 0b298c6130
12 changed files with 283 additions and 180 deletions

View File

@ -42,7 +42,7 @@ set(EHS_SOURCES
src/EHS.cpp include/ehs/EHS.h src/EHS.cpp include/ehs/EHS.h
src/Type.cpp include/ehs/Type.h src/Type.cpp include/ehs/Type.h
src/BaseObj.cpp include/ehs/BaseObj.h src/BaseObj.cpp include/ehs/BaseObj.h
src/GarbageCollector.cpp include/ehs/GarbageCollector.h src/GC.cpp include/ehs/GC.h
src/Log.cpp include/ehs/Log.h src/Log.cpp include/ehs/Log.h
src/URI.cpp include/ehs/URI.h src/URI.cpp include/ehs/URI.h
src/Math.cpp include/ehs/Math.h src/Math.cpp include/ehs/Math.h

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "EHS.h"
#include "Vector.h" #include "Vector.h"
#include "BaseObj.h" #include "BaseObj.h"
#include "ehs/system/Mutex.h" #include "ehs/system/Mutex.h"
@ -10,10 +9,10 @@ namespace ehs
{ {
typedef bool (*GcLogic)(BaseObj*); typedef bool (*GcLogic)(BaseObj*);
class GarbageCollector class GC
{ {
private: private:
static Vector<GcLogic>* logic; static Array<GcLogic> logic;
static Vector<BaseObj*> garbage; static Vector<BaseObj*> garbage;
static UInt_64 max; static UInt_64 max;
static Thread thread; static Thread thread;
@ -27,6 +26,10 @@ namespace ehs
static void Stop(); static void Stop();
static bool HasLogic(GcLogic logicCb);
static bool AddLogic(GcLogic logicCb);
/// Adds an object to the garbage pile to be deleted. /// Adds an object to the garbage pile to be deleted.
/// @param[in] obj The object to be deleted. /// @param[in] obj The object to be deleted.
static void Add(BaseObj* obj); static void Add(BaseObj* obj);
@ -59,5 +62,8 @@ namespace ehs
static void Dump(); static void Dump();
static bool IsRunning(); static bool IsRunning();
private:
static bool ShouldDelete(BaseObj *obj);
}; };
} }

View File

@ -116,20 +116,51 @@ namespace ehs
return sum; return sum;
} }
template <typename T = float>
static T Ln_Taylor(T x)
{
T result = 0;
T term = (x - 1) / (x + 1);
T term_squared = term * term;
T denominator = 1;
T current_term = term;
for (int n = 0; n < 100; ++n)
{
result += current_term / denominator;
current_term *= term_squared;
denominator += 2;
}
return 2 * result;
}
template <typename T = float> template <typename T = float>
static T Ln(T x) static T Ln(T x)
{ {
if (x <= 0) if (x <= 0)
return -1; return -1;
T result = 0; if (x == 1)
return 0;
x = (x - 1) / (x + 1); SSize exp = 0;
while (x > 2)
{
x /= 2;
exp++;
}
for (int i = 1; i <= 19; i += 2) while (x < 0.5)
result += (1 / i) * Exp<T>(x * i); {
x *= 2;
exp--;
}
return 2 * result; T result = Ln_Taylor<T>(x);
result += exp * Ln_Taylor<T>(2);
return result;
} }
/// A method for use of exponents. /// A method for use of exponents.
@ -142,26 +173,35 @@ namespace ehs
static T Pow(const T base, const I exponent) static T Pow(const T base, const I exponent)
{ {
if (base == 0) if (base == 0)
return 0; return (exponent == 0) ? 1 : 0;
if (exponent == 0) if (exponent == 0)
return 1; return 1;
UInt_32 exponentIsInteger = exponent == (UInt_32)exponent; SSize intExp = (SSize)exponent;
UInt_32 baseIsNegative = base < 0; bool isInteger = exponent == intExp;
bool isNeg = base < 0;
if (baseIsNegative && exponentIsInteger) if (isNeg && isInteger)
{ {
T result = Exp<T>(exponent * Ln<T>(-base)); T result = Exp<T>(exponent * Ln<T>(-base));
if (Mod((float)exponent, 2.0f) != 0) if ((SSize)exponent % 2)
result = -result; result = -result;
return result; return result;
} }
else if (!baseIsNegative)
return Exp<T>(exponent * Ln<T>(base));
return 0; if (isNeg && !isInteger)
{
T magnitude = Exp<T>(exponent * Ln<T>(-base));
T angle = exponent * Pi<T>();
T realPart = magnitude * Cos<T>(angle);
T imagPart = magnitude * Sin<T>(angle);
return realPart;
}
return Exp<T>(exponent * Ln<T>(base));
} }
template <typename T = float> template <typename T = float>

View File

@ -1795,23 +1795,23 @@ namespace ehs
return result; return result;
} }
/// A 32-bit FNV-1a hash algorithm. /// A 32-bit FNV-1a hash algorithm.
/// @param [in] str The string to hash. /// @param [in] str The string to hash.
/// @returns The resulting hash. Zero if string does not contain any characters. /// @returns The resulting hash. Zero if string does not contain any characters.
static UInt_32 Hash_32(const Str<T, N>& str) static UInt_32 Hash_32(const Str<T, N>& str)
{ {
if (!str.Size()) if (!str.Size())
return 0; return 0;
const Byte* const bytes = str.ToBytes(); const Byte* const bytes = str.ToBytes();
UInt_32 hash = 2166136261ul; UInt_32 hash = 2166136261ul;
for (N i = 0; i < str.Size(true); ++i) for (N i = 0; i < str.Size(true); ++i)
hash = (hash ^ bytes[i]) * 16777619; hash = (hash ^ bytes[i]) * 16777619;
return hash; return hash;
} }
/// A 32-bit FNV-1a hash algorithm. /// A 32-bit FNV-1a hash algorithm.
/// @returns The resulting hash. Zero if string does not contain any characters. /// @returns The resulting hash. Zero if string does not contain any characters.
@ -1830,23 +1830,23 @@ namespace ehs
return hash; return hash;
} }
/// A 64-bit FNV-1a hash algorithm. /// A 64-bit FNV-1a hash algorithm.
/// @param [in] str The string to hash. /// @param [in] str The string to hash.
/// @returns The resulting hash. Zero if string does not contain any characters. /// @returns The resulting hash. Zero if string does not contain any characters.
static UInt_64 Hash_64(const Str<T, N>& str) static UInt_64 Hash_64(const Str<T, N>& str)
{ {
if (!str.Size()) if (!str.Size())
return 0; return 0;
const Byte* const bytes = str.ToBytes(); const Byte* const bytes = str.ToBytes();
UInt_64 hash = 14695981039346656037ull; UInt_64 hash = 14695981039346656037ull;
for (N i = 0; i < str.Size(true); ++i) for (N i = 0; i < str.Size(true); ++i)
hash = (hash ^ bytes[i]) * 1099511628211; hash = (hash ^ bytes[i]) * 1099511628211;
return hash; return hash;
} }
/// A 64-bit FNV-1a hash algorithm. /// A 64-bit FNV-1a hash algorithm.
/// @returns The resulting hash. Zero if string does not contain any characters. /// @returns The resulting hash. Zero if string does not contain any characters.

View File

@ -62,7 +62,9 @@ namespace ehs
#if defined(EHS_64_BIT) #if defined(EHS_64_BIT)
typedef UInt_64 Size; typedef UInt_64 Size;
typedef SInt_64 SSize;
#elif defined(EHS_32_BIT) #elif defined(EHS_32_BIT)
typedef UInt_32 Size; typedef UInt_32 Size;
typedef SInt_32 SSize;
#endif #endif
} }

View File

@ -2,7 +2,7 @@
#include "ehs/Log.h" #include "ehs/Log.h"
#include "ehs/Version.h" #include "ehs/Version.h"
#include "ehs/io/Console.h" #include "ehs/io/Console.h"
#include "ehs/GarbageCollector.h" #include "ehs/GC.h"
#include "ehs/io/audio/Audio.h" #include "ehs/io/audio/Audio.h"
#include "ehs/io/img/Img.h" #include "ehs/io/img/Img.h"
#include "ehs/io/img/PNG.h" #include "ehs/io/img/PNG.h"
@ -141,13 +141,13 @@ int main()
ehs::DecodeEHM ehs::DecodeEHM
}); });
ehs::GarbageCollector::Start(); ehs::GC::Start();
const ehs::SInt_32 code = Main(&ehs::appName, &ehs::appVerId, &ehs::appVer); const ehs::SInt_32 code = Main(&ehs::appName, &ehs::appVerId, &ehs::appVer);
if (code) if (code)
EHS_LOG_INT(ehs::LogType::WARN, 0, "Executable exited with code #" + ehs::Str_8::FromNum(code) + "."); EHS_LOG_INT(ehs::LogType::WARN, 0, "Executable exited with code #" + ehs::Str_8::FromNum(code) + ".");
ehs::GarbageCollector::Stop(); ehs::GC::Stop();
ehs::Log::OnExit(); ehs::Log::OnExit();

180
src/GC.cpp Normal file
View File

@ -0,0 +1,180 @@
#include "ehs/GC.h"
namespace ehs
{
UInt_32 GarbageCollectionThread(void* params)
{
while (GC::IsRunning())
{
GC::Poll();
Thread::SleepFor(50);
}
GC::Dump();
return 0;
}
Array<GcLogic> GC::logic;
Vector<BaseObj*> GC::garbage(0, 1000);
UInt_64 GC::max = 10;
Thread GC::thread;
Mutex GC::mutex;
bool GC::running = false;
bool GC::Has(const BaseObj* obj)
{
for (UInt_64 i = 0; i < garbage.Size(); ++i)
if (garbage[i] == obj)
return true;
return false;
}
void GC::Start()
{
if (running)
return;
mutex.Initialize();
thread.Start(GarbageCollectionThread, nullptr);
running = true;
}
void GC::Stop()
{
if (!running)
return;
running = false;
thread.Join();
}
bool GC::HasLogic(GcLogic logicCb)
{
for (UInt_64 i = 0; i < logic.Size(); ++i)
if (logic[i] == logicCb)
return true;
return false;
}
bool GC::AddLogic(GcLogic logicCb)
{
if (HasLogic(logicCb))
return false;
if (running)
mutex.Lock();
logic.Push(logicCb);
if (running)
mutex.Unlock();
return true;
}
void GC::Add(BaseObj* obj)
{
if (!obj)
return;
#ifdef EHS_DEBUG
if (Has(obj))
{
EHS_LOG_INT(LogType::ERR, 1, Str_8(obj->GetTypeId(), obj->GetTypeIdSize()) +
" object with address of, \"" + Str_8::FromNum((ehs::Size)obj) + "\" is already in garbage.");
return;
}
#endif
garbage.Push(obj);
}
void GC::SetMax(const UInt_64 newMax)
{
max = newMax;
}
UInt_64 GC::GetMax()
{
return max;
}
void GC::SetStride(const UInt_64 newStride)
{
Dump();
garbage = Vector<BaseObj*>(0, newStride);
}
UInt_64 GC::GetStride()
{
return garbage.Stride();
}
UInt_64 GC::Size()
{
return garbage.Size();
}
void GC::Poll()
{
if (running)
mutex.Lock();
UInt_64 i = 0;
UInt_64 o = 0;
while (garbage.Size() && i < max && o < garbage.Size())
{
if (!ShouldDelete(garbage[o]))
{
o++;
continue;
}
if (o != garbage.Size() - 1)
garbage.Swap(o, garbage.End());
delete garbage.Pop();
i++;
}
if (running)
mutex.Unlock();
}
void GC::Dump()
{
if (running)
mutex.Lock();
for (UInt_64 i = 0; i < garbage.Size(); ++i)
delete garbage[i];
garbage.Clear();
if (running)
mutex.Unlock();
}
bool GC::IsRunning()
{
return running;
}
bool GC::ShouldDelete(BaseObj *obj)
{
for (UInt_64 l = 0; l < logic.Size(); ++l)
if (!logic[l](obj))
return false;
return true;
}
}

View File

@ -1,133 +0,0 @@
#include "ehs/GarbageCollector.h"
namespace ehs
{
UInt_32 GarbageCollectionThread(void* params)
{
while (GarbageCollector::IsRunning())
{
GarbageCollector::Poll();
Thread::SleepFor(50);
}
GarbageCollector::Dump();
return 0;
}
Vector<BaseObj*> GarbageCollector::garbage(0, 1000);
UInt_64 GarbageCollector::max = 10;
Thread GarbageCollector::thread;
Mutex GarbageCollector::mutex;
bool GarbageCollector::running = false;
bool GarbageCollector::Has(const BaseObj* obj)
{
for (UInt_64 i = 0; i < garbage.Size(); ++i)
if (garbage[i] == obj)
return true;
return false;
}
void GarbageCollector::Start()
{
if (running)
return;
mutex.Initialize();
thread.Start(GarbageCollectionThread, nullptr);
running = true;
}
void GarbageCollector::Stop()
{
if (!running)
return;
running = false;
thread.Join();
}
void GarbageCollector::Add(BaseObj* obj)
{
if (!obj)
return;
/*
if (Has(obj))
{
EHS_LOG_INT(LogType::WARN, 1, obj->GetTypeId() + " object with address of, \"" + Str_8::FromNum<USize>((USize)obj) + "\" is already in garbage.");
return;
}
*/
garbage.Push(obj);
}
void GarbageCollector::SetMax(const UInt_64 newMax)
{
max = newMax;
}
UInt_64 GarbageCollector::GetMax()
{
return max;
}
void GarbageCollector::SetStride(const UInt_64 newStride)
{
Dump();
garbage = Vector<BaseObj*>(0, newStride);
}
UInt_64 GarbageCollector::GetStride()
{
return garbage.Stride();
}
UInt_64 GarbageCollector::Size()
{
return garbage.Size();
}
void GarbageCollector::Poll()
{
if (running)
mutex.Lock();
UInt_64 i = 0;
while (i < garbage.Size())
{
garbage.Swap(i, garbage.End());
delete garbage.Pop();
}
if (running)
mutex.Unlock();
}
void GarbageCollector::Dump()
{
if (running)
mutex.Lock();
for (UInt_64 i = 0; i < garbage.Size(); ++i)
delete garbage[i];
garbage.Clear();
if (running)
mutex.Unlock();
}
bool GarbageCollector::IsRunning()
{
return running;
}
}

View File

@ -43,6 +43,7 @@ namespace ehs
atlas = new Byte[resolution.x * resolution.y]; atlas = new Byte[resolution.x * resolution.y];
size = 0; size = 0;
fData.ReadArray(atlas, &size); fData.ReadArray(atlas, &size);
fData.ReadArray(atlas, &size);
} }
FontAtlas::FontAtlas(FontAtlas&& fa) noexcept FontAtlas::FontAtlas(FontAtlas&& fa) noexcept

View File

@ -1,6 +1,7 @@
#include "ehs/io/audio/AudioDevice_ALSA.h" #include "ehs/io/audio/AudioDevice_ALSA.h"
#include "ehs/EHS.h" #include "ehs/EHS.h"
#include "ehs/Log.h" #include "ehs/Log.h"
#include "ehs/io/Console.h"
namespace ehs namespace ehs
{ {
@ -366,13 +367,21 @@ namespace ehs
} }
else else
{ {
EHS_LOG_INT(LogType::ERR, 0, "Wrong value for the audio device type."); EHS_LOG_INT(LogType::ERR, 1, "Wrong value for the audio device type.");
return {};
}
int err = snd_pcm_open(&result.hdl, "default", rType, SND_PCM_NONBLOCK);
if (err < 0)
{
EHS_LOG_INT(LogType::ERR, 2, "Failed to retrieve default audio device with error #" + Str_8::FromNum(err) + ".");
return {}; return {};
} }
snd_pcm_open(&result.hdl, "default", rType, SND_PCM_NONBLOCK);
result.type = AudioDeviceType::OUTPUT; result.type = AudioDeviceType::OUTPUT;
EHS_LOG_SUCCESS();
return result; return result;
} }
@ -380,4 +389,4 @@ namespace ehs
{ {
return {}; return {};
} }
} }

View File

@ -275,7 +275,6 @@ namespace ehs
meshes[i].SetIndices(data.ReadArray<UInt_32, UInt_64>()); meshes[i].SetIndices(data.ReadArray<UInt_32, UInt_64>());
/*
Bone& skeleton = mdl->GetSkeleton(); Bone& skeleton = mdl->GetSkeleton();
UInt_8 boneCount = data.Read<UInt_8>(); UInt_8 boneCount = data.Read<UInt_8>();
for (UInt_8 b = 0; b < boneCount; ++b) for (UInt_8 b = 0; b < boneCount; ++b)
@ -329,7 +328,6 @@ namespace ehs
} }
} }
} }
*/
} }
return true; return true;

View File

@ -29,7 +29,7 @@ namespace ehs
} }
Mesh::Mesh(const Mesh& mesh) Mesh::Mesh(const Mesh& mesh)
: BaseObj((BaseObj&&)mesh), hashId(mesh.hashId), id(mesh.id), vertices(mesh.vertices), indices(mesh.indices) : BaseObj(mesh), hashId(mesh.hashId), id(mesh.id), vertices(mesh.vertices), indices(mesh.indices)
{ {
} }