diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ebe0ff..1dd8539 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,7 @@ set(EHS_SOURCES src/EHS.cpp include/ehs/EHS.h src/Type.cpp include/ehs/Type.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/URI.cpp include/ehs/URI.h src/Math.cpp include/ehs/Math.h diff --git a/include/ehs/GarbageCollector.h b/include/ehs/GC.h similarity index 88% rename from include/ehs/GarbageCollector.h rename to include/ehs/GC.h index 0b97777..c6ad395 100644 --- a/include/ehs/GarbageCollector.h +++ b/include/ehs/GC.h @@ -1,6 +1,5 @@ #pragma once -#include "EHS.h" #include "Vector.h" #include "BaseObj.h" #include "ehs/system/Mutex.h" @@ -10,10 +9,10 @@ namespace ehs { typedef bool (*GcLogic)(BaseObj*); - class GarbageCollector + class GC { private: - static Vector* logic; + static Array logic; static Vector garbage; static UInt_64 max; static Thread thread; @@ -27,6 +26,10 @@ namespace ehs static void Stop(); + static bool HasLogic(GcLogic logicCb); + + static bool AddLogic(GcLogic logicCb); + /// Adds an object to the garbage pile to be deleted. /// @param[in] obj The object to be deleted. static void Add(BaseObj* obj); @@ -59,5 +62,8 @@ namespace ehs static void Dump(); static bool IsRunning(); + + private: + static bool ShouldDelete(BaseObj *obj); }; } diff --git a/include/ehs/Math.h b/include/ehs/Math.h index 9184a94..ddec883 100644 --- a/include/ehs/Math.h +++ b/include/ehs/Math.h @@ -116,20 +116,51 @@ namespace ehs return sum; } + template + 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 static T Ln(T x) { if (x <= 0) 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) - result += (1 / i) * Exp(x * i); + while (x < 0.5) + { + x *= 2; + exp--; + } - return 2 * result; + T result = Ln_Taylor(x); + result += exp * Ln_Taylor(2); + + return result; } /// A method for use of exponents. @@ -142,26 +173,35 @@ namespace ehs static T Pow(const T base, const I exponent) { if (base == 0) - return 0; + return (exponent == 0) ? 1 : 0; if (exponent == 0) return 1; - UInt_32 exponentIsInteger = exponent == (UInt_32)exponent; - UInt_32 baseIsNegative = base < 0; + SSize intExp = (SSize)exponent; + bool isInteger = exponent == intExp; + bool isNeg = base < 0; - if (baseIsNegative && exponentIsInteger) + if (isNeg && isInteger) { T result = Exp(exponent * Ln(-base)); - if (Mod((float)exponent, 2.0f) != 0) + if ((SSize)exponent % 2) result = -result; return result; } - else if (!baseIsNegative) - return Exp(exponent * Ln(base)); - return 0; + if (isNeg && !isInteger) + { + T magnitude = Exp(exponent * Ln(-base)); + T angle = exponent * Pi(); + T realPart = magnitude * Cos(angle); + T imagPart = magnitude * Sin(angle); + + return realPart; + } + + return Exp(exponent * Ln(base)); } template diff --git a/include/ehs/Str.h b/include/ehs/Str.h index e549792..e2a2b58 100644 --- a/include/ehs/Str.h +++ b/include/ehs/Str.h @@ -1795,23 +1795,23 @@ namespace ehs return result; } - /// A 32-bit FNV-1a hash algorithm. - /// @param [in] str The string to hash. - /// @returns The resulting hash. Zero if string does not contain any characters. - static UInt_32 Hash_32(const Str& str) - { + /// A 32-bit FNV-1a hash algorithm. + /// @param [in] str The string to hash. + /// @returns The resulting hash. Zero if string does not contain any characters. + static UInt_32 Hash_32(const Str& str) + { if (!str.Size()) 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) - hash = (hash ^ bytes[i]) * 16777619; + for (N i = 0; i < str.Size(true); ++i) + hash = (hash ^ bytes[i]) * 16777619; - return hash; - } + return hash; + } /// A 32-bit FNV-1a hash algorithm. /// @returns The resulting hash. Zero if string does not contain any characters. @@ -1830,23 +1830,23 @@ namespace ehs return hash; } - /// A 64-bit FNV-1a hash algorithm. - /// @param [in] str The string to hash. + /// A 64-bit FNV-1a hash algorithm. + /// @param [in] str The string to hash. /// @returns The resulting hash. Zero if string does not contain any characters. - static UInt_64 Hash_64(const Str& str) - { + static UInt_64 Hash_64(const Str& str) + { if (!str.Size()) 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) - hash = (hash ^ bytes[i]) * 1099511628211; + for (N i = 0; i < str.Size(true); ++i) + hash = (hash ^ bytes[i]) * 1099511628211; - return hash; - } + return hash; + } /// A 64-bit FNV-1a hash algorithm. /// @returns The resulting hash. Zero if string does not contain any characters. diff --git a/include/ehs/Types.h b/include/ehs/Types.h index 9ebc69b..62261ba 100644 --- a/include/ehs/Types.h +++ b/include/ehs/Types.h @@ -62,7 +62,9 @@ namespace ehs #if defined(EHS_64_BIT) typedef UInt_64 Size; + typedef SInt_64 SSize; #elif defined(EHS_32_BIT) typedef UInt_32 Size; + typedef SInt_32 SSize; #endif } \ No newline at end of file diff --git a/src/EHS.cpp b/src/EHS.cpp index dd78d3a..92342a9 100644 --- a/src/EHS.cpp +++ b/src/EHS.cpp @@ -2,7 +2,7 @@ #include "ehs/Log.h" #include "ehs/Version.h" #include "ehs/io/Console.h" -#include "ehs/GarbageCollector.h" +#include "ehs/GC.h" #include "ehs/io/audio/Audio.h" #include "ehs/io/img/Img.h" #include "ehs/io/img/PNG.h" @@ -141,13 +141,13 @@ int main() ehs::DecodeEHM }); - ehs::GarbageCollector::Start(); + ehs::GC::Start(); const ehs::SInt_32 code = Main(&ehs::appName, &ehs::appVerId, &ehs::appVer); if (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(); diff --git a/src/GC.cpp b/src/GC.cpp new file mode 100644 index 0000000..059200a --- /dev/null +++ b/src/GC.cpp @@ -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 GC::logic; + Vector 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(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; + } +} diff --git a/src/GarbageCollector.cpp b/src/GarbageCollector.cpp deleted file mode 100644 index 63bb753..0000000 --- a/src/GarbageCollector.cpp +++ /dev/null @@ -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 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)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(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; - } -} diff --git a/src/io/FontAtlas.cpp b/src/io/FontAtlas.cpp index 6ac63a2..a559f30 100644 --- a/src/io/FontAtlas.cpp +++ b/src/io/FontAtlas.cpp @@ -43,6 +43,7 @@ namespace ehs atlas = new Byte[resolution.x * resolution.y]; size = 0; fData.ReadArray(atlas, &size); + fData.ReadArray(atlas, &size); } FontAtlas::FontAtlas(FontAtlas&& fa) noexcept diff --git a/src/io/audio/AudioDevice_ALSA.cpp b/src/io/audio/AudioDevice_ALSA.cpp index 880b441..fcdadb8 100644 --- a/src/io/audio/AudioDevice_ALSA.cpp +++ b/src/io/audio/AudioDevice_ALSA.cpp @@ -1,6 +1,7 @@ #include "ehs/io/audio/AudioDevice_ALSA.h" #include "ehs/EHS.h" #include "ehs/Log.h" +#include "ehs/io/Console.h" namespace ehs { @@ -366,13 +367,21 @@ namespace ehs } 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 {}; } - snd_pcm_open(&result.hdl, "default", rType, SND_PCM_NONBLOCK); result.type = AudioDeviceType::OUTPUT; + EHS_LOG_SUCCESS(); + return result; } @@ -380,4 +389,4 @@ namespace ehs { return {}; } -} \ No newline at end of file +} diff --git a/src/io/model/Mdl.cpp b/src/io/model/Mdl.cpp index 7382d88..434fe0d 100644 --- a/src/io/model/Mdl.cpp +++ b/src/io/model/Mdl.cpp @@ -275,7 +275,6 @@ namespace ehs meshes[i].SetIndices(data.ReadArray()); - /* Bone& skeleton = mdl->GetSkeleton(); UInt_8 boneCount = data.Read(); for (UInt_8 b = 0; b < boneCount; ++b) @@ -329,7 +328,6 @@ namespace ehs } } } - */ } return true; diff --git a/src/io/model/Mesh.cpp b/src/io/model/Mesh.cpp index 629027c..50ae518 100644 --- a/src/io/model/Mesh.cpp +++ b/src/io/model/Mesh.cpp @@ -29,7 +29,7 @@ namespace ehs } 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) { }