From b30e8a251e086a0fad1afbbe89566bc1f68c573d Mon Sep 17 00:00:00 2001 From: bernhard-gatzhammer Date: Tue, 3 Nov 2015 16:35:11 +0100 Subject: [PATCH] Revert "Readers-writers lock: updated interface to match C++14 standard" This reverts commit ae2f181397c309d5f4a58eccc6be86ee5d74eae6. --- base_c/include/embb/base/c/base.h | 2 +- base_c/include/embb/base/c/internal/platform.h | 4 ++-- base_c/include/embb/base/c/rwlock.h | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ base_c/include/embb/base/c/shared_mutex.h | 196 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- base_c/src/rwlock.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ base_c/src/shared_mutex.c | 148 ---------------------------------------------------------------------------------------------------------------------------------------------------- base_c/test/main.cc | 6 +++--- base_c/test/rwlock_test.cc | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ base_c/test/rwlock_test.h | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ base_c/test/shared_mutex_test.cc | 110 -------------------------------------------------------------------------------------------------------------- base_c/test/shared_mutex_test.h | 63 --------------------------------------------------------------- base_cpp/include/embb/base/base.h | 2 +- base_cpp/include/embb/base/internal/platform.h | 4 ++-- base_cpp/include/embb/base/internal/shared_mutex-inl.h | 116 -------------------------------------------------------------------------------------------------------------------- base_cpp/include/embb/base/rwlock.h | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ base_cpp/include/embb/base/shared_mutex.h | 304 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- base_cpp/src/rwlock.cc | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ base_cpp/src/shared_mutex.cc | 73 ------------------------------------------------------------------------- base_cpp/test/main.cc | 6 +++--- base_cpp/test/rwlock_test.cc | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ base_cpp/test/rwlock_test.h | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ base_cpp/test/shared_mutex_test.cc | 158 -------------------------------------------------------------------------------------------------------------------------------------------------------------- base_cpp/test/shared_mutex_test.h | 63 --------------------------------------------------------------- 23 files changed, 986 insertions(+), 1243 deletions(-) create mode 100644 base_c/include/embb/base/c/rwlock.h delete mode 100644 base_c/include/embb/base/c/shared_mutex.h create mode 100644 base_c/src/rwlock.c delete mode 100644 base_c/src/shared_mutex.c create mode 100644 base_c/test/rwlock_test.cc create mode 100644 base_c/test/rwlock_test.h delete mode 100644 base_c/test/shared_mutex_test.cc delete mode 100644 base_c/test/shared_mutex_test.h delete mode 100644 base_cpp/include/embb/base/internal/shared_mutex-inl.h create mode 100644 base_cpp/include/embb/base/rwlock.h delete mode 100644 base_cpp/include/embb/base/shared_mutex.h create mode 100644 base_cpp/src/rwlock.cc delete mode 100644 base_cpp/src/shared_mutex.cc create mode 100644 base_cpp/test/rwlock_test.cc create mode 100644 base_cpp/test/rwlock_test.h delete mode 100644 base_cpp/test/shared_mutex_test.cc delete mode 100644 base_cpp/test/shared_mutex_test.h diff --git a/base_c/include/embb/base/c/base.h b/base_c/include/embb/base/c/base.h index 0f697de..d16e355 100644 --- a/base_c/include/embb/base/c/base.h +++ b/base_c/include/embb/base/c/base.h @@ -55,6 +55,6 @@ #include #include #include -#include +#include #endif /* EMBB_BASE_C_BASE_H_ */ diff --git a/base_c/include/embb/base/c/internal/platform.h b/base_c/include/embb/base/c/internal/platform.h index 2da445b..358b435 100644 --- a/base_c/include/embb/base/c/internal/platform.h +++ b/base_c/include/embb/base/c/internal/platform.h @@ -66,7 +66,7 @@ typedef struct embb_thread_t { typedef DWORD embb_thread_id_t; typedef CRITICAL_SECTION embb_mutex_t; typedef CONDITION_VARIABLE embb_condition_t; -typedef SRWLOCK embb_shared_mutex_t; +typedef SRWLOCK embb_rwlock_t; #define EMBB_DURATION_MIN_NANOSECONDS 1000 @@ -91,7 +91,7 @@ typedef struct embb_thread_t { typedef pthread_t embb_thread_id_t; typedef pthread_mutex_t embb_mutex_t; typedef pthread_cond_t embb_condition_t; -typedef pthread_rwlock_t embb_shared_mutex_t; +typedef pthread_rwlock_t embb_rwlock_t; #define EMBB_DURATION_MIN_NANOSECONDS 1 diff --git a/base_c/include/embb/base/c/rwlock.h b/base_c/include/embb/base/c/rwlock.h new file mode 100644 index 0000000..ef62d5b --- /dev/null +++ b/base_c/include/embb/base/c/rwlock.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2014-2015, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef EMBB_BASE_C_RWLOCK_H_ +#define EMBB_BASE_C_RWLOCK_H_ + +/** + * \defgroup C_BASE_RWLOCK Readers-Writers Lock + * + * Shared-read/exclusive-write lock for thread synchronization + * + * Provides an abstraction from platform-specific readers-writers lock + * implementations. + * + * \ingroup C_BASE + * \{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#ifdef DOXYGEN +/** + * Opaque type representing an rwlock. + */ +typedef opaque_type embb_rwlock_t; +#endif // DOXYGEN + +/** + * Initializes an rwlock + * + * \post \c rwlock is initialized + * + * \param rwlock Pointer to rwlock + * \return EMBB_SUCCESS if rwlock could be initialized \n + * EMBB_ERROR otherwise + * + * \memory (Potentially) allocates dynamic memory + * + * \notthreadsafe + * + * \see embb_rwlock_destroy() + */ +int embb_rwlock_init(embb_rwlock_t* rwlock); + +/** + * Waits until the rwlock can be locked for reading and locks it. + * + * \pre \c rwlock is initialized and not locked by the current thread. + * \post If successful, \c rwlock is locked for reading. + * + * \param rwlock Pointer to rwlock + * \return EMBB_SUCCESS if rwlock could be locked for reading \n + * EMBB_ERROR otherwise + * + * \threadsafe + * + * \see embb_rwlock_try_lock_read(), embb_rwlock_unlock_read() + */ +int embb_rwlock_lock_read(embb_rwlock_t* rwlock); + +/** + * Waits until the rwlock can be locked for writing and locks it. + * + * \pre \c rwlock is initialized and not locked by the current thread. + * \post If successful, \c rwlock is locked for writing. + * + * \param rwlock Pointer to rwlock + * \return EMBB_SUCCESS if rwlock could be locked for writing \n + * EMBB_ERROR otherwise + * + * \threadsafe + * + * \see embb_rwlock_try_lock_write(), embb_rwlock_unlock_write() + */ +int embb_rwlock_lock_write(embb_rwlock_t* rwlock); + +/** + * Tries to lock the rwlock for reading and returns immediately. + * + * \pre \c rwlock is initialized + * \post If successful, \c rwlock is locked for reading + * + * \param rwlock Pointer to rwlock + * \return EMBB_SUCCESS if rwlock could be locked for reading \n + * EMBB_BUSY if rwlock could not be locked for reading \n + * EMBB_ERROR if an error occurred + * + * \threadsafe + * + * \see embb_rwlock_lock_read(), embb_rwlock_unlock_read() + */ +int embb_rwlock_try_lock_read(embb_rwlock_t* rwlock); + +/** + * Tries to lock the rwlock for writing and returns immediately. + * + * \pre \c rwlock is initialized + * \post If successful, \c rwlock is locked for writing + * + * \param rwlock Pointer to rwlock + * \return EMBB_SUCCESS if rwlock could be locked for writing \n + * EMBB_BUSY if rwlock could not be locked for writing \n + * EMBB_ERROR if an error occurred + * + * \threadsafe + * + * \see embb_rwlock_lock_write(), embb_rwlock_unlock_write() + */ +int embb_rwlock_try_lock_write(embb_rwlock_t* rwlock); + +/** + * Unlocks an rwlock locked for reading. + * + * \pre \c rwlock has been locked for reading by the current thread. + * \post If successful, \c rwlock is unlocked. + * + * \param rwlock Pointer to rwlock + * \return EMBB_SUCCESS if the operation was successful \n + * EMBB_ERROR otherwise + * + * \threadsafe + * + * \see embb_rwlock_lock_read(), embb_rwlock_try_lock_read() + */ +int embb_rwlock_unlock_read(embb_rwlock_t* rwlock); + +/** + * Unlocks an rwlock locked for writing. + * + * \pre \c rwlock has been locked for writing by the current thread. + * \post If successful, \c rwlock is unlocked. + * + * \param rwlock Pointer to rwlock + * \return EMBB_SUCCESS if the operation was successful \n + * EMBB_ERROR otherwise + * + * \threadsafe + * + * \see embb_rwlock_lock_write(), embb_rwlock_try_lock_write() + */ +int embb_rwlock_unlock_write(embb_rwlock_t* rwlock); + +/** + * Destroys an rwlock and frees its resources. + * + * \pre \c rwlock has been initialized + * \post \c rwlock is uninitialized + * + * \param rwlock Pointer to rwlock + * + * \notthreadsafe + * + * \see embb_rwlock_init() + */ +void embb_rwlock_destroy(embb_rwlock_t* rwlock); + +#ifdef __cplusplus +} // Close extern "C" +#endif + +/** + * \} + */ + +#endif // EMBB_BASE_C_RWLOCK_H_ diff --git a/base_c/include/embb/base/c/shared_mutex.h b/base_c/include/embb/base/c/shared_mutex.h deleted file mode 100644 index 5855dfc..0000000 --- a/base_c/include/embb/base/c/shared_mutex.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 2014-2015, Siemens AG. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef EMBB_BASE_C_SHARED_MUTEX_H_ -#define EMBB_BASE_C_SHARED_MUTEX_H_ - -/** - * \defgroup C_BASE_SHARED_MUTEX Shared mutex - * - * Shared mutexes for thread synchronization - * - * Provides an abstraction from platform-specific shared mutex implementations. - * Shared mutexes provide two levels of access: exclusive access - only one - * thread can own the mutex; shared access - several threads can share ownership - * of the same mutex. Shared mutexes facilitate the "single writer, multiple - * readers" scenarios. - * - * \ingroup C_BASE - * \{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#ifdef DOXYGEN -/** - * Opaque type representing a shared mutex. - */ -typedef opaque_type embb_shared_mutex_t; -#endif // DOXYGEN - -/** - * Initializes a shared mutex - * - * \post \c shared_mutex is initialized - * - * \param shared_mutex Pointer to shared mutex - * \return EMBB_SUCCESS if shared mutex could be initialized \n - * EMBB_ERROR otherwise - * - * \memory (Potentially) allocates dynamic memory - * - * \notthreadsafe - * - * \see embb_shared_mutex_destroy() - */ -int embb_shared_mutex_init(embb_shared_mutex_t* shared_mutex); - -/** - * Waits until the shared mutex can be locked for writing and locks it. - * - * \pre \c shared_mutex is initialized and not locked by the current thread. - * \post If successful, \c shared_mutex is locked for writing. - * - * \param shared_mutex Pointer to shared mutex - * \return EMBB_SUCCESS if shared_mutex could be locked for writing \n - * EMBB_ERROR otherwise - * - * \threadsafe - * - * \see embb_shared_mutex_try_lock(), embb_shared_mutex_unlock() - */ -int embb_shared_mutex_lock(embb_shared_mutex_t* shared_mutex); - -/** - * Tries to lock the shared mutex for writing and returns immediately. - * - * \pre \c shared_mutex is initialized - * \post If successful, \c shared_mutex is locked for writing - * - * \param shared_mutex Pointer to shared mutex - * \return EMBB_SUCCESS if shared_mutex could be locked for writing \n - * EMBB_BUSY if shared_mutex could not be locked for writing \n - * EMBB_ERROR if an error occurred - * - * \threadsafe - * - * \see embb_shared_mutex_lock(), embb_shared_mutex_unlock() - */ -int embb_shared_mutex_try_lock(embb_shared_mutex_t* shared_mutex); - -/** - * Unlocks the shared mutex locked for writing. - * - * \pre \c shared_mutex has been locked for writing by the current thread. - * \post If successful, \c shared_mutex is unlocked. - * - * \param shared_mutex Pointer to shared mutex - * \return EMBB_SUCCESS if the operation was successful \n - * EMBB_ERROR otherwise - * - * \threadsafe - * - * \see embb_shared_mutex_lock(), embb_shared_mutex_try_lock() - */ -int embb_shared_mutex_unlock(embb_shared_mutex_t* shared_mutex); - -/** - * Waits until the shared mutex can be locked for reading and locks it. - * - * \pre \c shared_mutex is initialized and not locked by the current thread. - * \post If successful, \c shared_mutex is locked for reading. - * - * \param shared_mutex Pointer to shared mutex - * \return EMBB_SUCCESS if shared_mutex could be locked for reading \n - * EMBB_ERROR otherwise - * - * \threadsafe - * - * \see embb_shared_mutex_try_lock_shared(), embb_shared_mutex_unlock_shared() - */ -int embb_shared_mutex_lock_shared(embb_shared_mutex_t* shared_mutex); - -/** - * Tries to lock the shared mutex for reading and returns immediately. - * - * \pre \c shared_mutex is initialized - * \post If successful, \c shared_mutex is locked for reading - * - * \param shared_mutex Pointer to shared mutex - * \return EMBB_SUCCESS if shared_mutex could be locked for reading \n - * EMBB_BUSY if shared_mutex could not be locked for reading \n - * EMBB_ERROR if an error occurred - * - * \threadsafe - * - * \see embb_shared_mutex_lock_shared(), embb_shared_mutex_unlock_shared() - */ -int embb_shared_mutex_try_lock_shared(embb_shared_mutex_t* shared_mutex); - -/** - * Unlocks the shared mutex locked for reading. - * - * \pre \c shared_mutex has been locked for reading by the current thread. - * \post If successful, \c shared_mutex is unlocked. - * - * \param shared_mutex Pointer to shared mutex - * \return EMBB_SUCCESS if the operation was successful \n - * EMBB_ERROR otherwise - * - * \threadsafe - * - * \see embb_shared_mutex_lock_shared(), embb_shared_mutex_try_lock_shared() - */ -int embb_shared_mutex_unlock_shared(embb_shared_mutex_t* shared_mutex); - -/** - * Destroys the shared mutex and frees its resources. - * - * \pre \c shared_mutex has been initialized - * \post \c shared_mutex is uninitialized - * - * \param shared_mutex Pointer to shared mutex - * - * \notthreadsafe - * - * \see embb_shared_mutex_init() - */ -void embb_shared_mutex_destroy(embb_shared_mutex_t* shared_mutex); - -#ifdef __cplusplus -} // Close extern "C" -#endif - -/** - * \} - */ - -#endif // EMBB_BASE_C_SHARED_MUTEX_H_ diff --git a/base_c/src/rwlock.c b/base_c/src/rwlock.c new file mode 100644 index 0000000..a9bbbf5 --- /dev/null +++ b/base_c/src/rwlock.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2014-2015, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include + +#ifdef EMBB_PLATFORM_THREADING_WINTHREADS + +int embb_rwlock_init(embb_rwlock_t* rwlock) { + InitializeSRWLock(rwlock); + return EMBB_SUCCESS; +} + +int embb_rwlock_lock_read(embb_rwlock_t* rwlock) { + AcquireSRWLockShared(rwlock); + return EMBB_SUCCESS; +} + +int embb_rwlock_lock_write(embb_rwlock_t* rwlock) { + AcquireSRWLockExclusive(rwlock); + return EMBB_SUCCESS; +} + +int embb_rwlock_try_lock_read(embb_rwlock_t* rwlock) { + BOOLEAN success; + success = TryAcquireSRWLockShared(rwlock); + if (success == FALSE) return EMBB_ERROR; + return EMBB_SUCCESS; +} + +int embb_rwlock_try_lock_write(embb_rwlock_t* rwlock) { + BOOLEAN success; + success = TryAcquireSRWLockExclusive(rwlock); + if (success == FALSE) return EMBB_ERROR; + return EMBB_SUCCESS; +} + +int embb_rwlock_unlock_read(embb_rwlock_t* rwlock) { + ReleaseSRWLockShared(rwlock); + return EMBB_SUCCESS; +} + +int embb_rwlock_unlock_write(embb_rwlock_t* rwlock) { + ReleaseSRWLockExclusive(rwlock); + return EMBB_SUCCESS; +} + +void embb_rwlock_destroy(embb_rwlock_t* rwlock) { + // Quoting MSDN: "SRW locks do not need to be explicitly destroyed". + EMBB_UNUSED(rwlock); +} + +#endif /* EMBB_PLATFORM_THREADING_WINTHREADS */ + +#ifdef EMBB_PLATFORM_THREADING_POSIXTHREADS + +int embb_rwlock_init(embb_rwlock_t* rwlock) { + int result = pthread_rwlock_init(rwlock, NULL); + if (result != 0) { + return EMBB_ERROR; + } + return EMBB_SUCCESS; +} + +int embb_rwlock_lock_read(embb_rwlock_t* rwlock) { + int result = pthread_rwlock_rdlock(rwlock); + if (result != 0) { + return EMBB_ERROR; + } + return EMBB_SUCCESS; +} + +int embb_rwlock_lock_write(embb_rwlock_t* rwlock) { + int result = pthread_rwlock_wrlock(rwlock); + if (result != 0) { + return EMBB_ERROR; + } + return EMBB_SUCCESS; +} + +int embb_rwlock_try_lock_read(embb_rwlock_t* rwlock) { + int result = pthread_rwlock_tryrdlock(rwlock); + if (result == 0) { + return EMBB_SUCCESS; + } + if (result == EBUSY) { + return EMBB_BUSY; + } + return EMBB_ERROR; +} + +int embb_rwlock_try_lock_write(embb_rwlock_t* rwlock) { + int result = pthread_rwlock_trywrlock(rwlock); + if (result == 0) { + return EMBB_SUCCESS; + } + if (result == EBUSY) { + return EMBB_BUSY; + } + return EMBB_ERROR; +} + +int embb_rwlock_unlock_read(embb_rwlock_t* rwlock) { + int result = pthread_rwlock_unlock(rwlock); + if (result != 0) { + return EMBB_ERROR; + } + return EMBB_SUCCESS; +} + +int embb_rwlock_unlock_write(embb_rwlock_t* rwlock) { + int result = pthread_rwlock_unlock(rwlock); + if (result != 0) { + return EMBB_ERROR; + } + return EMBB_SUCCESS; +} + +void embb_rwlock_destroy(embb_rwlock_t* rwlock) { + pthread_rwlock_destroy(rwlock); +} + +#endif /* EMBB_PLATFORM_THREADING_POSIXTHREADS */ diff --git a/base_c/src/shared_mutex.c b/base_c/src/shared_mutex.c deleted file mode 100644 index 0709d26..0000000 --- a/base_c/src/shared_mutex.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2014-2015, Siemens AG. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -#include - -#ifdef EMBB_PLATFORM_THREADING_WINTHREADS - -int embb_shared_mutex_init(embb_shared_mutex_t* shared_mutex) { - InitializeSRWLock(shared_mutex); - return EMBB_SUCCESS; -} - -int embb_shared_mutex_lock(embb_shared_mutex_t* shared_mutex) { - AcquireSRWLockExclusive(shared_mutex); - return EMBB_SUCCESS; -} - -int embb_shared_mutex_try_lock(embb_shared_mutex_t* shared_mutex) { - BOOLEAN success; - success = TryAcquireSRWLockExclusive(shared_mutex); - if (success == FALSE) return EMBB_ERROR; - return EMBB_SUCCESS; -} - -int embb_shared_mutex_unlock(embb_shared_mutex_t* shared_mutex) { - ReleaseSRWLockExclusive(shared_mutex); - return EMBB_SUCCESS; -} - -int embb_shared_mutex_lock_shared(embb_shared_mutex_t* shared_mutex) { - AcquireSRWLockShared(shared_mutex); - return EMBB_SUCCESS; -} - -int embb_shared_mutex_try_lock_shared(embb_shared_mutex_t* shared_mutex) { - BOOLEAN success; - success = TryAcquireSRWLockShared(shared_mutex); - if (success == FALSE) return EMBB_ERROR; - return EMBB_SUCCESS; -} - -int embb_shared_mutex_unlock_shared(embb_shared_mutex_t* shared_mutex) { - ReleaseSRWLockShared(shared_mutex); - return EMBB_SUCCESS; -} - -void embb_shared_mutex_destroy(embb_shared_mutex_t* shared_mutex) { - // Quoting MSDN: "SRW locks do not need to be explicitly destroyed". - EMBB_UNUSED(shared_mutex); -} - -#endif /* EMBB_PLATFORM_THREADING_WINTHREADS */ - -#ifdef EMBB_PLATFORM_THREADING_POSIXTHREADS - -int embb_shared_mutex_init(embb_shared_mutex_t* shared_mutex) { - int result = pthread_rwlock_init(shared_mutex, NULL); - if (result != 0) { - return EMBB_ERROR; - } - return EMBB_SUCCESS; -} - -int embb_shared_mutex_lock(embb_shared_mutex_t* shared_mutex) { - int result = pthread_rwlock_wrlock(shared_mutex); - if (result != 0) { - return EMBB_ERROR; - } - return EMBB_SUCCESS; -} - -int embb_shared_mutex_try_lock(embb_shared_mutex_t* shared_mutex) { - int result = pthread_rwlock_trywrlock(shared_mutex); - if (result == 0) { - return EMBB_SUCCESS; - } - if (result == EBUSY) { - return EMBB_BUSY; - } - return EMBB_ERROR; -} - -int embb_shared_mutex_unlock(embb_shared_mutex_t* shared_mutex) { - int result = pthread_rwlock_unlock(shared_mutex); - if (result != 0) { - return EMBB_ERROR; - } - return EMBB_SUCCESS; -} - -int embb_shared_mutex_lock_shared(embb_shared_mutex_t* shared_mutex) { - int result = pthread_rwlock_rdlock(shared_mutex); - if (result != 0) { - return EMBB_ERROR; - } - return EMBB_SUCCESS; -} - -int embb_shared_mutex_try_lock_shared(embb_shared_mutex_t* shared_mutex) { - int result = pthread_rwlock_tryrdlock(shared_mutex); - if (result == 0) { - return EMBB_SUCCESS; - } - if (result == EBUSY) { - return EMBB_BUSY; - } - return EMBB_ERROR; -} - -int embb_shared_mutex_unlock_shared(embb_shared_mutex_t* shared_mutex) { - int result = pthread_rwlock_unlock(shared_mutex); - if (result != 0) { - return EMBB_ERROR; - } - return EMBB_SUCCESS; -} - -void embb_shared_mutex_destroy(embb_shared_mutex_t* shared_mutex) { - pthread_rwlock_destroy(shared_mutex); -} - -#endif /* EMBB_PLATFORM_THREADING_POSIXTHREADS */ diff --git a/base_c/test/main.cc b/base_c/test/main.cc index e2ed1b6..faa2430 100644 --- a/base_c/test/main.cc +++ b/base_c/test/main.cc @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include #include @@ -52,7 +52,7 @@ using embb::base::test::CoreSetTest; using embb::base::test::ConditionVarTest; using embb::base::test::ThreadTest; using embb::base::test::ThreadSpecificStorageTest; -using embb::base::test::SharedMutexTest; +using embb::base::test::RWLockTest; PT_MAIN("Base C") { embb_log_set_log_level(EMBB_LOG_LEVEL_WARNING); @@ -70,7 +70,7 @@ PT_MAIN("Base C") { PT_RUN(ConditionVarTest); PT_RUN(ThreadTest); PT_RUN(ThreadSpecificStorageTest); - PT_RUN(SharedMutexTest); + PT_RUN(RWLockTest); PT_EXPECT(embb_get_bytes_allocated() == 0); } diff --git a/base_c/test/rwlock_test.cc b/base_c/test/rwlock_test.cc new file mode 100644 index 0000000..3950fde --- /dev/null +++ b/base_c/test/rwlock_test.cc @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2014-2015, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +namespace embb { +namespace base { +namespace test { + +RWLockTest::RWLockTest() + : counter_(0), + num_threads_(partest::TestSuite::GetDefaultNumThreads()), + num_iterations_(partest::TestSuite::GetDefaultNumIterations()) { + CreateUnit("Shared read") + .Pre(&RWLockTest::TestSharedRead_Pre, this) + .Add(&RWLockTest::TestSharedRead_ThreadMethod, this, + num_threads_, num_iterations_) + .Post(&RWLockTest::TestSharedRead_Post, this); + CreateUnit("Exclusive write") + .Pre(&RWLockTest::TestExclusiveWrite_Pre, this) + .Add(&RWLockTest::TestExclusiveWrite_ReaderMethod, this, + num_threads_, num_iterations_) + .Add(&RWLockTest::TestExclusiveWrite_WriterMethod, this, + num_threads_, num_iterations_) + .Post(&RWLockTest::TestExclusiveWrite_Post, this); +} + +void RWLockTest::TestSharedRead_Pre() { + int success = embb_rwlock_init(&rwlock_); + PT_ASSERT_EQ_MSG(success, EMBB_SUCCESS, "Failed to initialize rwlock."); +} + +void RWLockTest::TestSharedRead_ThreadMethod() { + int success = embb_rwlock_try_lock_read(&rwlock_); + PT_ASSERT_EQ_MSG(success, EMBB_SUCCESS, "Failed to lock for reading."); + + int spin = 10000; + while (--spin != 0); + + success = embb_rwlock_unlock_read(&rwlock_); + PT_ASSERT_EQ_MSG(success, EMBB_SUCCESS, "Failed to unlock (reading)."); +} + +void RWLockTest::TestSharedRead_Post() { + embb_rwlock_destroy(&rwlock_); +} + +void RWLockTest::TestExclusiveWrite_Pre() { + int success = embb_rwlock_init(&rwlock_); + PT_ASSERT_EQ_MSG(success, EMBB_SUCCESS, "Failed to initialize rwlock."); + + counter_ = 0; +} + +void RWLockTest::TestExclusiveWrite_ReaderMethod() { + // Just add some contention + + int success = embb_rwlock_try_lock_read(&rwlock_); + if (success != EMBB_SUCCESS) return; + + int spin = 10000; + while (--spin != 0); + + success = embb_rwlock_unlock_read(&rwlock_); + PT_ASSERT_EQ_MSG(success, EMBB_SUCCESS, "Failed to unlock (reading)."); +} + +void RWLockTest::TestExclusiveWrite_WriterMethod() { + int success = embb_rwlock_lock_write(&rwlock_); + PT_ASSERT_EQ_MSG(success, EMBB_SUCCESS, "Failed to lock for writing."); + + ++counter_; + + success = embb_rwlock_unlock_write(&rwlock_); + PT_ASSERT_EQ_MSG(success, EMBB_SUCCESS, "Failed to unlock (writing)."); +} + +void RWLockTest::TestExclusiveWrite_Post() { + PT_ASSERT_EQ_MSG(counter_, num_iterations_ * num_threads_, + "Counter value is inconsistent."); + embb_rwlock_destroy(&rwlock_); +} + +} // namespace test +} // namespace base +} // namespace embb diff --git a/base_c/test/rwlock_test.h b/base_c/test/rwlock_test.h new file mode 100644 index 0000000..8d208cd --- /dev/null +++ b/base_c/test/rwlock_test.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014-2015, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BASE_C_TEST_RWLOCK_TEST_H_ +#define BASE_C_TEST_RWLOCK_TEST_H_ + +#include +#include +#include + + +namespace embb { +namespace base { +namespace test { + +class RWLockTest : public partest::TestCase { + public: + RWLockTest(); + + private: + void TestSharedRead_Pre(); + void TestSharedRead_ThreadMethod(); + void TestSharedRead_Post(); + + void TestExclusiveWrite_Pre(); + void TestExclusiveWrite_ReaderMethod(); + void TestExclusiveWrite_WriterMethod(); + void TestExclusiveWrite_Post(); + + embb_rwlock_t rwlock_; + size_t counter_; + size_t num_threads_; + size_t num_iterations_; +}; + +} // namespace test +} // namespace base +} // namespace embb + +#endif // BASE_C_TEST_RWLOCK_TEST_H_ diff --git a/base_c/test/shared_mutex_test.cc b/base_c/test/shared_mutex_test.cc deleted file mode 100644 index 9ec1005..0000000 --- a/base_c/test/shared_mutex_test.cc +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2014-2015, Siemens AG. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -namespace embb { -namespace base { -namespace test { - -SharedMutexTest::SharedMutexTest() - : counter_(0), - num_threads_(partest::TestSuite::GetDefaultNumThreads()), - num_iterations_(partest::TestSuite::GetDefaultNumIterations()) { - CreateUnit("Shared read") - .Pre(&SharedMutexTest::TestSharedRead_Pre, this) - .Add(&SharedMutexTest::TestSharedRead_ThreadMethod, this, - num_threads_, num_iterations_) - .Post(&SharedMutexTest::TestSharedRead_Post, this); - CreateUnit("Exclusive write") - .Pre(&SharedMutexTest::TestExclusiveWrite_Pre, this) - .Add(&SharedMutexTest::TestExclusiveWrite_ReaderMethod, this, - num_threads_ / 2, num_iterations_) - .Add(&SharedMutexTest::TestExclusiveWrite_WriterMethod, this, - num_threads_ / 2, num_iterations_) - .Post(&SharedMutexTest::TestExclusiveWrite_Post, this); -} - -void SharedMutexTest::TestSharedRead_Pre() { - int success = embb_shared_mutex_init(&shared_mutex_); - PT_ASSERT_EQ_MSG(success, EMBB_SUCCESS, "Failed to initialize shared mutex."); -} - -void SharedMutexTest::TestSharedRead_ThreadMethod() { - int success = embb_shared_mutex_try_lock_shared(&shared_mutex_); - PT_ASSERT_EQ_MSG(success, EMBB_SUCCESS, "Failed to lock for reading."); - - int spin = 10000; - while (--spin != 0); - - success = embb_shared_mutex_unlock_shared(&shared_mutex_); - PT_ASSERT_EQ_MSG(success, EMBB_SUCCESS, "Failed to unlock (reading)."); -} - -void SharedMutexTest::TestSharedRead_Post() { - embb_shared_mutex_destroy(&shared_mutex_); -} - -void SharedMutexTest::TestExclusiveWrite_Pre() { - int success = embb_shared_mutex_init(&shared_mutex_); - PT_ASSERT_EQ_MSG(success, EMBB_SUCCESS, "Failed to initialize shared mutex."); - - counter_ = 0; -} - -void SharedMutexTest::TestExclusiveWrite_ReaderMethod() { - // Just add some contention - - int success = embb_shared_mutex_try_lock_shared(&shared_mutex_); - if (success != EMBB_SUCCESS) return; - - int spin = 10000; - while (--spin != 0); - - success = embb_shared_mutex_unlock_shared(&shared_mutex_); - PT_ASSERT_EQ_MSG(success, EMBB_SUCCESS, "Failed to unlock (reading)."); -} - -void SharedMutexTest::TestExclusiveWrite_WriterMethod() { - int success = embb_shared_mutex_lock(&shared_mutex_); - PT_ASSERT_EQ_MSG(success, EMBB_SUCCESS, "Failed to lock for writing."); - - ++counter_; - - success = embb_shared_mutex_unlock(&shared_mutex_); - PT_ASSERT_EQ_MSG(success, EMBB_SUCCESS, "Failed to unlock (writing)."); -} - -void SharedMutexTest::TestExclusiveWrite_Post() { - PT_ASSERT_EQ_MSG(counter_, num_iterations_ * (num_threads_ / 2), - "Counter value is inconsistent."); - embb_shared_mutex_destroy(&shared_mutex_); -} - -} // namespace test -} // namespace base -} // namespace embb diff --git a/base_c/test/shared_mutex_test.h b/base_c/test/shared_mutex_test.h deleted file mode 100644 index 67f4a31..0000000 --- a/base_c/test/shared_mutex_test.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2014-2015, Siemens AG. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef BASE_C_TEST_SHARED_MUTEX_TEST_H_ -#define BASE_C_TEST_SHARED_MUTEX_TEST_H_ - -#include -#include -#include - - -namespace embb { -namespace base { -namespace test { - -class SharedMutexTest : public partest::TestCase { - public: - SharedMutexTest(); - - private: - void TestSharedRead_Pre(); - void TestSharedRead_ThreadMethod(); - void TestSharedRead_Post(); - - void TestExclusiveWrite_Pre(); - void TestExclusiveWrite_ReaderMethod(); - void TestExclusiveWrite_WriterMethod(); - void TestExclusiveWrite_Post(); - - embb_shared_mutex_t shared_mutex_; - size_t counter_; - size_t num_threads_; - size_t num_iterations_; -}; - -} // namespace test -} // namespace base -} // namespace embb - -#endif // BASE_C_TEST_SHARED_MUTEX_TEST_H_ diff --git a/base_cpp/include/embb/base/base.h b/base_cpp/include/embb/base/base.h index 3478685..26d0730 100644 --- a/base_cpp/include/embb/base/base.h +++ b/base_cpp/include/embb/base/base.h @@ -59,6 +59,6 @@ #include #include #include -#include +#include #endif // EMBB_BASE_BASE_H_ diff --git a/base_cpp/include/embb/base/internal/platform.h b/base_cpp/include/embb/base/internal/platform.h index 9106764..04a2b34 100644 --- a/base_cpp/include/embb/base/internal/platform.h +++ b/base_cpp/include/embb/base/internal/platform.h @@ -44,7 +44,7 @@ typedef embb_thread_t ThreadType; typedef DWORD IDType; typedef embb_mutex_t MutexType; typedef embb_condition_t ConditionVariableType; -typedef embb_shared_mutex_t SharedMutexType; +typedef embb_rwlock_t RWLockType; } // namespace internal } // namespace base @@ -60,7 +60,7 @@ typedef embb_thread_t ThreadType; typedef embb_thread_id_t IDType; typedef embb_mutex_t MutexType; typedef embb_condition_t ConditionVariableType; -typedef embb_shared_mutex_t SharedMutexType; +typedef embb_rwlock_t RWLockType; } // namespace internal } // namespace base diff --git a/base_cpp/include/embb/base/internal/shared_mutex-inl.h b/base_cpp/include/embb/base/internal/shared_mutex-inl.h deleted file mode 100644 index 5a3ea0b..0000000 --- a/base_cpp/include/embb/base/internal/shared_mutex-inl.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2014-2015, Siemens AG. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef EMBB_BASE_INTERNAL_SHARED_MUTEX_INL_H_ -#define EMBB_BASE_INTERNAL_SHARED_MUTEX_INL_H_ - -#include -#include // For std::swap() - -namespace embb { -namespace base { - -template -SharedLock::SharedLock() - : shared_mutex_(NULL), locked_(false) {} - -template -SharedLock::SharedLock(SharedMutex& shared_mutex) - : shared_mutex_(&shared_mutex), locked_(false) { - shared_mutex_->LockShared(); - locked_ = true; -} - -template -SharedLock::SharedLock(SharedMutex& shared_mutex, DeferLockTag) - : shared_mutex_(&shared_mutex), locked_(false) {} - -template -SharedLock::SharedLock(SharedMutex& shared_mutex, TryLockTag) - : shared_mutex_(&shared_mutex), locked_(shared_mutex_->TryLockShared()) {} - -template -SharedLock::SharedLock(SharedMutex& shared_mutex, AdoptLockTag) - : shared_mutex_(&shared_mutex), locked_(true) {} - -template -SharedLock::~SharedLock() { - if (OwnsLock()) { - shared_mutex_->UnlockShared(); - } -} - -template -void SharedLock::LockShared() { - if (shared_mutex_ == NULL || locked_) { - EMBB_THROW(ErrorException, "Mutex not set or locked"); - } - shared_mutex_->LockShared(); - locked_ = true; -} - -template -bool SharedLock::TryLockShared() { - if (shared_mutex_ == NULL || locked_) { - EMBB_THROW(ErrorException, "Mutex not set or locked"); - } - locked_ = shared_mutex_->TryLockShared(); - return locked_; -} - -template -void SharedLock::UnlockShared() { - if (shared_mutex_ == NULL || !locked_) { - EMBB_THROW(ErrorException, "Mutex not set or unlocked"); - } - shared_mutex_->UnlockShared(); - locked_ = false; -} - -template -void SharedLock::Swap(SharedLock& other) { - std::swap(shared_mutex_, other.shared_mutex_); - std::swap(locked_, other.locked_); -} - -template -SharedMutex* SharedLock::Release() { - SharedMutex* to_release = shared_mutex_; - shared_mutex_ = NULL; - locked_ = false; - return to_release; -} - -template -bool SharedLock::OwnsLock() const { - assert(!(locked_ && (shared_mutex_ == NULL))); - return locked_; -} - -} // namespace base -} // namespace embb - -#endif // EMBB_BASE_INTERNAL_SHARED_MUTEX_INL_H_ diff --git a/base_cpp/include/embb/base/rwlock.h b/base_cpp/include/embb/base/rwlock.h new file mode 100644 index 0000000..64ecd2a --- /dev/null +++ b/base_cpp/include/embb/base/rwlock.h @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2014-2015, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef EMBB_BASE_RWLOCK_H_ +#define EMBB_BASE_RWLOCK_H_ + +#include +#include + +namespace embb { +namespace base { + +/** + * \defgroup CPP_BASE_RWLOCK Readers-Writers Lock + * + * Shared-read/exclusive-write lock for thread synchronization. + * + * \ingroup CPP_BASE + */ + +/** + * Shared-read/exclusive-write (readers-writers) lock. + * + * Allows simultaneous shared access for concurrent readers, but only exclusive + * access for writers. Cannot be locked recursively. Fairness and/or FIFO order + * guaranties are platform specific and should be assumed non-existent. + * + * \ingroup CPP_BASE_RWLOCK + */ +class RWLock { + public: + /** + * Creates an rwlock which is in unlocked state. + * + * \memory Potentially allocates dynamic memory + * \notthreadsafe + */ + RWLock(); + + /** + * Destroys internal representation. + */ + ~RWLock(); + + /** + * Waits until the rwlock can be locked for reading and locks it. + * + * \pre The \c rwlock is not locked by the current thread. + * \post The \c rwlock is locked for reading. + * + * \threadsafe + * + * \see TryLockRead(), UnlockRead() + */ + void LockRead(); + + /** + * Waits until the rwlock can be locked for writing and locks it. + * + * \pre \c rwlock is initialized and not locked by the current thread. + * \post \c rwlock is locked for writing. + * + * \threadsafe + * + * \see TryLockWrite(), UnlockWrite() + */ + void LockWrite(); + + /** + * Tries to lock the rwlock for reading and returns immediately. + * + * \pre \c rwlock is not locked by the current thread. + * \post If successful, \c rwlock is locked for reading. + * + * \return \c true if rwlock was locked for reading \n + * \c false otherwise + * + * \threadsafe + * + * \see LockRead(), UnlockRead() + */ + bool TryLockRead(); + + /** + * Tries to lock the rwlock for writing and returns immediately. + * + * \pre \c rwlock is not locked by the current thread. + * \post If successful, \c rwlock is locked for writing. + * + * \return \c true if rwlock was locked for reading \n + * \c false otherwise + * + * \threadsafe + * + * \see LockWrite(), UnlockWrite() + */ + bool TryLockWrite(); + + /** + * Unlocks an rwlock locked for reading. + * + * \pre \c rwlock has been locked for reading by the current thread. + * \post \c rwlock is unlocked. + * + * \threadsafe + * + * \see LockRead(), TryLockRead() + */ + void UnlockRead(); + + /** + * Unlocks an rwlock locked for writing. + * + * \pre \c rwlock has been locked for writing by the current thread. + * \post \c rwlock is unlocked. + * + * \threadsafe + * + * \see LockWrite(), TryLockWrite() + */ + void UnlockWrite(); + + + /** + * Adaptor class for the readers lock that can be used with "LockGuard" and/or + * "UniqueLock" ownership wrappers. + * + * \see LockGuard, UniqueLock + */ + class ReaderLock { + public: + ReaderLock(RWLock& rwlock); + void Lock(); + bool TryLock(); + void Unlock(); + private: + ReaderLock(const ReaderLock&); + ReaderLock& operator=(const ReaderLock&); + RWLock& rwlock_; + }; + + /** + * Adaptor class for the writers lock that can be used with "LockGuard" and/or + * "UniqueLock" ownership wrappers. + * + * \see LockGuard, UniqueLock + */ + class WriterLock { + public: + WriterLock(RWLock& rwlock); + void Lock(); + bool TryLock(); + void Unlock(); + private: + WriterLock(const WriterLock&); + WriterLock& operator=(const WriterLock&); + RWLock& rwlock_; + }; + + /** + * Returns an adaptor for the readers lock to be used with "LockGuard" and/or + * "UniqueLock" ownership wrappers. + */ + ReaderLock& GetReaderLock(); + + /** + * Returns an adaptor for the writes lock to be used with "LockGuard" and/or + * "UniqueLock" ownership wrappers. + */ + WriterLock& GetWriterLock(); + + private: + /** + * Disables copy construction and assignment. + */ + RWLock(const RWLock&); + RWLock& operator=(const RWLock&); + + internal::RWLockType rwlock_; /**< Actual rwlock implementation from base_c */ + ReaderLock reader_lock_; /**< Lock adaptor for readers */ + WriterLock writer_lock_; /**< Lock adaptor for writers */ +}; + +} // namespace base +} // namespace embb + +#endif // EMBB_BASE_RWLOCK_H_ diff --git a/base_cpp/include/embb/base/shared_mutex.h b/base_cpp/include/embb/base/shared_mutex.h deleted file mode 100644 index 4e2138d..0000000 --- a/base_cpp/include/embb/base/shared_mutex.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (c) 2014-2015, Siemens AG. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef EMBB_BASE_SHARED_MUTEX_H_ -#define EMBB_BASE_SHARED_MUTEX_H_ - -#include -#include -#include - -namespace embb { -namespace base { - -/** - * \defgroup CPP_BASE_SHARED_MUTEX Shared mutex - * - * Shared mutexes for thread synchronization - * - * Provides an abstraction from platform-specific shared mutex implementations. - * Shared mutexes provide two levels of access: exclusive access - only one - * thread can own the mutex; shared access - several threads can share ownership - * of the same mutex. Shared mutexes facilitate the "single writer, multiple - * readers" scenarios. - * - * \ingroup CPP_BASE - */ - -/** - * Shared mutex providing shared-read/exclusive-write access synchronization. - * - * Allows simultaneous shared access for concurrent readers, but only exclusive - * access for writers. Cannot be locked recursively. Fairness and/or FIFO order - * guarantees are platform specific and should be assumed non-existent. - * - * \see Mutex - * - * \ingroup CPP_BASE_SHARED_MUTEX - */ -class SharedMutex { - public: - /** - * Creates the shared mutex object which is initially in an unlocked state. - * - * \memory Potentially allocates dynamic memory - * - * \notthreadsafe - */ - SharedMutex(); - - /** - * Destroys internal representation. - */ - ~SharedMutex(); - - /** - * Waits until the shared mutex can be locked for writing and locks it. - * - * \pre \c shared_mutex is initialized and not locked by the current thread. - * \post \c shared_mutex is locked for writing. - * - * \threadsafe - * - * \see TryLock(), Unlock() - */ - void Lock(); - - /** - * Tries to lock the shared mutex for writing and returns immediately. - * - * \pre \c shared_mutex is not locked by the current thread. - * \post If successful, \c shared_mutex is locked for writing. - * - * \return \c true if shared mutex was locked for reading \n - * \c false otherwise - * - * \threadsafe - * - * \see Lock(), Unlock() - */ - bool TryLock(); - - /** - * Unlocks the shared mutex locked for writing. - * - * \pre \c shared_mutex has been locked for writing by the current thread. - * \post \c shared_mutex is unlocked. - * - * \threadsafe - * - * \see Lock(), TryLock() - */ - void Unlock(); - - /** - * Waits until the shared mutex can be locked for reading and locks it. - * - * \pre The \c shared_mutex is not locked by the current thread. - * \post The \c shared_mutex is locked for reading. - * - * \threadsafe - * - * \see TryLockShared(), UnlockShared() - */ - void LockShared(); - - /** - * Tries to lock the shared mutex for reading and returns immediately. - * - * \pre \c shared_mutex is not locked by the current thread. - * \post If successful, \c shared_mutex is locked for reading. - * - * \return \c true if shared mutex was locked for reading \n - * \c false otherwise - * - * \threadsafe - * - * \see LockShared(), UnlockShared() - */ - bool TryLockShared(); - - /** - * Unlocks the shared mutex locked for reading. - * - * \pre \c shared_mutex has been locked for reading by the current thread. - * \post \c shared_mutex is unlocked. - * - * \threadsafe - * - * \see LockShared(), TryLockShared() - */ - void UnlockShared(); - - private: - /** - * Disables copy construction and assignment. - */ - SharedMutex(const SharedMutex&); - SharedMutex& operator=(const SharedMutex&); - - /** Actual shared mutex implementation from base_c */ - internal::SharedMutexType shared_mutex_; -}; - -/** - * Ownership wrapper for a shared mutex that works on the shared access level - * (i.e. it locks a shared mutex in shared "readers" mode). - * - * For exclusive ownership wrapping, use UniqueLock. - * - * \notthreadsafe - * - * \tparam SharedMutex Type of the shared mutex object being wrapped - * - * \see SharedMutex, UniqueLock - * - * \ingroup CPP_BASE_MUTEX - */ -template -class SharedLock { - public: - /** - * Creates a lock without assigned shared mutex. - * - * A shared mutex can be assigned to the lock using the method Swap(). - */ - SharedLock(); - - /** - * Creates a lock from an unlocked shared mutex and locks it for reading. - * - * \pre \c shared_mutex is unlocked - * \post \c shared_mutex is locked for reading - * - * \param[IN] shared_mutex Shared mutex to be managed - */ - explicit SharedLock(SharedMutex& shared_mutex); - - /** - * Creates a lock from an unlocked shared mutex without locking it. - * - * \pre \c shared_mutex is unlocked - * \post \c shared_mutex is unlocked - * - * \param[IN] shared_mutex Shared mutex to be managed - * \param[IN] tag Tag to select correct constructor - */ - SharedLock(SharedMutex& shared_mutex, DeferLockTag tag); - - /** - * Creates a lock from an unlocked shared mutex and tries to lock it - * for reading. - * - * \pre \c shared_mutex is unlocked - * \post If successful, \c shared_mutex is locked for reading - * - * \param[IN] shared_mutex Shared mutex to be managed - * \param[IN] tag Tag to select correct constructor - */ - SharedLock(SharedMutex& shared_mutex, TryLockTag tag); - - /** - * Creates a lock from an already locked shared mutex. - * - * \pre \c shared_mutex is locked for reading - * \post \c shared_mutex is locked for reading - * - * \param[IN] shared_mutex Shared mutex to be managed - * \param[IN] tag Tag to select correct constructor - */ - SharedLock(SharedMutex& shared_mutex, AdoptLockTag tag); - - /** - * Unlocks the shared mutex if owned. - */ - ~SharedLock(); - - /** - * Waits until the shared mutex can be locked for reading and locks it. - * - * \throws ErrorException, if no shared mutex is set or it is already locked - */ - void LockShared(); - - /** - * Tries to lock the shared mutex for reading and returns immediately. - * - * \return \c true if shared mutex was locked for reading \n - * \c false otherwise - * - * \throws ErrorException, if no shared mutex is set or it is already locked - */ - bool TryLockShared(); - - /** - * Unlocks the shared mutex locked for reading. - * - * \throws ErrorException, if no shared mutex is set or it is not yet locked - */ - void UnlockShared(); - - /** - * Exchange shared mutex ownership with another shared lock - * - * \param other Shared lock to exchange ownership with - */ - void Swap(SharedLock& other); - - /** - * Gives up ownership of the shared mutex and returns a pointer to it. - * - * \return A pointer to the owned shared mutex. (If no shared mutex was - * owned, returns NULL). - */ - SharedMutex* Release(); - - /** - * Checks whether the shared mutex is owned and locked. - * - * \return \c true if shared mutex is locked, otherwise \c false. - */ - bool OwnsLock() const; - - private: - /** - * Disable copy construction and assignment. - */ - SharedLock(const SharedLock&); - SharedLock& operator=(const SharedLock&); - - /** Pointer to the owned shared mutex */ - SharedMutex* shared_mutex_; - /** Locked flag (is true if and only if the owned shared mutex is locked) */ - bool locked_; -}; - -} // namespace base -} // namespace embb - -#include - -#endif // EMBB_BASE_SHARED_MUTEX_H_ diff --git a/base_cpp/src/rwlock.cc b/base_cpp/src/rwlock.cc new file mode 100644 index 0000000..24dd2c6 --- /dev/null +++ b/base_cpp/src/rwlock.cc @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2014-2015, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +namespace embb { +namespace base { + +RWLock::RWLock() + : rwlock_(), +// Disable "this is used in base member initializer" warning. +// We explicitly want this. +#ifdef EMBB_PLATFORM_COMPILER_MSVC +#pragma warning(push) +#pragma warning(disable:4355) +#endif + reader_lock_(*this), + writer_lock_(*this) { +#ifdef EMBB_PLATFORM_COMPILER_MSVC +#pragma warning(pop) +#endif + embb_rwlock_init(&rwlock_); +} + +RWLock::~RWLock() { + embb_rwlock_destroy(&rwlock_); +} + +void RWLock::LockRead() { + embb_rwlock_lock_read(&rwlock_); +} + +void RWLock::LockWrite() { + embb_rwlock_lock_write(&rwlock_); +} + +bool RWLock::TryLockRead() { + int result = embb_rwlock_try_lock_read(&rwlock_); + return result == EMBB_SUCCESS; +} + +bool RWLock::TryLockWrite() { + int result = embb_rwlock_try_lock_write(&rwlock_); + return result == EMBB_SUCCESS; +} + +void RWLock::UnlockRead() { + embb_rwlock_unlock_read(&rwlock_); +} + +void RWLock::UnlockWrite() { + embb_rwlock_unlock_write(&rwlock_); +} + +RWLock::ReaderLock::ReaderLock(RWLock& rwlock) : rwlock_(rwlock) {} +void RWLock::ReaderLock::Lock() { rwlock_.LockRead(); } +bool RWLock::ReaderLock::TryLock() { return rwlock_.TryLockRead(); } +void RWLock::ReaderLock::Unlock() { rwlock_.UnlockRead(); } + +RWLock::WriterLock::WriterLock(RWLock& rwlock) : rwlock_(rwlock) {} +void RWLock::WriterLock::Lock() { rwlock_.LockWrite(); } +bool RWLock::WriterLock::TryLock() { return rwlock_.TryLockWrite(); } +void RWLock::WriterLock::Unlock() { rwlock_.UnlockWrite(); } + +RWLock::ReaderLock& RWLock::GetReaderLock() { + return reader_lock_; +} +RWLock::WriterLock& RWLock::GetWriterLock() { + return writer_lock_; +} + +} // namespace base +} // namespace embb + + + + diff --git a/base_cpp/src/shared_mutex.cc b/base_cpp/src/shared_mutex.cc deleted file mode 100644 index 63f6978..0000000 --- a/base_cpp/src/shared_mutex.cc +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2014-2015, Siemens AG. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -namespace embb { -namespace base { - -SharedMutex::SharedMutex() - : shared_mutex_() { - embb_shared_mutex_init(&shared_mutex_); -} - -SharedMutex::~SharedMutex() { - embb_shared_mutex_destroy(&shared_mutex_); -} - -void SharedMutex::Lock() { - embb_shared_mutex_lock(&shared_mutex_); -} - -bool SharedMutex::TryLock() { - int result = embb_shared_mutex_try_lock(&shared_mutex_); - return result == EMBB_SUCCESS; -} - -void SharedMutex::Unlock() { - embb_shared_mutex_unlock(&shared_mutex_); -} - -void SharedMutex::LockShared() { - embb_shared_mutex_lock_shared(&shared_mutex_); -} - -bool SharedMutex::TryLockShared() { - int result = embb_shared_mutex_try_lock_shared(&shared_mutex_); - return result == EMBB_SUCCESS; -} - -void SharedMutex::UnlockShared() { - embb_shared_mutex_unlock_shared(&shared_mutex_); -} - -} // namespace base -} // namespace embb - - - - diff --git a/base_cpp/test/main.cc b/base_cpp/test/main.cc index ce56da7..f25e976 100644 --- a/base_cpp/test/main.cc +++ b/base_cpp/test/main.cc @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include @@ -46,7 +46,7 @@ using embb::base::test::ThreadSpecificStorageTest; using embb::base::test::AtomicTest; using embb::base::test::MemoryAllocationTest; using embb::base::test::ThreadTest; -using embb::base::test::SharedMutexTest; +using embb::base::test::RWLockTest; PT_MAIN("Base C++") { unsigned int max_threads = @@ -60,7 +60,7 @@ PT_MAIN("Base C++") { PT_RUN(AtomicTest); PT_RUN(MemoryAllocationTest); PT_RUN(ThreadTest); - PT_RUN(SharedMutexTest); + PT_RUN(RWLockTest); PT_EXPECT(embb_get_bytes_allocated() == 0); } diff --git a/base_cpp/test/rwlock_test.cc b/base_cpp/test/rwlock_test.cc new file mode 100644 index 0000000..088691b --- /dev/null +++ b/base_cpp/test/rwlock_test.cc @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014-2015, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +namespace embb { +namespace base { +namespace test { + +RWLockTest::RWLockTest() + : counter_(0), + num_threads_(partest::TestSuite::GetDefaultNumThreads()), + num_iterations_(partest::TestSuite::GetDefaultNumIterations()) { + CreateUnit("Shared read") + .Add(&RWLockTest::TestSharedRead_ThreadMethod, this, + num_threads_, num_iterations_); + CreateUnit("Exclusive write") + .Pre(&RWLockTest::TestExclusiveWrite_Pre, this) + .Add(&RWLockTest::TestExclusiveWrite_ReaderMethod, this, + num_threads_, num_iterations_) + .Add(&RWLockTest::TestExclusiveWrite_WriterMethod, this, + num_threads_, num_iterations_) + .Post(&RWLockTest::TestExclusiveWrite_Post, this); +} + +void RWLockTest::TestSharedRead_ThreadMethod() { + UniqueLock lock(rwlock_.GetReaderLock(), + embb::base::try_lock); + PT_ASSERT_EQ_MSG(lock.OwnsLock(), true, "Failed to lock for reading."); + + int spin = 10000; + while (--spin != 0); +} + +void RWLockTest::TestExclusiveWrite_Pre() { + counter_ = 0; +} + +void RWLockTest::TestExclusiveWrite_ReaderMethod() { + // Just add some contention + UniqueLock lock(rwlock_.GetReaderLock(), + embb::base::try_lock); + + int spin = 10000; + while (--spin != 0); +} + +void RWLockTest::TestExclusiveWrite_WriterMethod() { + UniqueLock lock(rwlock_.GetWriterLock()); + + ++counter_; +} + +void RWLockTest::TestExclusiveWrite_Post() { + PT_ASSERT_EQ_MSG(counter_, num_iterations_ * num_threads_, + "Counter value is inconsistent."); +} + +} // namespace test +} // namespace base +} // namespace embb diff --git a/base_cpp/test/rwlock_test.h b/base_cpp/test/rwlock_test.h new file mode 100644 index 0000000..47b10e4 --- /dev/null +++ b/base_cpp/test/rwlock_test.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014-2015, Siemens AG. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BASE_CPP_TEST_RWLOCK_TEST_H_ +#define BASE_CPP_TEST_RWLOCK_TEST_H_ + +#include +#include +#include + + +namespace embb { +namespace base { +namespace test { + +class RWLockTest : public partest::TestCase { + public: + RWLockTest(); + + private: + void TestSharedRead_Pre(); + void TestSharedRead_ThreadMethod(); + void TestSharedRead_Post(); + + void TestExclusiveWrite_Pre(); + void TestExclusiveWrite_ReaderMethod(); + void TestExclusiveWrite_WriterMethod(); + void TestExclusiveWrite_Post(); + + RWLock rwlock_; + size_t counter_; + size_t num_threads_; + size_t num_iterations_; +}; + +} // namespace test +} // namespace base +} // namespace embb + +#endif // BASE_CPP_TEST_RWLOCK_TEST_H_ diff --git a/base_cpp/test/shared_mutex_test.cc b/base_cpp/test/shared_mutex_test.cc deleted file mode 100644 index b4524a7..0000000 --- a/base_cpp/test/shared_mutex_test.cc +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2014-2015, Siemens AG. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -namespace embb { -namespace base { -namespace test { - -SharedMutexTest::SharedMutexTest() - : shared_mutex_(), - counter_(0), - num_threads_(partest::TestSuite::GetDefaultNumThreads()), - num_iterations_(partest::TestSuite::GetDefaultNumIterations()) { - CreateUnit("Shared read") - .Add(&SharedMutexTest::TestSharedRead_ThreadMethod, this, - num_threads_, num_iterations_); - CreateUnit("Exclusive write") - .Pre(&SharedMutexTest::TestExclusiveWrite_Pre, this) - .Add(&SharedMutexTest::TestExclusiveWrite_ReaderMethod, this, - num_threads_ / 2, num_iterations_) - .Add(&SharedMutexTest::TestExclusiveWrite_WriterMethod, this, - num_threads_ / 2, num_iterations_) - .Post(&SharedMutexTest::TestExclusiveWrite_Post, this); - CreateUnit("SharedLock") - .Add(&SharedMutexTest::TestSharedLock_ThreadMethod, this, - num_threads_, num_iterations_); -} - -void SharedMutexTest::TestSharedRead_ThreadMethod() { - SharedLock lock(shared_mutex_, embb::base::try_lock); - PT_ASSERT_EQ_MSG(lock.OwnsLock(), true, "Failed to lock for reading."); - - int spin = 10000; - while (--spin != 0); -} - -void SharedMutexTest::TestExclusiveWrite_Pre() { - counter_ = 0; -} - -void SharedMutexTest::TestExclusiveWrite_ReaderMethod() { - // Just add some contention - SharedLock lock(shared_mutex_, embb::base::try_lock); - - if (lock.OwnsLock()) { - int spin = 10000; - while (--spin != 0); - } -} - -void SharedMutexTest::TestExclusiveWrite_WriterMethod() { - UniqueLock lock(shared_mutex_); - - ++counter_; -} - -void SharedMutexTest::TestExclusiveWrite_Post() { - PT_ASSERT_EQ_MSG(counter_, num_iterations_ * (num_threads_ / 2), - "Counter value is inconsistent."); -} - -void SharedMutexTest::TestSharedLock_ThreadMethod() { - // Test basic usage - { - SharedLock<> lock(shared_mutex_); - PT_EXPECT_EQ(lock.OwnsLock(), true); - - lock.UnlockShared(); - PT_EXPECT_EQ(lock.OwnsLock(), false); - - lock.LockShared(); - PT_EXPECT_EQ(lock.OwnsLock(), true); - - lock.UnlockShared(); - PT_EXPECT_EQ(lock.OwnsLock(), false); - - bool locked_after_try = lock.TryLockShared(); - PT_EXPECT_EQ(locked_after_try, true); - PT_EXPECT_EQ(lock.OwnsLock(), true); - - lock.Release()->UnlockShared(); - PT_EXPECT_EQ(lock.OwnsLock(), false); - } - - // Test deferred lock construction - { - SharedLock<> lock(shared_mutex_, embb::base::defer_lock); - PT_EXPECT_EQ(lock.OwnsLock(), false); - } - - // Test try-lock construction - { - SharedLock<> lock(shared_mutex_, embb::base::try_lock); - PT_EXPECT_EQ(lock.OwnsLock(), true); - } - - // Test adopt lock construction - { - shared_mutex_.LockShared(); - SharedLock<> lock(shared_mutex_, embb::base::adopt_lock); - PT_EXPECT_EQ(lock.OwnsLock(), true); - } - - // Test lock swapping - { - SharedMutex another_mutex; - SharedLock<> lock1(another_mutex); - PT_EXPECT_EQ(lock1.OwnsLock(), true); - - { - SharedLock<> lock2(shared_mutex_); - PT_EXPECT_EQ(lock2.OwnsLock(), true); - - lock1.Swap(lock2); - PT_EXPECT_EQ(lock1.OwnsLock(), true); - PT_EXPECT_EQ(lock2.OwnsLock(), true); - } - - // At this point, lock2 was destroyed and "another_mutex" must be unlocked - SharedLock<> lock3(another_mutex, embb::base::try_lock); - PT_EXPECT_EQ(lock3.OwnsLock(), true); - - // But lock1 must still be locking "shared_mutex_" - PT_EXPECT_EQ(lock1.OwnsLock(), true); - lock1.Release()->UnlockShared(); - PT_EXPECT_EQ(lock1.OwnsLock(), false); - } -} - -} // namespace test -} // namespace base -} // namespace embb diff --git a/base_cpp/test/shared_mutex_test.h b/base_cpp/test/shared_mutex_test.h deleted file mode 100644 index 7b6df22..0000000 --- a/base_cpp/test/shared_mutex_test.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2014-2015, Siemens AG. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef BASE_CPP_TEST_SHARED_MUTEX_TEST_H_ -#define BASE_CPP_TEST_SHARED_MUTEX_TEST_H_ - -#include -#include -#include - - -namespace embb { -namespace base { -namespace test { - -class SharedMutexTest : public partest::TestCase { - public: - SharedMutexTest(); - - private: - void TestSharedRead_ThreadMethod(); - - void TestExclusiveWrite_Pre(); - void TestExclusiveWrite_ReaderMethod(); - void TestExclusiveWrite_WriterMethod(); - void TestExclusiveWrite_Post(); - - void TestSharedLock_ThreadMethod(); - - SharedMutex shared_mutex_; - size_t counter_; - size_t num_threads_; - size_t num_iterations_; -}; - -} // namespace test -} // namespace base -} // namespace embb - -#endif // BASE_CPP_TEST_SHARED_MUTEX_TEST_H_ -- libgit2 0.26.0