Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
FORMUS3IC_LAS3
/
embb
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
ae2f1813
authored
May 13, 2015
by
Danila Klimenko
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Readers-writers lock: updated interface to match C++14 standard
parent
a257320c
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
653 additions
and
396 deletions
+653
-396
base_c/include/embb/base/c/base.h
+1
-1
base_c/include/embb/base/c/internal/platform.h
+2
-2
base_c/include/embb/base/c/shared_mutex.h
+71
-68
base_c/src/shared_mutex.c
+49
-49
base_c/test/main.cc
+3
-3
base_c/test/shared_mutex_test.cc
+31
-31
base_c/test/shared_mutex_test.h
+7
-7
base_cpp/include/embb/base/base.h
+1
-1
base_cpp/include/embb/base/internal/platform.h
+2
-2
base_cpp/include/embb/base/internal/shared_mutex-inl.h
+116
-0
base_cpp/include/embb/base/shared_mutex.h
+180
-86
base_cpp/src/shared_mutex.cc
+20
-48
base_cpp/test/main.cc
+3
-3
base_cpp/test/rwlock_test.cc
+0
-86
base_cpp/test/shared_mutex_test.cc
+158
-0
base_cpp/test/shared_mutex_test.h
+9
-9
No files found.
base_c/include/embb/base/c/base.h
View file @
ae2f1813
...
@@ -55,6 +55,6 @@
...
@@ -55,6 +55,6 @@
#include <embb/base/c/thread.h>
#include <embb/base/c/thread.h>
#include <embb/base/c/thread_specific_storage.h>
#include <embb/base/c/thread_specific_storage.h>
#include <embb/base/c/time.h>
#include <embb/base/c/time.h>
#include <embb/base/c/
rwlock
.h>
#include <embb/base/c/
shared_mutex
.h>
#endif
/* EMBB_BASE_C_BASE_H_ */
#endif
/* EMBB_BASE_C_BASE_H_ */
base_c/include/embb/base/c/internal/platform.h
View file @
ae2f1813
...
@@ -66,7 +66,7 @@ typedef struct embb_thread_t {
...
@@ -66,7 +66,7 @@ typedef struct embb_thread_t {
typedef
DWORD
embb_thread_id_t
;
typedef
DWORD
embb_thread_id_t
;
typedef
CRITICAL_SECTION
embb_mutex_t
;
typedef
CRITICAL_SECTION
embb_mutex_t
;
typedef
CONDITION_VARIABLE
embb_condition_t
;
typedef
CONDITION_VARIABLE
embb_condition_t
;
typedef
SRWLOCK
embb_
rwlock
_t
;
typedef
SRWLOCK
embb_
shared_mutex
_t
;
#define EMBB_DURATION_MIN_NANOSECONDS 1000
#define EMBB_DURATION_MIN_NANOSECONDS 1000
...
@@ -91,7 +91,7 @@ typedef struct embb_thread_t {
...
@@ -91,7 +91,7 @@ typedef struct embb_thread_t {
typedef
pthread_t
embb_thread_id_t
;
typedef
pthread_t
embb_thread_id_t
;
typedef
pthread_mutex_t
embb_mutex_t
;
typedef
pthread_mutex_t
embb_mutex_t
;
typedef
pthread_cond_t
embb_condition_t
;
typedef
pthread_cond_t
embb_condition_t
;
typedef
pthread_rwlock_t
embb_
rwlock
_t
;
typedef
pthread_rwlock_t
embb_
shared_mutex
_t
;
#define EMBB_DURATION_MIN_NANOSECONDS 1
#define EMBB_DURATION_MIN_NANOSECONDS 1
...
...
base_c/include/embb/base/c/
rwlock
.h
→
base_c/include/embb/base/c/
shared_mutex
.h
View file @
ae2f1813
...
@@ -24,16 +24,19 @@
...
@@ -24,16 +24,19 @@
* POSSIBILITY OF SUCH DAMAGE.
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
#ifndef EMBB_BASE_C_
RWLOCK
_H_
#ifndef EMBB_BASE_C_
SHARED_MUTEX
_H_
#define EMBB_BASE_C_
RWLOCK
_H_
#define EMBB_BASE_C_
SHARED_MUTEX
_H_
/**
/**
* \defgroup C_BASE_
RWLOCK Readers-Writers Lock
* \defgroup C_BASE_
SHARED_MUTEX Shared mutex
*
*
* Shared
-read/exclusive-write lock
for thread synchronization
* Shared
mutexes
for thread synchronization
*
*
* Provides an abstraction from platform-specific readers-writers lock
* Provides an abstraction from platform-specific shared mutex implementations.
* 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
* \ingroup C_BASE
* \{
* \{
...
@@ -48,139 +51,139 @@ extern "C" {
...
@@ -48,139 +51,139 @@ extern "C" {
#ifdef DOXYGEN
#ifdef DOXYGEN
/**
/**
* Opaque type representing a
n rwlock
.
* Opaque type representing a
shared mutex
.
*/
*/
typedef
opaque_type
embb_
rwlock
_t
;
typedef
opaque_type
embb_
shared_mutex
_t
;
#endif // DOXYGEN
#endif // DOXYGEN
/**
/**
* Initializes a
n rwlock
* Initializes a
shared mutex
*
*
* \post \c
rwlock
is initialized
* \post \c
shared_mutex
is initialized
*
*
* \param
rwlock Pointer to rwlock
* \param
shared_mutex Pointer to shared mutex
* \return EMBB_SUCCESS if
rwlock
could be initialized \n
* \return EMBB_SUCCESS if
shared mutex
could be initialized \n
* EMBB_ERROR otherwise
* EMBB_ERROR otherwise
*
*
* \memory (Potentially) allocates dynamic memory
* \memory (Potentially) allocates dynamic memory
*
*
* \notthreadsafe
* \notthreadsafe
*
*
* \see embb_
rwlock
_destroy()
* \see embb_
shared_mutex
_destroy()
*/
*/
int
embb_
rwlock_init
(
embb_rwlock_t
*
rwlock
);
int
embb_
shared_mutex_init
(
embb_shared_mutex_t
*
shared_mutex
);
/**
/**
* Waits until the
rwlock can be locked for read
ing and locks it.
* Waits until the
shared mutex can be locked for writ
ing and locks it.
*
*
* \pre \c
rwlock
is initialized and not locked by the current thread.
* \pre \c
shared_mutex
is initialized and not locked by the current thread.
* \post If successful, \c
rwlock is locked for read
ing.
* \post If successful, \c
shared_mutex is locked for writ
ing.
*
*
* \param
rwlock Pointer to rwlock
* \param
shared_mutex Pointer to shared mutex
* \return EMBB_SUCCESS if
rwlock could be locked for read
ing \n
* \return EMBB_SUCCESS if
shared_mutex could be locked for writ
ing \n
* EMBB_ERROR otherwise
* EMBB_ERROR otherwise
*
*
* \threadsafe
* \threadsafe
*
*
* \see embb_
rwlock_try_lock_read(), embb_rwlock_unlock_read
()
* \see embb_
shared_mutex_try_lock(), embb_shared_mutex_unlock
()
*/
*/
int
embb_
rwlock_lock_read
(
embb_rwlock_t
*
rwlock
);
int
embb_
shared_mutex_lock
(
embb_shared_mutex_t
*
shared_mutex
);
/**
/**
*
Waits until the rwlock can be locked for writing and locks it
.
*
Tries to lock the shared mutex for writing and returns immediately
.
*
*
* \pre \c
rwlock is initialized and not locked by the current thread.
* \pre \c
shared_mutex is initialized
* \post If successful, \c
rwlock is locked for writing.
* \post If successful, \c
shared_mutex is locked for writing
*
*
* \param rwlock Pointer to rwlock
* \param shared_mutex Pointer to shared mutex
* \return EMBB_SUCCESS if rwlock could be locked for writing \n
* \return EMBB_SUCCESS if shared_mutex could be locked for writing \n
* EMBB_ERROR otherwise
* EMBB_BUSY if shared_mutex could not be locked for writing \n
* EMBB_ERROR if an error occurred
*
*
* \threadsafe
* \threadsafe
*
*
* \see embb_
rwlock_try_lock_write(), embb_rwlock_unlock_write
()
* \see embb_
shared_mutex_lock(), embb_shared_mutex_unlock
()
*/
*/
int
embb_
rwlock_lock_write
(
embb_rwlock_t
*
rwlock
);
int
embb_
shared_mutex_try_lock
(
embb_shared_mutex_t
*
shared_mutex
);
/**
/**
*
Tries to lock the rwlock for reading and returns immediately
.
*
Unlocks the shared mutex locked for writing
.
*
*
* \pre \c
rwlock is initialized
* \pre \c
shared_mutex has been locked for writing by the current thread.
* \post If successful, \c
rwlock is locked for reading
* \post If successful, \c
shared_mutex is unlocked.
*
*
* \param rwlock Pointer to rwlock
* \param shared_mutex Pointer to shared mutex
* \return EMBB_SUCCESS if rwlock could be locked for reading \n
* \return EMBB_SUCCESS if the operation was successful \n
* EMBB_BUSY if rwlock could not be locked for reading \n
* EMBB_ERROR otherwise
* EMBB_ERROR if an error occurred
*
*
* \threadsafe
* \threadsafe
*
*
* \see embb_
rwlock_lock_read(), embb_rwlock_unlock_read
()
* \see embb_
shared_mutex_lock(), embb_shared_mutex_try_lock
()
*/
*/
int
embb_
rwlock_try_lock_read
(
embb_rwlock_t
*
rwlock
);
int
embb_
shared_mutex_unlock
(
embb_shared_mutex_t
*
shared_mutex
);
/**
/**
*
Tries to lock the rwlock for writing and returns immediately
.
*
Waits until the shared mutex can be locked for reading and locks it
.
*
*
* \pre \c
rwlock is initialized
* \pre \c
shared_mutex is initialized and not locked by the current thread.
* \post If successful, \c
rwlock is locked for writing
* \post If successful, \c
shared_mutex is locked for reading.
*
*
* \param rwlock Pointer to rwlock
* \param shared_mutex Pointer to shared mutex
* \return EMBB_SUCCESS if rwlock could be locked for writing \n
* \return EMBB_SUCCESS if shared_mutex could be locked for reading \n
* EMBB_BUSY if rwlock could not be locked for writing \n
* EMBB_ERROR otherwise
* EMBB_ERROR if an error occurred
*
*
* \threadsafe
* \threadsafe
*
*
* \see embb_
rwlock_lock_write(), embb_rwlock_unlock_write
()
* \see embb_
shared_mutex_try_lock_shared(), embb_shared_mutex_unlock_shared
()
*/
*/
int
embb_
rwlock_try_lock_write
(
embb_rwlock_t
*
rwlock
);
int
embb_
shared_mutex_lock_shared
(
embb_shared_mutex_t
*
shared_mutex
);
/**
/**
*
Unlocks an rwlock locked for reading
.
*
Tries to lock the shared mutex for reading and returns immediately
.
*
*
* \pre \c
rwlock has been locked for reading by the current thread.
* \pre \c
shared_mutex is initialized
* \post If successful, \c
rwlock is unlocked.
* \post If successful, \c
shared_mutex is locked for reading
*
*
* \param rwlock Pointer to rwlock
* \param shared_mutex Pointer to shared mutex
* \return EMBB_SUCCESS if the operation was successful \n
* \return EMBB_SUCCESS if shared_mutex could be locked for reading \n
* EMBB_ERROR otherwise
* EMBB_BUSY if shared_mutex could not be locked for reading \n
* EMBB_ERROR if an error occurred
*
*
* \threadsafe
* \threadsafe
*
*
* \see embb_
rwlock_lock_read(), embb_rwlock_try_lock_rea
d()
* \see embb_
shared_mutex_lock_shared(), embb_shared_mutex_unlock_share
d()
*/
*/
int
embb_
rwlock_unlock_read
(
embb_rwlock_t
*
rwlock
);
int
embb_
shared_mutex_try_lock_shared
(
embb_shared_mutex_t
*
shared_mutex
);
/**
/**
* Unlocks
an rwlock locked for writ
ing.
* Unlocks
the shared mutex locked for read
ing.
*
*
* \pre \c
rwlock has been locked for writ
ing by the current thread.
* \pre \c
shared_mutex has been locked for read
ing by the current thread.
* \post If successful, \c
rwlock
is unlocked.
* \post If successful, \c
shared_mutex
is unlocked.
*
*
* \param
rwlock Pointer to rwlock
* \param
shared_mutex Pointer to shared mutex
* \return EMBB_SUCCESS if the operation was successful \n
* \return EMBB_SUCCESS if the operation was successful \n
* EMBB_ERROR otherwise
* EMBB_ERROR otherwise
*
*
* \threadsafe
* \threadsafe
*
*
* \see embb_
rwlock_lock_write(), embb_rwlock_try_lock_write
()
* \see embb_
shared_mutex_lock_shared(), embb_shared_mutex_try_lock_shared
()
*/
*/
int
embb_
rwlock_unlock_write
(
embb_rwlock_t
*
rwlock
);
int
embb_
shared_mutex_unlock_shared
(
embb_shared_mutex_t
*
shared_mutex
);
/**
/**
* Destroys
an rwlock
and frees its resources.
* Destroys
the shared mutex
and frees its resources.
*
*
* \pre \c
rwlock
has been initialized
* \pre \c
shared_mutex
has been initialized
* \post \c
rwlock
is uninitialized
* \post \c
shared_mutex
is uninitialized
*
*
* \param
rwlock Pointer to rwlock
* \param
shared_mutex Pointer to shared mutex
*
*
* \notthreadsafe
* \notthreadsafe
*
*
* \see embb_
rwlock
_init()
* \see embb_
shared_mutex
_init()
*/
*/
void
embb_
rwlock_destroy
(
embb_rwlock_t
*
rwlock
);
void
embb_
shared_mutex_destroy
(
embb_shared_mutex_t
*
shared_mutex
);
#ifdef __cplusplus
#ifdef __cplusplus
}
// Close extern "C"
}
// Close extern "C"
...
@@ -190,4 +193,4 @@ void embb_rwlock_destroy(embb_rwlock_t* rwlock);
...
@@ -190,4 +193,4 @@ void embb_rwlock_destroy(embb_rwlock_t* rwlock);
* \}
* \}
*/
*/
#endif // EMBB_BASE_C_
RWLOCK
_H_
#endif // EMBB_BASE_C_
SHARED_MUTEX
_H_
base_c/src/
rwlock
.c
→
base_c/src/
shared_mutex
.c
View file @
ae2f1813
...
@@ -24,87 +24,79 @@
...
@@ -24,87 +24,79 @@
* POSSIBILITY OF SUCH DAMAGE.
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
#include <embb/base/c/
rwlock
.h>
#include <embb/base/c/
shared_mutex
.h>
#include <assert.h>
#include <assert.h>
#include <embb/base/c/internal/unused.h>
#include <embb/base/c/internal/unused.h>
#ifdef EMBB_PLATFORM_THREADING_WINTHREADS
#ifdef EMBB_PLATFORM_THREADING_WINTHREADS
int
embb_
rwlock_init
(
embb_rwlock_t
*
rwlock
)
{
int
embb_
shared_mutex_init
(
embb_shared_mutex_t
*
shared_mutex
)
{
InitializeSRWLock
(
rwlock
);
InitializeSRWLock
(
shared_mutex
);
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_
rwlock_lock_read
(
embb_rwlock_t
*
rwlock
)
{
int
embb_
shared_mutex_lock
(
embb_shared_mutex_t
*
shared_mutex
)
{
AcquireSRWLock
Shared
(
rwlock
);
AcquireSRWLock
Exclusive
(
shared_mutex
);
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_rwlock_lock_write
(
embb_rwlock_t
*
rwlock
)
{
int
embb_shared_mutex_try_lock
(
embb_shared_mutex_t
*
shared_mutex
)
{
AcquireSRWLockExclusive
(
rwlock
);
BOOLEAN
success
;
success
=
TryAcquireSRWLockExclusive
(
shared_mutex
);
if
(
success
==
FALSE
)
return
EMBB_ERROR
;
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_rwlock_try_lock_read
(
embb_rwlock_t
*
rwlock
)
{
int
embb_shared_mutex_unlock
(
embb_shared_mutex_t
*
shared_mutex
)
{
BOOLEAN
success
;
ReleaseSRWLockExclusive
(
shared_mutex
);
success
=
TryAcquireSRWLockShared
(
rwlock
);
if
(
success
==
FALSE
)
return
EMBB_ERROR
;
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_rwlock_try_lock_write
(
embb_rwlock_t
*
rwlock
)
{
int
embb_shared_mutex_lock_shared
(
embb_shared_mutex_t
*
shared_mutex
)
{
BOOLEAN
success
;
AcquireSRWLockShared
(
shared_mutex
);
success
=
TryAcquireSRWLockExclusive
(
rwlock
);
if
(
success
==
FALSE
)
return
EMBB_ERROR
;
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_rwlock_unlock_read
(
embb_rwlock_t
*
rwlock
)
{
int
embb_shared_mutex_try_lock_shared
(
embb_shared_mutex_t
*
shared_mutex
)
{
ReleaseSRWLockShared
(
rwlock
);
BOOLEAN
success
;
success
=
TryAcquireSRWLockShared
(
shared_mutex
);
if
(
success
==
FALSE
)
return
EMBB_ERROR
;
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_
rwlock_unlock_write
(
embb_rwlock_t
*
rwlock
)
{
int
embb_
shared_mutex_unlock_shared
(
embb_shared_mutex_t
*
shared_mutex
)
{
ReleaseSRWLock
Exclusive
(
rwlock
);
ReleaseSRWLock
Shared
(
shared_mutex
);
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
void
embb_
rwlock_destroy
(
embb_rwlock_t
*
rwlock
)
{
void
embb_
shared_mutex_destroy
(
embb_shared_mutex_t
*
shared_mutex
)
{
// Quoting MSDN: "SRW locks do not need to be explicitly destroyed".
// Quoting MSDN: "SRW locks do not need to be explicitly destroyed".
EMBB_UNUSED
(
rwlock
);
EMBB_UNUSED
(
shared_mutex
);
}
}
#endif
/* EMBB_PLATFORM_THREADING_WINTHREADS */
#endif
/* EMBB_PLATFORM_THREADING_WINTHREADS */
#ifdef EMBB_PLATFORM_THREADING_POSIXTHREADS
#ifdef EMBB_PLATFORM_THREADING_POSIXTHREADS
int
embb_
rwlock_init
(
embb_rwlock_t
*
rwlock
)
{
int
embb_
shared_mutex_init
(
embb_shared_mutex_t
*
shared_mutex
)
{
int
result
=
pthread_rwlock_init
(
rwlock
,
NULL
);
int
result
=
pthread_rwlock_init
(
shared_mutex
,
NULL
);
if
(
result
!=
0
)
{
if
(
result
!=
0
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_
rwlock_lock_read
(
embb_rwlock_t
*
rwlock
)
{
int
embb_
shared_mutex_lock
(
embb_shared_mutex_t
*
shared_mutex
)
{
int
result
=
pthread_rwlock_
rdlock
(
rwlock
);
int
result
=
pthread_rwlock_
wrlock
(
shared_mutex
);
if
(
result
!=
0
)
{
if
(
result
!=
0
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_rwlock_lock_write
(
embb_rwlock_t
*
rwlock
)
{
int
embb_shared_mutex_try_lock
(
embb_shared_mutex_t
*
shared_mutex
)
{
int
result
=
pthread_rwlock_wrlock
(
rwlock
);
int
result
=
pthread_rwlock_trywrlock
(
shared_mutex
);
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
)
{
if
(
result
==
0
)
{
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
...
@@ -114,35 +106,43 @@ int embb_rwlock_try_lock_read(embb_rwlock_t* rwlock) {
...
@@ -114,35 +106,43 @@ int embb_rwlock_try_lock_read(embb_rwlock_t* rwlock) {
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
int
embb_rwlock_try_lock_write
(
embb_rwlock_t
*
rwlock
)
{
int
embb_shared_mutex_unlock
(
embb_shared_mutex_t
*
shared_mutex
)
{
int
result
=
pthread_rwlock_trywrlock
(
rwlock
);
int
result
=
pthread_rwlock_unlock
(
shared_mutex
);
if
(
result
==
0
)
{
if
(
result
!=
0
)
{
return
EMBB_SUCCESS
;
}
if
(
result
==
EBUSY
)
{
return
EMBB_BUSY
;
}
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
return
EMBB_SUCCESS
;
}
}
int
embb_
rwlock_unlock_read
(
embb_rwlock_t
*
rwlock
)
{
int
embb_
shared_mutex_lock_shared
(
embb_shared_mutex_t
*
shared_mutex
)
{
int
result
=
pthread_rwlock_
unlock
(
rwlock
);
int
result
=
pthread_rwlock_
rdlock
(
shared_mutex
);
if
(
result
!=
0
)
{
if
(
result
!=
0
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_rwlock_unlock_write
(
embb_rwlock_t
*
rwlock
)
{
int
embb_shared_mutex_try_lock_shared
(
embb_shared_mutex_t
*
shared_mutex
)
{
int
result
=
pthread_rwlock_unlock
(
rwlock
);
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
)
{
if
(
result
!=
0
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
void
embb_
rwlock_destroy
(
embb_rwlock_t
*
rwlock
)
{
void
embb_
shared_mutex_destroy
(
embb_shared_mutex_t
*
shared_mutex
)
{
pthread_rwlock_destroy
(
rwlock
);
pthread_rwlock_destroy
(
shared_mutex
);
}
}
#endif
/* EMBB_PLATFORM_THREADING_POSIXTHREADS */
#endif
/* EMBB_PLATFORM_THREADING_POSIXTHREADS */
base_c/test/main.cc
View file @
ae2f1813
...
@@ -35,7 +35,7 @@
...
@@ -35,7 +35,7 @@
#include <condition_var_test.h>
#include <condition_var_test.h>
#include <thread_test.h>
#include <thread_test.h>
#include <thread_specific_storage_test.h>
#include <thread_specific_storage_test.h>
#include <
rwlock
_test.h>
#include <
shared_mutex
_test.h>
#include <embb/base/c/thread.h>
#include <embb/base/c/thread.h>
#include <embb/base/c/log.h>
#include <embb/base/c/log.h>
#include <iostream>
#include <iostream>
...
@@ -52,7 +52,7 @@ using embb::base::test::CoreSetTest;
...
@@ -52,7 +52,7 @@ using embb::base::test::CoreSetTest;
using
embb
::
base
::
test
::
ConditionVarTest
;
using
embb
::
base
::
test
::
ConditionVarTest
;
using
embb
::
base
::
test
::
ThreadTest
;
using
embb
::
base
::
test
::
ThreadTest
;
using
embb
::
base
::
test
::
ThreadSpecificStorageTest
;
using
embb
::
base
::
test
::
ThreadSpecificStorageTest
;
using
embb
::
base
::
test
::
RWLock
Test
;
using
embb
::
base
::
test
::
SharedMutex
Test
;
PT_MAIN
(
"Base C"
)
{
PT_MAIN
(
"Base C"
)
{
embb_log_set_log_level
(
EMBB_LOG_LEVEL_WARNING
);
embb_log_set_log_level
(
EMBB_LOG_LEVEL_WARNING
);
...
@@ -70,7 +70,7 @@ PT_MAIN("Base C") {
...
@@ -70,7 +70,7 @@ PT_MAIN("Base C") {
PT_RUN
(
ConditionVarTest
);
PT_RUN
(
ConditionVarTest
);
PT_RUN
(
ThreadTest
);
PT_RUN
(
ThreadTest
);
PT_RUN
(
ThreadSpecificStorageTest
);
PT_RUN
(
ThreadSpecificStorageTest
);
PT_RUN
(
RWLock
Test
);
PT_RUN
(
SharedMutex
Test
);
PT_EXPECT
(
embb_get_bytes_allocated
()
==
0
);
PT_EXPECT
(
embb_get_bytes_allocated
()
==
0
);
}
}
base_c/test/
rwlock
_test.cc
→
base_c/test/
shared_mutex
_test.cc
View file @
ae2f1813
...
@@ -24,85 +24,85 @@
...
@@ -24,85 +24,85 @@
* POSSIBILITY OF SUCH DAMAGE.
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
#include <
rwlock
_test.h>
#include <
shared_mutex
_test.h>
#include <embb/base/c/errors.h>
#include <embb/base/c/errors.h>
namespace
embb
{
namespace
embb
{
namespace
base
{
namespace
base
{
namespace
test
{
namespace
test
{
RWLockTest
::
RWLock
Test
()
SharedMutexTest
::
SharedMutex
Test
()
:
counter_
(
0
),
:
counter_
(
0
),
num_threads_
(
partest
::
TestSuite
::
GetDefaultNumThreads
()),
num_threads_
(
partest
::
TestSuite
::
GetDefaultNumThreads
()),
num_iterations_
(
partest
::
TestSuite
::
GetDefaultNumIterations
())
{
num_iterations_
(
partest
::
TestSuite
::
GetDefaultNumIterations
())
{
CreateUnit
(
"Shared read"
)
CreateUnit
(
"Shared read"
)
.
Pre
(
&
RWLock
Test
::
TestSharedRead_Pre
,
this
)
.
Pre
(
&
SharedMutex
Test
::
TestSharedRead_Pre
,
this
)
.
Add
(
&
RWLock
Test
::
TestSharedRead_ThreadMethod
,
this
,
.
Add
(
&
SharedMutex
Test
::
TestSharedRead_ThreadMethod
,
this
,
num_threads_
,
num_iterations_
)
num_threads_
,
num_iterations_
)
.
Post
(
&
RWLock
Test
::
TestSharedRead_Post
,
this
);
.
Post
(
&
SharedMutex
Test
::
TestSharedRead_Post
,
this
);
CreateUnit
(
"Exclusive write"
)
CreateUnit
(
"Exclusive write"
)
.
Pre
(
&
RWLock
Test
::
TestExclusiveWrite_Pre
,
this
)
.
Pre
(
&
SharedMutex
Test
::
TestExclusiveWrite_Pre
,
this
)
.
Add
(
&
RWLock
Test
::
TestExclusiveWrite_ReaderMethod
,
this
,
.
Add
(
&
SharedMutex
Test
::
TestExclusiveWrite_ReaderMethod
,
this
,
num_threads_
,
num_iterations_
)
num_threads_
/
2
,
num_iterations_
)
.
Add
(
&
RWLock
Test
::
TestExclusiveWrite_WriterMethod
,
this
,
.
Add
(
&
SharedMutex
Test
::
TestExclusiveWrite_WriterMethod
,
this
,
num_threads_
,
num_iterations_
)
num_threads_
/
2
,
num_iterations_
)
.
Post
(
&
RWLock
Test
::
TestExclusiveWrite_Post
,
this
);
.
Post
(
&
SharedMutex
Test
::
TestExclusiveWrite_Post
,
this
);
}
}
void
RWLock
Test
::
TestSharedRead_Pre
()
{
void
SharedMutex
Test
::
TestSharedRead_Pre
()
{
int
success
=
embb_
rwlock_init
(
&
rwlock
_
);
int
success
=
embb_
shared_mutex_init
(
&
shared_mutex
_
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to initialize
rwlock
."
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to initialize
shared mutex
."
);
}
}
void
RWLock
Test
::
TestSharedRead_ThreadMethod
()
{
void
SharedMutex
Test
::
TestSharedRead_ThreadMethod
()
{
int
success
=
embb_
rwlock_try_lock_read
(
&
rwlock
_
);
int
success
=
embb_
shared_mutex_try_lock_shared
(
&
shared_mutex
_
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to lock for reading."
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to lock for reading."
);
int
spin
=
10000
;
int
spin
=
10000
;
while
(
--
spin
!=
0
);
while
(
--
spin
!=
0
);
success
=
embb_
rwlock_unlock_read
(
&
rwlock
_
);
success
=
embb_
shared_mutex_unlock_shared
(
&
shared_mutex
_
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to unlock (reading)."
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to unlock (reading)."
);
}
}
void
RWLock
Test
::
TestSharedRead_Post
()
{
void
SharedMutex
Test
::
TestSharedRead_Post
()
{
embb_
rwlock_destroy
(
&
rwlock
_
);
embb_
shared_mutex_destroy
(
&
shared_mutex
_
);
}
}
void
RWLock
Test
::
TestExclusiveWrite_Pre
()
{
void
SharedMutex
Test
::
TestExclusiveWrite_Pre
()
{
int
success
=
embb_
rwlock_init
(
&
rwlock
_
);
int
success
=
embb_
shared_mutex_init
(
&
shared_mutex
_
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to initialize
rwlock
."
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to initialize
shared mutex
."
);
counter_
=
0
;
counter_
=
0
;
}
}
void
RWLock
Test
::
TestExclusiveWrite_ReaderMethod
()
{
void
SharedMutex
Test
::
TestExclusiveWrite_ReaderMethod
()
{
// Just add some contention
// Just add some contention
int
success
=
embb_
rwlock_try_lock_read
(
&
rwlock
_
);
int
success
=
embb_
shared_mutex_try_lock_shared
(
&
shared_mutex
_
);
if
(
success
!=
EMBB_SUCCESS
)
return
;
if
(
success
!=
EMBB_SUCCESS
)
return
;
int
spin
=
10000
;
int
spin
=
10000
;
while
(
--
spin
!=
0
);
while
(
--
spin
!=
0
);
success
=
embb_
rwlock_unlock_read
(
&
rwlock
_
);
success
=
embb_
shared_mutex_unlock_shared
(
&
shared_mutex
_
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to unlock (reading)."
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to unlock (reading)."
);
}
}
void
RWLock
Test
::
TestExclusiveWrite_WriterMethod
()
{
void
SharedMutex
Test
::
TestExclusiveWrite_WriterMethod
()
{
int
success
=
embb_
rwlock_lock_write
(
&
rwlock
_
);
int
success
=
embb_
shared_mutex_lock
(
&
shared_mutex
_
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to lock for writing."
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to lock for writing."
);
++
counter_
;
++
counter_
;
success
=
embb_
rwlock_unlock_write
(
&
rwlock
_
);
success
=
embb_
shared_mutex_unlock
(
&
shared_mutex
_
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to unlock (writing)."
);
PT_ASSERT_EQ_MSG
(
success
,
EMBB_SUCCESS
,
"Failed to unlock (writing)."
);
}
}
void
RWLock
Test
::
TestExclusiveWrite_Post
()
{
void
SharedMutex
Test
::
TestExclusiveWrite_Post
()
{
PT_ASSERT_EQ_MSG
(
counter_
,
num_iterations_
*
num_threads_
,
PT_ASSERT_EQ_MSG
(
counter_
,
num_iterations_
*
(
num_threads_
/
2
)
,
"Counter value is inconsistent."
);
"Counter value is inconsistent."
);
embb_
rwlock_destroy
(
&
rwlock
_
);
embb_
shared_mutex_destroy
(
&
shared_mutex
_
);
}
}
}
// namespace test
}
// namespace test
...
...
base_c/test/
rwlock
_test.h
→
base_c/test/
shared_mutex
_test.h
View file @
ae2f1813
...
@@ -24,21 +24,21 @@
...
@@ -24,21 +24,21 @@
* POSSIBILITY OF SUCH DAMAGE.
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
#ifndef BASE_C_TEST_
RWLOCK
_TEST_H_
#ifndef BASE_C_TEST_
SHARED_MUTEX
_TEST_H_
#define BASE_C_TEST_
RWLOCK
_TEST_H_
#define BASE_C_TEST_
SHARED_MUTEX
_TEST_H_
#include <partest/partest.h>
#include <partest/partest.h>
#include <embb/base/c/internal/platform.h>
#include <embb/base/c/internal/platform.h>
#include <embb/base/c/
rwlock
.h>
#include <embb/base/c/
shared_mutex
.h>
namespace
embb
{
namespace
embb
{
namespace
base
{
namespace
base
{
namespace
test
{
namespace
test
{
class
RWLock
Test
:
public
partest
::
TestCase
{
class
SharedMutex
Test
:
public
partest
::
TestCase
{
public
:
public
:
RWLock
Test
();
SharedMutex
Test
();
private
:
private
:
void
TestSharedRead_Pre
();
void
TestSharedRead_Pre
();
...
@@ -50,7 +50,7 @@ class RWLockTest : public partest::TestCase {
...
@@ -50,7 +50,7 @@ class RWLockTest : public partest::TestCase {
void
TestExclusiveWrite_WriterMethod
();
void
TestExclusiveWrite_WriterMethod
();
void
TestExclusiveWrite_Post
();
void
TestExclusiveWrite_Post
();
embb_
rwlock_t
rwlock
_
;
embb_
shared_mutex_t
shared_mutex
_
;
size_t
counter_
;
size_t
counter_
;
size_t
num_threads_
;
size_t
num_threads_
;
size_t
num_iterations_
;
size_t
num_iterations_
;
...
@@ -60,4 +60,4 @@ class RWLockTest : public partest::TestCase {
...
@@ -60,4 +60,4 @@ class RWLockTest : public partest::TestCase {
}
// namespace base
}
// namespace base
}
// namespace embb
}
// namespace embb
#endif // BASE_C_TEST_
RWLOCK
_TEST_H_
#endif // BASE_C_TEST_
SHARED_MUTEX
_TEST_H_
base_cpp/include/embb/base/base.h
View file @
ae2f1813
...
@@ -59,6 +59,6 @@
...
@@ -59,6 +59,6 @@
#include <embb/base/thread.h>
#include <embb/base/thread.h>
#include <embb/base/thread_specific_storage.h>
#include <embb/base/thread_specific_storage.h>
#include <embb/base/time.h>
#include <embb/base/time.h>
#include <embb/base/
rwlock
.h>
#include <embb/base/
shared_mutex
.h>
#endif // EMBB_BASE_BASE_H_
#endif // EMBB_BASE_BASE_H_
base_cpp/include/embb/base/internal/platform.h
View file @
ae2f1813
...
@@ -44,7 +44,7 @@ typedef embb_thread_t ThreadType;
...
@@ -44,7 +44,7 @@ typedef embb_thread_t ThreadType;
typedef
DWORD
IDType
;
typedef
DWORD
IDType
;
typedef
embb_mutex_t
MutexType
;
typedef
embb_mutex_t
MutexType
;
typedef
embb_condition_t
ConditionVariableType
;
typedef
embb_condition_t
ConditionVariableType
;
typedef
embb_
rwlock_t
RWLock
Type
;
typedef
embb_
shared_mutex_t
SharedMutex
Type
;
}
// namespace internal
}
// namespace internal
}
// namespace base
}
// namespace base
...
@@ -60,7 +60,7 @@ typedef embb_thread_t ThreadType;
...
@@ -60,7 +60,7 @@ typedef embb_thread_t ThreadType;
typedef
embb_thread_id_t
IDType
;
typedef
embb_thread_id_t
IDType
;
typedef
embb_mutex_t
MutexType
;
typedef
embb_mutex_t
MutexType
;
typedef
embb_condition_t
ConditionVariableType
;
typedef
embb_condition_t
ConditionVariableType
;
typedef
embb_
rwlock_t
RWLock
Type
;
typedef
embb_
shared_mutex_t
SharedMutex
Type
;
}
// namespace internal
}
// namespace internal
}
// namespace base
}
// namespace base
...
...
base_cpp/include/embb/base/internal/shared_mutex-inl.h
0 → 100644
View file @
ae2f1813
/*
* 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 <assert.h>
#include <algorithm> // For std::swap()
namespace
embb
{
namespace
base
{
template
<
typename
SharedMutex
>
SharedLock
<
SharedMutex
>::
SharedLock
()
:
shared_mutex_
(
NULL
),
locked_
(
false
)
{}
template
<
typename
SharedMutex
>
SharedLock
<
SharedMutex
>::
SharedLock
(
SharedMutex
&
shared_mutex
)
:
shared_mutex_
(
&
shared_mutex
),
locked_
(
false
)
{
shared_mutex_
->
LockShared
();
locked_
=
true
;
}
template
<
typename
SharedMutex
>
SharedLock
<
SharedMutex
>::
SharedLock
(
SharedMutex
&
shared_mutex
,
DeferLockTag
)
:
shared_mutex_
(
&
shared_mutex
),
locked_
(
false
)
{}
template
<
typename
SharedMutex
>
SharedLock
<
SharedMutex
>::
SharedLock
(
SharedMutex
&
shared_mutex
,
TryLockTag
)
:
shared_mutex_
(
&
shared_mutex
),
locked_
(
shared_mutex_
->
TryLockShared
())
{}
template
<
typename
SharedMutex
>
SharedLock
<
SharedMutex
>::
SharedLock
(
SharedMutex
&
shared_mutex
,
AdoptLockTag
)
:
shared_mutex_
(
&
shared_mutex
),
locked_
(
true
)
{}
template
<
typename
SharedMutex
>
SharedLock
<
SharedMutex
>::~
SharedLock
()
{
if
(
OwnsLock
())
{
shared_mutex_
->
UnlockShared
();
}
}
template
<
typename
SharedMutex
>
void
SharedLock
<
SharedMutex
>::
LockShared
()
{
if
(
shared_mutex_
==
NULL
||
locked_
)
{
EMBB_THROW
(
ErrorException
,
"Mutex not set or locked"
);
}
shared_mutex_
->
LockShared
();
locked_
=
true
;
}
template
<
typename
SharedMutex
>
bool
SharedLock
<
SharedMutex
>::
TryLockShared
()
{
if
(
shared_mutex_
==
NULL
||
locked_
)
{
EMBB_THROW
(
ErrorException
,
"Mutex not set or locked"
);
}
locked_
=
shared_mutex_
->
TryLockShared
();
return
locked_
;
}
template
<
typename
SharedMutex
>
void
SharedLock
<
SharedMutex
>::
UnlockShared
()
{
if
(
shared_mutex_
==
NULL
||
!
locked_
)
{
EMBB_THROW
(
ErrorException
,
"Mutex not set or unlocked"
);
}
shared_mutex_
->
UnlockShared
();
locked_
=
false
;
}
template
<
typename
SharedMutex
>
void
SharedLock
<
SharedMutex
>::
Swap
(
SharedLock
&
other
)
{
std
::
swap
(
shared_mutex_
,
other
.
shared_mutex_
);
std
::
swap
(
locked_
,
other
.
locked_
);
}
template
<
typename
SharedMutex
>
SharedMutex
*
SharedLock
<
SharedMutex
>::
Release
()
{
SharedMutex
*
to_release
=
shared_mutex_
;
shared_mutex_
=
NULL
;
locked_
=
false
;
return
to_release
;
}
template
<
typename
SharedMutex
>
bool
SharedLock
<
SharedMutex
>::
OwnsLock
()
const
{
assert
(
!
(
locked_
&&
(
shared_mutex_
==
NULL
)));
return
locked_
;
}
}
// namespace base
}
// namespace embb
#endif // EMBB_BASE_INTERNAL_SHARED_MUTEX_INL_H_
base_cpp/include/embb/base/
rwlock
.h
→
base_cpp/include/embb/base/
shared_mutex
.h
View file @
ae2f1813
...
@@ -24,187 +24,281 @@
...
@@ -24,187 +24,281 @@
* POSSIBILITY OF SUCH DAMAGE.
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
#ifndef EMBB_BASE_
RWLOCK
_H_
#ifndef EMBB_BASE_
SHARED_MUTEX
_H_
#define EMBB_BASE_
RWLOCK
_H_
#define EMBB_BASE_
SHARED_MUTEX
_H_
#include <embb/base/internal/platform.h>
#include <embb/base/internal/platform.h>
#include <embb/base/exceptions.h>
#include <embb/base/exceptions.h>
#include <embb/base/mutex.h>
namespace
embb
{
namespace
embb
{
namespace
base
{
namespace
base
{
/**
/**
* \defgroup CPP_BASE_
RWLOCK Readers-Writers Lock
* \defgroup CPP_BASE_
SHARED_MUTEX Shared mutex
*
*
* Shared-read/exclusive-write lock for thread synchronization.
* 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
* \ingroup CPP_BASE
*/
*/
/**
/**
* Shared
-read/exclusive-write (readers-writers) lock
.
* Shared
mutex providing shared-read/exclusive-write access synchronization
.
*
*
* Allows simultaneous shared access for concurrent readers, but only exclusive
* Allows simultaneous shared access for concurrent readers, but only exclusive
* access for writers. Cannot be locked recursively. Fairness and/or FIFO order
* access for writers. Cannot be locked recursively. Fairness and/or FIFO order
* guaranties are platform specific and should be assumed non-existent.
* guarantees are platform specific and should be assumed non-existent.
*
* \see Mutex
*
*
* \ingroup CPP_BASE_
RWLOCK
* \ingroup CPP_BASE_
SHARED_MUTEX
*/
*/
class
RWLock
{
class
SharedMutex
{
public
:
public
:
/**
/**
* Creates
an rwlock which is i
n unlocked state.
* Creates
the shared mutex object which is initially in a
n unlocked state.
*
*
* \memory Potentially allocates dynamic memory
* \memory Potentially allocates dynamic memory
*
* \notthreadsafe
* \notthreadsafe
*/
*/
RWLock
();
SharedMutex
();
/**
/**
* Destroys internal representation.
* Destroys internal representation.
*/
*/
~
RWLock
();
~
SharedMutex
();
/**
/**
* Waits until the
rwlock can be locked for read
ing and locks it.
* Waits until the
shared mutex can be locked for writ
ing and locks it.
*
*
* \pre
The \c rwlock is
not locked by the current thread.
* \pre
\c shared_mutex is initialized and
not locked by the current thread.
* \post
The \c rwlock is locked for read
ing.
* \post
\c shared_mutex is locked for writ
ing.
*
*
* \threadsafe
* \threadsafe
*
*
* \see TryLock
Read(), UnlockRead
()
* \see TryLock
(), Unlock
()
*/
*/
void
Lock
Read
();
void
Lock
();
/**
/**
* Waits until the rwlock can be locked for writing and locks it.
* 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.
*
*
* \
pre \c rwlock is initialized and not locked by the current thread.
* \
return \c true if shared mutex was locked for reading \n
*
\post \c rwlock is locked for writing.
*
\c false otherwise
*
*
* \threadsafe
* \threadsafe
*
*
* \see
TryLockWrite(), UnlockWrite
()
* \see
Lock(), Unlock
()
*/
*/
void
LockWrite
();
bool
TryLock
();
/**
/**
*
Tries to lock the rwlock for reading and returns immediately
.
*
Unlocks the shared mutex locked for writing
.
*
*
* \pre \c
rwlock is not locked
by the current thread.
* \pre \c
shared_mutex has been locked for writing
by the current thread.
* \post
If successful, \c rwlock is locked for reading
.
* \post
\c shared_mutex is unlocked
.
*
*
* \return \c true if rwlock was locked for reading \n
* \threadsafe
* \c false otherwise
*
* \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
* \threadsafe
*
*
* \see
LockRead(), UnlockRea
d()
* \see
TryLockShared(), UnlockShare
d()
*/
*/
bool
TryLockRea
d
();
void
LockShare
d
();
/**
/**
* Tries to lock the
rwlock for writ
ing and returns immediately.
* Tries to lock the
shared mutex for read
ing and returns immediately.
*
*
* \pre \c
rwlock
is not locked by the current thread.
* \pre \c
shared_mutex
is not locked by the current thread.
* \post If successful, \c
rwlock is locked for writ
ing.
* \post If successful, \c
shared_mutex is locked for read
ing.
*
*
* \return \c true if
rwlock
was locked for reading \n
* \return \c true if
shared mutex
was locked for reading \n
* \c false otherwise
* \c false otherwise
*
*
* \threadsafe
* \threadsafe
*
*
* \see Lock
Write(), UnlockWrite
()
* \see Lock
Shared(), UnlockShared
()
*/
*/
bool
TryLock
Write
();
bool
TryLock
Shared
();
/**
/**
* Unlocks
an rwlock
locked for reading.
* Unlocks
the shared mutex
locked for reading.
*
*
* \pre \c
rwlock
has been locked for reading by the current thread.
* \pre \c
shared_mutex
has been locked for reading by the current thread.
* \post \c
rwlock
is unlocked.
* \post \c
shared_mutex
is unlocked.
*
*
* \threadsafe
* \threadsafe
*
*
* \see Lock
Read(), TryLockRea
d()
* \see Lock
Shared(), TryLockShare
d()
*/
*/
void
Unlock
Rea
d
();
void
Unlock
Share
d
();
private
:
/**
/**
* Unlocks an rwlock locked for writing.
* 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).
*
*
* \pre \c rwlock has been locked for writing by the current thread.
* For exclusive ownership wrapping, use UniqueLock<SharedMutex>.
* \post \c rwlock is unlocked.
*
*
* \
threadsafe
* \not
threadsafe
*
*
* \see LockWrite(), TryLockWrite()
* \tparam SharedMutex Type of the shared mutex object being wrapped
*
* \see SharedMutex, UniqueLock
*
* \ingroup CPP_BASE_MUTEX
*/
*/
void
UnlockWrite
();
template
<
typename
SharedMutex
=
embb
::
base
::
SharedMutex
>
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
);
/**
/**
* Adaptor class for the readers lock that can be used with "LockGuard" and/or
* Creates a lock from an unlocked shared mutex without locking it.
* "UniqueLock" ownership wrappers.
*
*
* \see LockGuard, UniqueLock
* \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
*/
*/
class
ReaderLock
{
SharedLock
(
SharedMutex
&
shared_mutex
,
DeferLockTag
tag
);
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
* Creates a lock from an unlocked shared mutex and tries to lock it
* "UniqueLock" ownership wrappers.
* for reading.
*
* \pre \c shared_mutex is unlocked
* \post If successful, \c shared_mutex is locked for reading
*
*
* \see LockGuard, UniqueLock
* \param[IN] shared_mutex Shared mutex to be managed
* \param[IN] tag Tag to select correct constructor
*/
*/
class
WriterLock
{
SharedLock
(
SharedMutex
&
shared_mutex
,
TryLockTag
tag
);
public
:
WriterLock
(
RWLock
&
rwlock
);
/**
void
Lock
();
* Creates a lock from an already locked shared mutex.
bool
TryLock
();
*
void
Unlock
();
* \pre \c shared_mutex is locked for reading
private
:
* \post \c shared_mutex is locked for reading
WriterLock
(
const
WriterLock
&
);
*
WriterLock
&
operator
=
(
const
WriterLock
&
);
* \param[IN] shared_mutex Shared mutex to be managed
RWLock
&
rwlock_
;
* \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
();
/**
/**
* Returns an adaptor for the readers lock to be used with "LockGuard" and/or
* Unlocks the shared mutex locked for reading.
* "UniqueLock" ownership wrappers.
*
* \throws ErrorException, if no shared mutex is set or it is not yet locked
*/
*/
ReaderLock
&
GetReaderLock
();
void
UnlockShared
();
/**
/**
* Returns an adaptor for the writes lock to be used with "LockGuard" and/or
* Exchange shared mutex ownership with another shared lock
* "UniqueLock" ownership wrappers.
*
* \param other Shared lock to exchange ownership with
*/
*/
WriterLock
&
GetWriterLock
();
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
:
private
:
/**
/**
* Disable
s
copy construction and assignment.
* Disable copy construction and assignment.
*/
*/
RWLock
(
const
RW
Lock
&
);
SharedLock
(
const
Shared
Lock
&
);
RWLock
&
operator
=
(
const
RW
Lock
&
);
SharedLock
&
operator
=
(
const
Shared
Lock
&
);
internal
::
RWLockType
rwlock_
;
/**< Actual rwlock implementation from base_c */
/** Pointer to the owned shared mutex */
ReaderLock
reader_lock_
;
/**< Lock adaptor for readers */
SharedMutex
*
shared_mutex_
;
WriterLock
writer_lock_
;
/**< Lock adaptor for writers */
/** Locked flag (is true if and only if the owned shared mutex is locked) */
bool
locked_
;
};
};
}
// namespace base
}
// namespace base
}
// namespace embb
}
// namespace embb
#endif // EMBB_BASE_RWLOCK_H_
#include <embb/base/internal/shared_mutex-inl.h>
#endif // EMBB_BASE_SHARED_MUTEX_H_
base_cpp/src/
rwlock
.cc
→
base_cpp/src/
shared_mutex
.cc
View file @
ae2f1813
...
@@ -24,73 +24,45 @@
...
@@ -24,73 +24,45 @@
* POSSIBILITY OF SUCH DAMAGE.
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
#include <embb/base/
rwlock
.h>
#include <embb/base/
shared_mutex
.h>
#include <embb/base/c/
rwlock
.h>
#include <embb/base/c/
shared_mutex
.h>
namespace
embb
{
namespace
embb
{
namespace
base
{
namespace
base
{
RWLock
::
RWLock
()
SharedMutex
::
SharedMutex
()
:
rwlock_
(),
:
shared_mutex_
()
{
// Disable "this is used in base member initializer" warning.
embb_shared_mutex_init
(
&
shared_mutex_
);
// 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
()
{
SharedMutex
::~
SharedMutex
()
{
embb_
rwlock_destroy
(
&
rwlock
_
);
embb_
shared_mutex_destroy
(
&
shared_mutex
_
);
}
}
void
RWLock
::
LockRead
()
{
void
SharedMutex
::
Lock
()
{
embb_
rwlock_lock_read
(
&
rwlock
_
);
embb_
shared_mutex_lock
(
&
shared_mutex
_
);
}
}
void
RWLock
::
LockWrite
()
{
bool
SharedMutex
::
TryLock
()
{
embb_rwlock_lock_write
(
&
rwlock_
);
int
result
=
embb_shared_mutex_try_lock
(
&
shared_mutex_
);
}
bool
RWLock
::
TryLockRead
()
{
int
result
=
embb_rwlock_try_lock_read
(
&
rwlock_
);
return
result
==
EMBB_SUCCESS
;
return
result
==
EMBB_SUCCESS
;
}
}
bool
RWLock
::
TryLockWrite
()
{
void
SharedMutex
::
Unlock
()
{
int
result
=
embb_rwlock_try_lock_write
(
&
rwlock_
);
embb_shared_mutex_unlock
(
&
shared_mutex_
);
return
result
==
EMBB_SUCCESS
;
}
}
void
RWLock
::
UnlockRea
d
()
{
void
SharedMutex
::
LockShare
d
()
{
embb_
rwlock_unlock_read
(
&
rwlock
_
);
embb_
shared_mutex_lock_shared
(
&
shared_mutex
_
);
}
}
void
RWLock
::
UnlockWrite
()
{
bool
SharedMutex
::
TryLockShared
()
{
embb_rwlock_unlock_write
(
&
rwlock_
);
int
result
=
embb_shared_mutex_try_lock_shared
(
&
shared_mutex_
);
return
result
==
EMBB_SUCCESS
;
}
}
RWLock
::
ReaderLock
::
ReaderLock
(
RWLock
&
rwlock
)
:
rwlock_
(
rwlock
)
{}
void
SharedMutex
::
UnlockShared
()
{
void
RWLock
::
ReaderLock
::
Lock
()
{
rwlock_
.
LockRead
();
}
embb_shared_mutex_unlock_shared
(
&
shared_mutex_
);
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 base
...
...
base_cpp/test/main.cc
View file @
ae2f1813
...
@@ -34,7 +34,7 @@
...
@@ -34,7 +34,7 @@
#include <thread_specific_storage_test.h>
#include <thread_specific_storage_test.h>
#include <atomic_test.h>
#include <atomic_test.h>
#include <memory_allocation_test.h>
#include <memory_allocation_test.h>
#include <
rwlock
_test.h>
#include <
shared_mutex
_test.h>
#include <embb/base/c/memory_allocation.h>
#include <embb/base/c/memory_allocation.h>
...
@@ -46,7 +46,7 @@ using embb::base::test::ThreadSpecificStorageTest;
...
@@ -46,7 +46,7 @@ using embb::base::test::ThreadSpecificStorageTest;
using
embb
::
base
::
test
::
AtomicTest
;
using
embb
::
base
::
test
::
AtomicTest
;
using
embb
::
base
::
test
::
MemoryAllocationTest
;
using
embb
::
base
::
test
::
MemoryAllocationTest
;
using
embb
::
base
::
test
::
ThreadTest
;
using
embb
::
base
::
test
::
ThreadTest
;
using
embb
::
base
::
test
::
RWLock
Test
;
using
embb
::
base
::
test
::
SharedMutex
Test
;
PT_MAIN
(
"Base C++"
)
{
PT_MAIN
(
"Base C++"
)
{
unsigned
int
max_threads
=
unsigned
int
max_threads
=
...
@@ -60,7 +60,7 @@ PT_MAIN("Base C++") {
...
@@ -60,7 +60,7 @@ PT_MAIN("Base C++") {
PT_RUN
(
AtomicTest
);
PT_RUN
(
AtomicTest
);
PT_RUN
(
MemoryAllocationTest
);
PT_RUN
(
MemoryAllocationTest
);
PT_RUN
(
ThreadTest
);
PT_RUN
(
ThreadTest
);
PT_RUN
(
RWLock
Test
);
PT_RUN
(
SharedMutex
Test
);
PT_EXPECT
(
embb_get_bytes_allocated
()
==
0
);
PT_EXPECT
(
embb_get_bytes_allocated
()
==
0
);
}
}
base_cpp/test/rwlock_test.cc
deleted
100644 → 0
View file @
a257320c
/*
* 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
base_cpp/test/shared_mutex_test.cc
0 → 100644
View file @
ae2f1813
/*
* 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 <shared_mutex_test.h>
#include <embb/base/c/errors.h>
#include <embb/base/mutex.h>
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
<
embb
::
base
::
SharedMutex
>
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
<
embb
::
base
::
SharedMutex
>
lock
(
shared_mutex_
,
embb
::
base
::
try_lock
);
if
(
lock
.
OwnsLock
())
{
int
spin
=
10000
;
while
(
--
spin
!=
0
);
}
}
void
SharedMutexTest
::
TestExclusiveWrite_WriterMethod
()
{
UniqueLock
<
embb
::
base
::
SharedMutex
>
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
base_cpp/test/
rwlock
_test.h
→
base_cpp/test/
shared_mutex
_test.h
View file @
ae2f1813
...
@@ -24,33 +24,33 @@
...
@@ -24,33 +24,33 @@
* POSSIBILITY OF SUCH DAMAGE.
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
#ifndef BASE_CPP_TEST_
RWLOCK
_TEST_H_
#ifndef BASE_CPP_TEST_
SHARED_MUTEX
_TEST_H_
#define BASE_CPP_TEST_
RWLOCK
_TEST_H_
#define BASE_CPP_TEST_
SHARED_MUTEX
_TEST_H_
#include <partest/partest.h>
#include <partest/partest.h>
#include <embb/base/c/internal/platform.h>
#include <embb/base/c/internal/platform.h>
#include <embb/base/
rwlock
.h>
#include <embb/base/
shared_mutex
.h>
namespace
embb
{
namespace
embb
{
namespace
base
{
namespace
base
{
namespace
test
{
namespace
test
{
class
RWLock
Test
:
public
partest
::
TestCase
{
class
SharedMutex
Test
:
public
partest
::
TestCase
{
public
:
public
:
RWLock
Test
();
SharedMutex
Test
();
private
:
private
:
void
TestSharedRead_Pre
();
void
TestSharedRead_ThreadMethod
();
void
TestSharedRead_ThreadMethod
();
void
TestSharedRead_Post
();
void
TestExclusiveWrite_Pre
();
void
TestExclusiveWrite_Pre
();
void
TestExclusiveWrite_ReaderMethod
();
void
TestExclusiveWrite_ReaderMethod
();
void
TestExclusiveWrite_WriterMethod
();
void
TestExclusiveWrite_WriterMethod
();
void
TestExclusiveWrite_Post
();
void
TestExclusiveWrite_Post
();
RWLock
rwlock_
;
void
TestSharedLock_ThreadMethod
();
SharedMutex
shared_mutex_
;
size_t
counter_
;
size_t
counter_
;
size_t
num_threads_
;
size_t
num_threads_
;
size_t
num_iterations_
;
size_t
num_iterations_
;
...
@@ -60,4 +60,4 @@ class RWLockTest : public partest::TestCase {
...
@@ -60,4 +60,4 @@ class RWLockTest : public partest::TestCase {
}
// namespace base
}
// namespace base
}
// namespace embb
}
// namespace embb
#endif // BASE_CPP_TEST_
RWLOCK
_TEST_H_
#endif // BASE_CPP_TEST_
SHARED_MUTEX
_TEST_H_
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment