// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. #pragma once #if PLATFORM_UNIX #include "Engine/Platform/Platform.h" #include class UnixConditionVariable; /// /// Unix implementation of a critical section. /// class FLAXENGINE_API UnixCriticalSection { friend UnixConditionVariable; private: pthread_mutex_t _mutex; pthread_mutex_t* _mutexPtr; #if BUILD_DEBUG pthread_t _owningThreadId; #endif UnixCriticalSection(const UnixCriticalSection&); UnixCriticalSection& operator=(const UnixCriticalSection&); public: /// /// Initializes a new instance of the class. /// UnixCriticalSection() { pthread_mutexattr_t attributes; pthread_mutexattr_init(&attributes); pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&_mutex, &attributes); pthread_mutexattr_destroy(&attributes); _mutexPtr = &_mutex; #if BUILD_DEBUG _owningThreadId = 0; #endif } /// /// Finalizes an instance of the class. /// ~UnixCriticalSection() { pthread_mutex_destroy(&_mutex); } public: /// /// Locks the critical section. /// NO_SANITIZE_THREAD void Lock() const { pthread_mutex_lock(_mutexPtr); #if BUILD_DEBUG ((UnixCriticalSection*)this)->_owningThreadId = pthread_self(); #endif } /// /// Attempts to enter a critical section without blocking. If the call is successful, the calling thread takes ownership of the critical section. /// /// True if calling thread took ownership of the critical section. NO_SANITIZE_THREAD bool TryLock() const { return pthread_mutex_trylock(_mutexPtr) == 0; } /// /// Releases the lock on the critical section. /// NO_SANITIZE_THREAD void Unlock() const { #if BUILD_DEBUG ((UnixCriticalSection*)this)->_owningThreadId = 0; #endif pthread_mutex_unlock(_mutexPtr); } }; #endif