| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <log4cxx/logstring.h> |
| #include <log4cxx/helpers/exception.h> |
| #include <log4cxx/helpers/mutex.h> |
| #include <log4cxx/helpers/pool.h> |
| #include <apr_thread_mutex.h> |
| #include <apr_thread_rwlock.h> |
| #include <assert.h> |
| #if !defined(LOG4CXX) |
| #define LOG4CXX 1 |
| #endif |
| #include <log4cxx/helpers/aprinitializer.h> |
| |
| #if defined(NON_BLOCKING) |
| |
| #if defined(WIN32) || defined(_WIN32) || defined(_WIN64) |
| #include <windows.h> |
| #else |
| // POSIX |
| #include <semaphore.h> |
| #endif |
| |
| #endif // NON_BLOCKING |
| |
| using namespace log4cxx::helpers; |
| using namespace log4cxx; |
| |
| |
| Mutex::Mutex(Pool& p) |
| { |
| #if APR_HAS_THREADS |
| apr_status_t stat = apr_thread_mutex_create(&mutex, |
| APR_THREAD_MUTEX_NESTED, p.getAPRPool()); |
| |
| if (stat != APR_SUCCESS) |
| { |
| throw MutexException(stat); |
| } |
| |
| #endif |
| } |
| |
| Mutex::Mutex(apr_pool_t* p) |
| { |
| #if APR_HAS_THREADS |
| apr_status_t stat = apr_thread_mutex_create(&mutex, |
| APR_THREAD_MUTEX_NESTED, p); |
| |
| if (stat != APR_SUCCESS) |
| { |
| throw MutexException(stat); |
| } |
| |
| #endif |
| } |
| |
| |
| Mutex::~Mutex() |
| { |
| #if APR_HAS_THREADS |
| |
| // LOGCXX-322 |
| if (APRInitializer::isDestructed) |
| { |
| return; |
| } |
| |
| apr_thread_mutex_destroy(mutex); |
| #endif |
| } |
| |
| apr_thread_mutex_t* Mutex::getAPRMutex() const |
| { |
| return mutex; |
| } |
| |
| #if defined(RW_MUTEX) |
| |
| RWMutex::RWMutex(Pool& p) |
| : id((apr_os_thread_t) -1) |
| , count(0) |
| { |
| #if APR_HAS_THREADS |
| apr_status_t stat = apr_thread_rwlock_create(&mutex, |
| p.getAPRPool()); |
| |
| if (stat != APR_SUCCESS) |
| { |
| throw MutexException(stat); |
| } |
| |
| #endif |
| } |
| |
| RWMutex::RWMutex(apr_pool_t* p) |
| : id((apr_os_thread_t) -1) |
| , count(0) |
| { |
| #if APR_HAS_THREADS |
| apr_status_t stat = apr_thread_rwlock_create(&mutex, p); |
| |
| if (stat != APR_SUCCESS) |
| { |
| throw MutexException(stat); |
| } |
| |
| #endif |
| } |
| |
| |
| RWMutex::~RWMutex() |
| { |
| #if APR_HAS_THREADS |
| apr_thread_rwlock_destroy(mutex); |
| #endif |
| } |
| |
| void RWMutex::rdLock() const |
| { |
| #if APR_HAS_THREADS |
| apr_status_t stat = apr_thread_rwlock_rdlock(mutex); |
| #endif |
| } |
| |
| void RWMutex::rdUnlock() const |
| { |
| #if APR_HAS_THREADS |
| apr_status_t stat = apr_thread_rwlock_unlock(mutex); |
| #endif |
| } |
| |
| void RWMutex::wrLock() const |
| { |
| #if APR_HAS_THREADS |
| apr_os_thread_t self = apr_os_thread_current(); |
| |
| if (id == self) |
| { |
| ++count; |
| } |
| else |
| { |
| apr_status_t stat = apr_thread_rwlock_wrlock(mutex); |
| id = self; |
| count = 1; |
| } |
| |
| #endif |
| } |
| |
| void RWMutex::wrUnlock() const |
| { |
| #if APR_HAS_THREADS |
| |
| if (--count == 0) |
| { |
| id = (apr_os_thread_t) -1; // id_ = "not a thread" |
| apr_status_t stat = apr_thread_rwlock_unlock(mutex); |
| } |
| else |
| { |
| } |
| |
| #endif |
| } |
| |
| #endif // RW_MUTEX |
| |
| #if defined(NON_BLOCKING) |
| |
| #if defined(WIN32) || defined(_WIN32) || defined(_WIN64) |
| |
| namespace log4cxx |
| { |
| namespace helpers |
| { |
| struct SemaphoreImpl |
| { |
| HANDLE semaphore; |
| }; |
| } |
| } |
| |
| static const LONG cMax = 10000; // arbitrary high value |
| |
| Semaphore::Semaphore(log4cxx::helpers::Pool& p) |
| : impl(nullptr) |
| { |
| #if APR_HAS_THREADS |
| impl = (SemaphoreImpl*)p.palloc(sizeof(SemaphoreImpl)); |
| |
| if (nullptr == impl) |
| { |
| throw MutexException(APR_ENOMEM); |
| } |
| |
| impl->semaphore = CreateSemaphore( |
| NULL, // default security attributes |
| 0, // initial count |
| cMax, // maximum count |
| NULL); // unnamed semaphore |
| |
| if (impl->semaphore == NULL) |
| { |
| throw MutexException(APR_ENOSHMAVAIL); |
| } |
| |
| #endif |
| } |
| |
| Semaphore::~Semaphore() |
| { |
| #if APR_HAS_THREADS |
| |
| if (impl && impl->semaphore) |
| { |
| CloseHandle(impl->semaphore); |
| } |
| |
| #endif |
| } |
| |
| void Semaphore::await() const |
| { |
| #if APR_HAS_THREADS |
| DWORD dwWaitResult = WaitForSingleObject(impl->semaphore, INFINITE); |
| |
| if (stat != 0) |
| { |
| throw MutexException(1); |
| } |
| |
| #endif |
| } |
| |
| void Semaphore::signalAll() const |
| { |
| #if APR_HAS_THREADS |
| BOOL stat = ReleaseSemaphore(impl->semaphore, 1, NULL); |
| |
| if (!stat) |
| { |
| throw MutexException(stat); |
| } |
| |
| #endif |
| } |
| |
| #else |
| // POSIX |
| |
| namespace log4cxx |
| { |
| namespace helpers |
| { |
| struct SemaphoreImpl |
| { |
| sem_t semaphore; |
| }; |
| } |
| } |
| |
| Semaphore::Semaphore(log4cxx::helpers::Pool& p) |
| : impl(nullptr) |
| { |
| #if APR_HAS_THREADS |
| impl = (SemaphoreImpl*)p.palloc(sizeof(SemaphoreImpl)); |
| |
| if (nullptr == impl) |
| { |
| throw MutexException(APR_ENOMEM); |
| } |
| |
| int stat = sem_init(&impl->semaphore, 0, 0); |
| |
| if (stat != 0) |
| { |
| throw MutexException(APR_ENOSHMAVAIL); |
| } |
| |
| #endif |
| } |
| |
| Semaphore::~Semaphore() |
| { |
| #if APR_HAS_THREADS |
| |
| if (impl) |
| { |
| int stat = sem_destroy(&impl->semaphore); |
| } |
| |
| #endif |
| } |
| |
| void Semaphore::await() const |
| { |
| #if APR_HAS_THREADS |
| int stat = sem_wait(&impl->semaphore); |
| |
| if (stat != 0) |
| { |
| throw MutexException(stat); |
| } |
| |
| #endif |
| } |
| |
| void Semaphore::signalAll() const |
| { |
| #if APR_HAS_THREADS |
| int stat = sem_post(&impl->semaphore); |
| |
| if (stat != 0) |
| { |
| throw MutexException(stat); |
| } |
| |
| #endif |
| } |
| |
| #endif // POSIX |
| |
| #endif // NON_BLOCKING |