/*** Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuLogClasses.cpp Date: 2023-3-22 Author: Reece ***/ #include #include "AuLogClasses.hpp" namespace Aurora::Logging { static const AuUInt8 kAvailableSlots = AuLog::kLogLevelMax - AuLog::kLogLevelUsr; static AuUInt32 gAtomicInUseCount {}; static AuUInt32 gInUseMap[kAvailableSlots / 8] {}; static AuString gStringMap[kAvailableSlots]; static AuUInt32 gIterator {}; static AuThreadPrimitives::MutexSOO gMutex; static const auto kBitsPerWord = 8 * sizeof(*gInUseMap); AUKN_SYM bool LogClassInUse(AuUInt8 uIndex); static bool TryAcquire(AuUInt8 uIdx) { if (AuAtomicSet(&gInUseMap[uIdx / kBitsPerWord], uIdx % kBitsPerWord)) { return false; } AuAtomicAdd(&gAtomicInUseCount, 1u); return true; } static void Release(AuUInt8 uIdx) { if (AuAtomicUnset(&gInUseMap[uIdx / kBitsPerWord], uIdx % kBitsPerWord)) { AuAtomicSub(&gAtomicInUseCount, 1u); AU_LOCK_GUARD(gMutex); if (!LogClassInUse(uIdx + AuLog::kLogLevelUsr)) { gStringMap[uIdx].clear(); } } } static void SetString(AuUInt8 uIdx, const AuString &str) { AU_LOCK_GUARD(gMutex); gStringMap[uIdx] = str; } static AuResult TryAcquire() { auto uFirstGuess = (AuAtomicAdd(&gIterator, 1u) - 1) % kAvailableSlots; if (!TryAcquire(uFirstGuess)) { for (AU_ITERATE_N(i, kAvailableSlots)) { auto uIndex = (i + uFirstGuess) % kAvailableSlots; if (TryAcquire(uIndex)) { gIterator = uIndex; return AuUInt8(uIndex); } } return {}; } else { return AuUInt8(uFirstGuess); } } AUKN_SYM void LogClassAssociateName(AuUInt8 uIndex, const AuString &str) { uIndex -= AuLog::kLogLevelUsr; if (uIndex >= kAvailableSlots) { return; } SetString(uIndex, str); } AUKN_SYM const AuString &LogClassGetNameUnsafe(AuUInt8 uIndex) { uIndex -= AuLog::kLogLevelUsr; SysAssertDbg(uIndex < kAvailableSlots); return gStringMap[uIndex]; } AUKN_SYM AuString LogClassGetNameSafe(AuUInt8 uIndex) { AU_LOCK_GUARD(gMutex); uIndex -= AuLog::kLogLevelUsr; if (uIndex >= kAvailableSlots) { return {}; } return gStringMap[uIndex]; } AUKN_SYM void LogClassRelease(AuUInt8 uIndex) { uIndex -= AuLog::kLogLevelUsr; if (uIndex >= kAvailableSlots) { return; } Release(uIndex); } AUKN_SYM AuResult LogClassGetNext() { auto uRes = TryAcquire(); if (uRes) { return AuUInt8(uRes.value() + AuLog::kLogLevelUsr); } return {}; } AUKN_SYM bool LogClassInUse(AuUInt8 uIndex) { uIndex -= AuLog::kLogLevelUsr; if (uIndex >= kAvailableSlots) { return false; } return AuTestBit(gInUseMap[uIndex / kBitsPerWord], uIndex % kBitsPerWord); } AUKN_SYM AuUInt8 LogClassTotalAvailable() { return kAvailableSlots; } AUKN_SYM AuUInt8 LogClassTotalInUse() { return gAtomicInUseCount; } }