diff --git a/Source/core/Portability.h b/Source/core/Portability.h index 395b252af..b5b44cb90 100644 --- a/Source/core/Portability.h +++ b/Source/core/Portability.h @@ -359,6 +359,20 @@ typedef std::string string; //const std::basic_string::size_type std::basic_string::npos = (std::basic_string::size_type) - 1; //#endif +// NTQuerySemaphore (undocumented) is used to retrieve current count of a semaphore +using NTSTATUS = LONG; +using _NTQuerySemaphore = NTSTATUS(NTAPI*)( + HANDLE SemaphoreHandle, + DWORD SemaphoreInformationClass, + PVOID SemaphoreInformation, + ULONG SemaphoreInformationLength, + PULONG ReturnLength OPTIONAL +); +struct SEMAPHORE_BASIC_INFORMATION { + ULONG CurrentCount; + ULONG MaximumCount; +}; + #define LITTLE_ENDIAN_PLATFORM 1 #undef ERROR #define __WINDOWS__ @@ -385,6 +399,7 @@ typedef std::string string; #include #include #include +#include #include #include @@ -412,9 +427,24 @@ typedef std::string string; #include #include #include // memfd_create in Messaging/ConsoleRedirect.h +#include #include +#ifndef _GNU_SOURCE + #define _GNU_SOURCE + #include + #ifndef __USE_GNU + #define __MUSL__ + #endif + #undef _GNU_SOURCE /* don't contaminate other includes unnecessarily */ +#else + #include + #ifndef __USE_GNU + #define __MUSL__ + #endif +#endif + #ifdef __APPLE__ #include #define SCHED_BATCH 99 diff --git a/Source/core/Proxy.h b/Source/core/Proxy.h index d51cce599..0b2830fe5 100644 --- a/Source/core/Proxy.h +++ b/Source/core/Proxy.h @@ -539,11 +539,11 @@ POP_WARNING() { return (!operator==(a_RHS)); } - inline bool operator==(const nullptr_t&) const + inline bool operator==(const std::nullptr_t&) const { return (_refCount == nullptr); } - inline bool operator!=(const nullptr_t&) const + inline bool operator!=(const std::nullptr_t&) const { return (_refCount != nullptr); } diff --git a/Source/core/SharedBuffer.cpp b/Source/core/SharedBuffer.cpp index c26704943..572b1f7d9 100644 --- a/Source/core/SharedBuffer.cpp +++ b/Source/core/SharedBuffer.cpp @@ -26,148 +26,38 @@ namespace Thunder { namespace Core { -#ifdef __WINDOWS__ - SharedBuffer::Semaphore::Semaphore(const TCHAR sourceName[]) - : _semaphore(::CreateSemaphore(nullptr, 1, 1, sourceName)) - { - } -#else - SharedBuffer::Semaphore::Semaphore(sem_t* storage) - : _semaphore(storage) - { - ASSERT(storage != nullptr); - } -#endif - SharedBuffer::Semaphore::~Semaphore() - { -#ifdef __WINDOWS__ - if (_semaphore != nullptr) { - ::CloseHandle(_semaphore); - } -#else - sem_destroy(_semaphore); -#endif - } - - uint32_t SharedBuffer::Semaphore::Unlock() - { -#ifdef __WINDOWS__ - if (_semaphore != nullptr) { - BOOL result = ::ReleaseSemaphore(_semaphore, 1, nullptr); - - ASSERT(result != FALSE); - } -#else - VARIABLE_IS_NOT_USED int result = sem_post(_semaphore); - - ASSERT((result == 0) || (errno == EOVERFLOW)); -#endif - return ERROR_NONE; - } - - bool SharedBuffer::Semaphore::IsLocked() - { -#ifdef __WINDOWS__ - bool locked = (::WaitForSingleObjectEx(_semaphore, 0, FALSE) != WAIT_OBJECT_0); - - if (locked == false) { - ::ReleaseSemaphore(_semaphore, 1, nullptr); - } - - return (locked); -#else - int semValue = 0; - sem_getvalue(_semaphore, &semValue); - return (semValue == 0); -#endif - } - - uint32_t SharedBuffer::Semaphore::Lock(const uint32_t waitTime) - { - uint32_t result = Core::ERROR_GENERAL; -#ifdef __WINDOWS__ - if (_semaphore != nullptr) { - return (::WaitForSingleObjectEx(_semaphore, waitTime, FALSE) == WAIT_OBJECT_0 ? Core::ERROR_NONE : Core::ERROR_TIMEDOUT); - } -#elif defined(__APPLE__) - - uint32_t timeLeft = waitTime; - int semResult; - while (((semResult = sem_trywait(_semaphore)) != 0) && timeLeft > 0) { - ::SleepMs(100); - if (timeLeft != Core::infinite) { - timeLeft -= (timeLeft > 100 ? 100 : timeLeft); - } - } - result = semResult == 0 ? Core::ERROR_NONE : Core::ERROR_TIMEDOUT; -#else - - struct timespec structTime = {0,0}; - - clock_gettime(CLOCK_MONOTONIC, &structTime); - structTime.tv_nsec += ((waitTime % 1000) * 1000 * 1000); /* remainder, milliseconds to nanoseconds */ - structTime.tv_sec += (waitTime / 1000) + (structTime.tv_nsec / 1000000000); /* milliseconds to seconds */ - structTime.tv_nsec = structTime.tv_nsec % 1000000000; - - do { - if (sem_clockwait(_semaphore, CLOCK_MONOTONIC, &structTime) == 0) { - result = Core::ERROR_NONE; - } - else if ( errno == EINTR ) { - continue; - } - else if ( errno == ETIMEDOUT ) { - result = Core::ERROR_TIMEDOUT; - } - else { - ASSERT(false); - } - break; - } while (true); -#endif - return (result); - } - SharedBuffer::SharedBuffer(const TCHAR name[]) : DataElementFile(name, File::USER_READ | File::USER_WRITE | File::SHAREABLE, 0) , _administrationBuffer((string(name) + ".admin"), File::USER_READ | File::USER_WRITE | File::SHAREABLE, 0) , _administration(reinterpret_cast(PointerAlign(_administrationBuffer.Buffer()))) -#ifdef __WINDOWS__ + #ifdef __WINDOWS__ , _producer((string(name) + ".producer").c_str()) , _consumer((string(name) + ".consumer").c_str()) -#else - , _producer(&(_administration->_producer)) - , _consumer(&(_administration->_consumer)) -#endif - , _customerAdministration(PointerAlign(&(reinterpret_cast(_administration)[sizeof(Administration)]))) + #else + , _producer(reinterpret_cast(_administration) + sizeof(Administration)) + , _consumer(reinterpret_cast(_administration) + sizeof(Administration) + SharedSemaphore::Size()) + #endif + , _customerAdministration(PointerAlign(&(reinterpret_cast(_administration)[sizeof(Administration) + (SharedSemaphore::Size() * 2)]))) { Align(); } SharedBuffer::SharedBuffer(const TCHAR name[], const uint32_t mode, const uint32_t bufferSize, const uint16_t administratorSize) : DataElementFile(name, mode | File::SHAREABLE | File::CREATE, bufferSize) - , _administrationBuffer((string(name) + ".admin"), mode | File::SHAREABLE | File::CREATE, administratorSize + sizeof(Administration) + (2 * sizeof(void*)) + 8 /* Align buffer on 64 bits boundary */) + , _administrationBuffer((string(name) + ".admin"), mode | File::SHAREABLE | File::CREATE, sizeof(Administration) + (SharedSemaphore::Size() * 2) + administratorSize + + (sizeof(void*) * 2) + ((sizeof(Administration) + (SharedSemaphore::Size() * 2) + administratorSize) % sizeof(void*) == 0 ? + 0 : (sizeof(void*) - ((sizeof(Administration) + (SharedSemaphore::Size() * 2) + administratorSize) % sizeof(void*)))) /* Align buffer on 32/64 bits boundary */) , _administration(reinterpret_cast(PointerAlign(_administrationBuffer.Buffer()))) -#ifdef __WINDOWS__ - , _producer((string(name) + ".producer").c_str()) - , _consumer((string(name) + ".consumer").c_str()) -#else - , _producer(&(_administration->_producer)) - , _consumer(&(_administration->_consumer)) -#endif - , _customerAdministration(PointerAlign(&(reinterpret_cast(_administration)[sizeof(Administration)]))) - { - -#ifndef __WINDOWS__ - memset(_administration, 0, sizeof(Administration)); - - sem_init(&(_administration->_producer), 1, 1); /* Initial value is 1. */ - sem_init(&(_administration->_consumer), 1, 0); /* Initial value is 0. */ -#endif + #ifdef __WINDOWS__ + , _producer((string(name) + ".producer").c_str(), 1, 1) + , _consumer((string(name) + ".consumer").c_str(), 0, 1) + #else + , _producer(reinterpret_cast(_administration) + sizeof(Administration), 1, 1) + , _consumer(reinterpret_cast(_administration) + sizeof(Administration) + SharedSemaphore::Size(), 0, 1) +# endif + , _customerAdministration(PointerAlign(&(reinterpret_cast(_administration)[sizeof(Administration) + (SharedSemaphore::Size() * 2)]))) + { + _administration->_bytesWritten = 0; Align(); } - - SharedBuffer::~SharedBuffer() - { - } -} } +} \ No newline at end of file diff --git a/Source/core/SharedBuffer.h b/Source/core/SharedBuffer.h index 664e34d98..77035525d 100644 --- a/Source/core/SharedBuffer.h +++ b/Source/core/SharedBuffer.h @@ -65,46 +65,12 @@ namespace Core { SharedBuffer& operator=(const SharedBuffer&) = delete; private: - class Semaphore { - private: - Semaphore() = delete; - Semaphore(const Semaphore&) = delete; - Semaphore& operator=(const Semaphore&) = delete; - - public: -#ifdef __WINDOWS__ - Semaphore(const TCHAR name[]); -#else - Semaphore(sem_t* storage); - //Semaphore(sem_t* storage, bool initialize) { - //} -#endif - ~Semaphore(); - - public: - uint32_t Lock(const uint32_t waitTime); - uint32_t Unlock(); - bool IsLocked(); - - private: -#ifdef __WINDOWS__ - HANDLE _semaphore; -#else - sem_t* _semaphore; -#endif - }; struct Administration { - uint32_t _bytesWritten; - -#ifndef __WINDOWS__ - sem_t _producer; - sem_t _consumer; -#endif }; public: - virtual ~SharedBuffer(); + ~SharedBuffer() override = default; // This is the consumer constructor. It should always take place, after, the producer // construct. The producer will create the Administration area, and the shared buffer, @@ -215,8 +181,8 @@ namespace Core { private: DataElementFile _administrationBuffer; Administration* _administration; - Semaphore _producer; - Semaphore _consumer; + Core::SharedSemaphore _producer; + Core::SharedSemaphore _consumer; uint8_t* _customerAdministration; }; } diff --git a/Source/core/Sync.cpp b/Source/core/Sync.cpp index e5f04ef3a..545161e0d 100644 --- a/Source/core/Sync.cpp +++ b/Source/core/Sync.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #endif #ifdef __APPLE__ #include @@ -271,7 +272,7 @@ namespace Core { //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- - // BinairySemaphore class + // BinarySemaphore class //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- @@ -283,12 +284,12 @@ namespace Core { // sets the inital count an the maximum count. This way, on platform changes, // only the declaration/definition of the synchronisation object has to be defined // as being Binairy, not the coding. - BinairySemaphore::BinairySemaphore(unsigned int nInitialCount, unsigned int nMaxCount) + BinarySemaphore::BinarySemaphore(unsigned int nInitialCount, unsigned int nMaxCount) { DEBUG_VARIABLE(nMaxCount); ASSERT((nInitialCount == 0) || (nInitialCount == 1)); - TRACE_L5("Constructor BinairySemaphore (int, int) <%p>", (this)); + TRACE_L5("Constructor BinarySemaphore (int, int) <%p>", (this)); #ifdef __POSIX__ m_blLocked = (nInitialCount == 0); @@ -323,12 +324,12 @@ namespace Core { #endif } - BinairySemaphore::BinairySemaphore(bool blLocked) + BinarySemaphore::BinarySemaphore(bool blLocked) #ifdef __POSIX__ : m_blLocked(blLocked) #endif { - TRACE_L5("Constructor BinairySemaphore <%p>", (this)); + TRACE_L5("Constructor BinarySemaphore <%p>", (this)); #ifdef __POSIX__ pthread_condattr_t attr; @@ -360,9 +361,9 @@ namespace Core { #endif } - BinairySemaphore::~BinairySemaphore() + BinarySemaphore::~BinarySemaphore() { - TRACE_L5("Destructor BinairySemaphore <%p>", (this)); + TRACE_L5("Destructor BinarySemaphore <%p>", (this)); #ifdef __POSIX__ // If we really create it, we really have to destroy it. @@ -380,7 +381,7 @@ namespace Core { //---------------------------------------------------------------------------- uint32_t - BinairySemaphore::Lock() + BinarySemaphore::Lock() { #ifdef __WINDOWS__ @@ -423,7 +424,7 @@ namespace Core { } uint32_t - BinairySemaphore::Lock(unsigned int nTime) + BinarySemaphore::Lock(unsigned int nTime) { #ifdef __WINDOWS__ return (::WaitForSingleObjectEx(m_syncMutex, nTime, FALSE) == WAIT_OBJECT_0 ? Core::ERROR_NONE : Core::ERROR_TIMEDOUT); @@ -482,8 +483,8 @@ namespace Core { #endif } - void - BinairySemaphore::Unlock() + uint32_t + BinarySemaphore::Unlock() { #ifdef __POSIX__ @@ -505,6 +506,7 @@ namespace Core { #ifdef __WINDOWS__ ::ReleaseMutex(m_syncMutex); #endif + return ERROR_NONE; } //---------------------------------------------------------------------------- @@ -782,6 +784,241 @@ namespace Core { return (nResult); } + //---------------------------------------------------------------------------- + //---------------------------------------------------------------------------- + // SharedSemaphore class + //---------------------------------------------------------------------------- + //---------------------------------------------------------------------------- + + //---------------------------------------------------------------------------- + // CONSTRUCTOR & DESTRUCTOR + //---------------------------------------------------------------------------- + +#ifdef __WINDOWS__ + class WindowsAPI { + public: + WindowsAPI(WindowsAPI&&) = delete; + WindowsAPI(const WindowsAPI&) = delete; + WindowsAPI& operator=(WindowsAPI&&) = delete; + WindowsAPI& operator=(const WindowsAPI&) = delete; + + ~WindowsAPI() = default; + WindowsAPI() { + _ntQuerySemaphore = reinterpret_cast<_NTQuerySemaphore>(GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtQuerySemaphore")); + ASSERT (_ntQuerySemaphore != nullptr); + } + + uint32_t GetSemaphoreCount(HANDLE parameter) const { + SEMAPHORE_BASIC_INFORMATION basicInfo; + NTSTATUS status; + status = _ntQuerySemaphore(parameter, 0, &basicInfo, sizeof(SEMAPHORE_BASIC_INFORMATION), nullptr); + return (status == ERROR_SUCCESS) ? basicInfo.CurrentCount : 0; + } + private: + _NTQuerySemaphore _ntQuerySemaphore; + }; + + static WindowsAPI _windowsAPI; +#endif + + SharedSemaphore::SharedSemaphore(const TCHAR sourceName[], const uint32_t initCount, VARIABLE_IS_NOT_USED const uint32_t maxCount) + { + ASSERT(initCount <= 1); + ASSERT(maxCount == 1); +#ifdef __WINDOWS__ + _semaphore = (::CreateSemaphore(nullptr, initCount, maxCount, sourceName)); + ASSERT(_semaphore != nullptr); +#else + _name = "/" + string(sourceName); + _semaphore = sem_open(_name.c_str(), O_CREAT | O_RDWR | O_EXCL, 0644, initCount); + ASSERT(_semaphore != SEM_FAILED); +#endif + } + + SharedSemaphore::SharedSemaphore(const TCHAR sourceName[]) + { +#ifdef __WINDOWS__ + _semaphore = ::OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, sourceName); + ASSERT(_semaphore != nullptr); +#else + _semaphore = sem_open(sourceName, 0); + ASSERT(_semaphore != nullptr); +#endif + } + +#ifndef __WINDOWS__ + SharedSemaphore::SharedSemaphore(void* storage, const uint32_t initCount, VARIABLE_IS_NOT_USED const uint32_t maxCount) + : _semaphore(storage), _name("") + { + ASSERT(storage != nullptr); + ASSERT(initCount <= 1); + ASSERT(maxCount == 1); + memset(_semaphore, 0, sizeof(sem_t)); + VARIABLE_IS_NOT_USED int result = sem_init(static_cast(_semaphore), 1, initCount); + ASSERT(result != -1); + } + + SharedSemaphore::SharedSemaphore(void* storage) + : _semaphore(storage), _name("") + { + ASSERT(storage != nullptr); + } + +#endif + + SharedSemaphore::~SharedSemaphore() + { +#ifdef __WINDOWS__ + if (_semaphore != nullptr) { + ::CloseHandle(_semaphore); + } +#else + if(_name.size() != 0) { + sem_close(static_cast(_semaphore)); + sem_unlink(_name.c_str()); + } + else { + sem_destroy(static_cast(_semaphore)); + } +#endif + } + + size_t SharedSemaphore::Size() + { +#ifdef __WINDOWS__ + return sizeof(HANDLE); +#else + return sizeof(sem_t); +#endif + } + + uint32_t SharedSemaphore::MaxCount() const + { + // Currently max count is 1, as it is implemented as a binary shared semaphore + return 1; + } + + //---------------------------------------------------------------------------- + // PUBLIC METHODS + //---------------------------------------------------------------------------- + + uint32_t + SharedSemaphore::Unlock() + { +#ifdef __WINDOWS__ + if (_semaphore != nullptr) { + BOOL result = ::ReleaseSemaphore(_semaphore, 1, nullptr); + ASSERT(result != FALSE); + } +#else + VARIABLE_IS_NOT_USED int result = sem_post(static_cast(_semaphore)); + ASSERT((result == 0) || (errno == EOVERFLOW)); +#endif + return ERROR_NONE; + } + + uint32_t + SharedSemaphore::Count() const + { +#ifdef __WINDOWS__ + return (_windowsAPI.GetSemaphoreCount(_semaphore)); +#else + int semValue = 0; + sem_getvalue(static_cast(_semaphore), &semValue); + return semValue; +#endif + } + + uint32_t + SharedSemaphore::Lock(const uint32_t waitTime) + { + uint32_t result = Core::ERROR_GENERAL; +#ifdef __WINDOWS__ + if (_semaphore != nullptr) { + return (::WaitForSingleObjectEx(_semaphore, waitTime, FALSE) == WAIT_OBJECT_0 ? Core::ERROR_NONE : Core::ERROR_TIMEDOUT); + } +#elif defined(__APPLE__) + + uint32_t timeLeft = waitTime; + int semResult; + while (((semResult = sem_trywait(static_cast(_semaphore))) != 0) && timeLeft > 0) { + ::SleepMs(100); + if (timeLeft != Core::infinite) { + timeLeft -= (timeLeft > 100 ? 100 : timeLeft); + } + } + result = semResult == 0 ? Core::ERROR_NONE : Core::ERROR_TIMEDOUT; + +#elif defined(__MUSL__) + struct timespec referenceTime = {0,0}; + clock_gettime(CLOCK_MONOTONIC, &referenceTime); + referenceTime.tv_nsec += ((waitTime % 1000) * 1000 * 1000); /* remainder, milliseconds to nanoseconds */ + referenceTime.tv_sec += (waitTime / 1000) + (referenceTime.tv_nsec / 1000000000); /* milliseconds to seconds */ + referenceTime.tv_nsec = referenceTime.tv_nsec % 1000000000; + do { + + struct timespec structTime = {0,0}; + clock_gettime(CLOCK_REALTIME, &structTime); + structTime.tv_nsec += ((waitTime % 1000) * 1000 * 1000); /* remainder, milliseconds to nanoseconds */ + structTime.tv_sec += (waitTime / 1000) + (structTime.tv_nsec / 1000000000); /* milliseconds to seconds */ + structTime.tv_nsec = structTime.tv_nsec % 1000000000; + + if (sem_timedwait(static_cast(_semaphore), &structTime) == 0) { + result = Core::ERROR_NONE; + } + else if ( errno == EINTR ) { + continue; + } + else if ( errno == ETIMEDOUT ) { + struct timespec currentMonoTime; + clock_gettime(CLOCK_MONOTONIC, ¤tMonoTime); + + struct timespec jumpTime; + jumpTime.tv_sec = currentMonoTime.tv_sec - referenceTime.tv_sec; + + if(jumpTime.tv_sec != 0) { + result = Core::ERROR_TIMEDOUT; + break; + } + + if(referenceTime.tv_sec < currentMonoTime.tv_sec || (referenceTime.tv_sec == currentMonoTime.tv_sec && + referenceTime.tv_nsec < currentMonoTime.tv_nsec)) + { + result = Core::ERROR_TIMEDOUT; + break; + } + } + else { + ASSERT(false); + } + break; + } while (true); +#else + struct timespec structTime = {0,0}; + clock_gettime(CLOCK_MONOTONIC, &structTime); + structTime.tv_nsec += ((waitTime % 1000) * 1000 * 1000); /* remainder, milliseconds to nanoseconds */ + structTime.tv_sec += (waitTime / 1000) + (structTime.tv_nsec / 1000000000); /* milliseconds to seconds */ + structTime.tv_nsec = structTime.tv_nsec % 1000000000; + + do { + if (sem_clockwait(static_cast(_semaphore), CLOCK_MONOTONIC, &structTime) == 0) { + result = Core::ERROR_NONE; + } + else if ( errno == EINTR ) { + continue; + } + else if ( errno == ETIMEDOUT ) { + result = Core::ERROR_TIMEDOUT; + } + else { + ASSERT(false); + } + break; + } while (true); +#endif + return (result); + } + //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Event class (AVAILABLE WITHIN PROCESS SPACE) diff --git a/Source/core/Sync.h b/Source/core/Sync.h index 63540c773..fbe30a663 100644 --- a/Source/core/Sync.h +++ b/Source/core/Sync.h @@ -29,7 +29,6 @@ #ifdef __LINUX__ #include -#include #endif namespace Thunder { @@ -112,23 +111,22 @@ namespace Core { // =========================================================================== // class BinairySemaphore // =========================================================================== - - class EXTERNAL BinairySemaphore { + class EXTERNAL BinarySemaphore { private: - BinairySemaphore() = delete; - BinairySemaphore(const BinairySemaphore&) = delete; - BinairySemaphore& operator=(const BinairySemaphore&) = delete; + BinarySemaphore() = delete; + BinarySemaphore(const BinarySemaphore&) = delete; + BinarySemaphore& operator=(const BinarySemaphore&) = delete; public: // Methods - BinairySemaphore(unsigned int nInitialCount, unsigned int nMaxCount); - BinairySemaphore(bool blLocked); - ~BinairySemaphore(); + BinarySemaphore(unsigned int nInitialCount, unsigned int nMaxCount); + BinarySemaphore(bool blLocked); + ~BinarySemaphore(); uint32_t Lock(); // Time in milliseconds! uint32_t Lock(unsigned int nSeconds); - void Unlock(); + uint32_t Unlock(); bool Locked() const; protected: // Members @@ -143,6 +141,9 @@ namespace Core { #endif }; + // For compatability reaons with old class name + using BinairySemaphore = BinarySemaphore; + // =========================================================================== // class CountingSemaphore // =========================================================================== @@ -181,6 +182,45 @@ namespace Core { // For Windows platform compatibility typedef CountingSemaphore Semaphore; + // =========================================================================== + // class SharedSemaphore + // =========================================================================== + + class EXTERNAL SharedSemaphore { + public: + SharedSemaphore() = delete; + SharedSemaphore(const Semaphore&) = delete; + SharedSemaphore& operator=(const SharedSemaphore&) = delete; + + SharedSemaphore(const TCHAR name[], const uint32_t initValue, const uint32_t maxValue); + SharedSemaphore(const TCHAR name[]); +#ifndef __WINDOWS__ + /* + If pshared is nonzero, then the semaphore is shared between + processes, and should be located in a region of shared memory + (see shm_open(3), mmap(2), and shmget(2)) + Storage should be at least sizeof(sem_t)! + */ + SharedSemaphore(void *storage, const uint32_t initValue, const uint32_t maxValue); + SharedSemaphore(void *storage); + public: +#endif + ~SharedSemaphore(); + public: + uint32_t Lock(const uint32_t waitTime); + uint32_t Unlock(); + uint32_t Count() const; + static size_t Size(); + uint32_t MaxCount() const; + private: +#ifdef __WINDOWS__ + HANDLE _semaphore; +#else + void* _semaphore; + string _name; +#endif + }; + // =========================================================================== // class Event // =========================================================================== diff --git a/Source/core/Thread.cpp b/Source/core/Thread.cpp index b635c20f4..b5251b310 100644 --- a/Source/core/Thread.cpp +++ b/Source/core/Thread.cpp @@ -469,7 +469,7 @@ POP_WARNING() } #ifdef __DEBUG__ - int Thread::GetCallstack(void** buffer, int size) + int Thread::GetCallstack(VARIABLE_IS_NOT_USED void** buffer, VARIABLE_IS_NOT_USED int size) { #if defined(THUNDER_BACKTRACE) return GetCallStack(m_hThreadInstance, buffer, size);