Commit b88f17ae by bernhard-gatzhammer

Revert "* Implemented readers-writers lock, added Doxygen documentation and tests."

This reverts commit a257320c.
parent b30e8a25
......@@ -55,6 +55,5 @@
#include <embb/base/c/thread.h>
#include <embb/base/c/thread_specific_storage.h>
#include <embb/base/c/time.h>
#include <embb/base/c/rwlock.h>
#endif /* EMBB_BASE_C_BASE_H_ */
......@@ -66,7 +66,6 @@ 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_rwlock_t;
#define EMBB_DURATION_MIN_NANOSECONDS 1000
......@@ -91,7 +90,6 @@ 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_rwlock_t;
#define EMBB_DURATION_MIN_NANOSECONDS 1
......
/*
* 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 <embb/base/c/internal/platform.h>
#include <embb/base/c/errors.h>
#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_
/*
* 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 <embb/base/c/rwlock.h>
#include <assert.h>
#include <embb/base/c/internal/unused.h>
#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 */
......@@ -35,7 +35,6 @@
#include <condition_var_test.h>
#include <thread_test.h>
#include <thread_specific_storage_test.h>
#include <rwlock_test.h>
#include <embb/base/c/thread.h>
#include <embb/base/c/log.h>
#include <iostream>
......@@ -52,7 +51,6 @@ using embb::base::test::CoreSetTest;
using embb::base::test::ConditionVarTest;
using embb::base::test::ThreadTest;
using embb::base::test::ThreadSpecificStorageTest;
using embb::base::test::RWLockTest;
PT_MAIN("Base C") {
embb_log_set_log_level(EMBB_LOG_LEVEL_WARNING);
......@@ -70,7 +68,6 @@ PT_MAIN("Base C") {
PT_RUN(ConditionVarTest);
PT_RUN(ThreadTest);
PT_RUN(ThreadSpecificStorageTest);
PT_RUN(RWLockTest);
PT_EXPECT(embb_get_bytes_allocated() == 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 <rwlock_test.h>
#include <embb/base/c/errors.h>
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
/*
* 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 <partest/partest.h>
#include <embb/base/c/internal/platform.h>
#include <embb/base/c/rwlock.h>
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_
......@@ -59,6 +59,5 @@
#include <embb/base/thread.h>
#include <embb/base/thread_specific_storage.h>
#include <embb/base/time.h>
#include <embb/base/rwlock.h>
#endif // EMBB_BASE_BASE_H_
......@@ -44,7 +44,6 @@ typedef embb_thread_t ThreadType;
typedef DWORD IDType;
typedef embb_mutex_t MutexType;
typedef embb_condition_t ConditionVariableType;
typedef embb_rwlock_t RWLockType;
} // namespace internal
} // namespace base
......@@ -60,7 +59,6 @@ typedef embb_thread_t ThreadType;
typedef embb_thread_id_t IDType;
typedef embb_mutex_t MutexType;
typedef embb_condition_t ConditionVariableType;
typedef embb_rwlock_t RWLockType;
} // namespace internal
} // namespace base
......
/*
* 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 <embb/base/internal/platform.h>
#include <embb/base/exceptions.h>
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_
/*
* 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 <embb/base/rwlock.h>
#include <embb/base/c/rwlock.h>
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
......@@ -34,7 +34,6 @@
#include <thread_specific_storage_test.h>
#include <atomic_test.h>
#include <memory_allocation_test.h>
#include <rwlock_test.h>
#include <embb/base/c/memory_allocation.h>
......@@ -46,7 +45,6 @@ using embb::base::test::ThreadSpecificStorageTest;
using embb::base::test::AtomicTest;
using embb::base::test::MemoryAllocationTest;
using embb::base::test::ThreadTest;
using embb::base::test::RWLockTest;
PT_MAIN("Base C++") {
unsigned int max_threads =
......@@ -60,7 +58,6 @@ PT_MAIN("Base C++") {
PT_RUN(AtomicTest);
PT_RUN(MemoryAllocationTest);
PT_RUN(ThreadTest);
PT_RUN(RWLockTest);
PT_EXPECT(embb_get_bytes_allocated() == 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 <rwlock_test.h>
#include <embb/base/c/errors.h>
#include <embb/base/mutex.h>
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<embb::base::RWLock::ReaderLock> 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<embb::base::RWLock::ReaderLock> lock(rwlock_.GetReaderLock(),
embb::base::try_lock);
int spin = 10000;
while (--spin != 0);
}
void RWLockTest::TestExclusiveWrite_WriterMethod() {
UniqueLock<embb::base::RWLock::WriterLock> 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
/*
* 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 <partest/partest.h>
#include <embb/base/c/internal/platform.h>
#include <embb/base/rwlock.h>
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_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment