/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: LockGuard.hpp Date: 2021-6-10 Author: Reece ***/ #pragma once namespace Aurora::Threading { template class LockGuard { private: using Internal_t = AuRemovePointer_t; public: LockGuard(T &lock) { if constexpr (AuIsPointer_v) { annoying_ = lock; } else { annoying_ = &lock; } if constexpr (AuIsBaseOfTemplate::value || AuIsBaseOfTemplate::value) { annoying_->get()->Lock(); } else { annoying_->Lock(); } constructed_ = true; } LockGuard(T &&lock) { if constexpr (AuIsPointer_v) { annoying_ = lock; } else { annoying_ = &lock; } if constexpr (AuIsBaseOfTemplate::value || AuIsBaseOfTemplate::value) { annoying_->get()->Lock(); } else { annoying_->Lock(); } constructed_ = true; } ~LockGuard() { if (!constructed_) { return; } if constexpr (AuIsBaseOfTemplate::value || AuIsBaseOfTemplate::value) { annoying_->get()->Unlock(); } else { annoying_->Unlock(); } } private: AuConditional_t, T, T*> annoying_; bool constructed_ {}; }; #define AU_LOCK_GUARD(variable) Aurora::Threading::LockGuard AU_CONCAT(__stack_lock, __COUNTER__) (variable); }