Skip to content

Commit 8383ace

Browse files
Merge branch '151-augment-coverage' into develop
2 parents f6d6733 + 77c7ed3 commit 8383ace

File tree

12 files changed

+328
-201
lines changed

12 files changed

+328
-201
lines changed

CHANGELOG

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
1.9.0
2+
- better comments in sync_queue (#157)
3+
- conditional_variable tests (#154)
4+
- new exception tests (#153)#
25
- fix SONAR detected issues (#149)
6+
- bug fixing: #155, #156
37
v1.8.0
48
- integrate GTest as an external module (#79)
59
- use CMake

include/pthread/condition_variable.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,17 @@ namespace pthread {
195195

196196
// constructor/destructor ------------------------------------------------
197197

198+
/** construct a new condition_variable (pthread_cond_init).
199+
*/
198200
condition_variable ();
201+
202+
/** destroy a condition_variable (pthread_cond_destroy)
203+
*
204+
*/
199205
virtual ~condition_variable();
200206

201207
private:
208+
202209
void milliseconds( int milliseconds);
203210

204211
timespec timeout;
@@ -231,7 +238,7 @@ namespace pthread {
231238
int rc = 0;
232239
cv_status status = no_timeout;
233240

234-
milliseconds(millis); // update timeou
241+
milliseconds(millis); // update timeout
235242
bool stop_waiting = lambda(); // returns ​false if the waiting should be continued.
236243

237244
while((! stop_waiting) && (status == no_timeout)){

include/pthread/exceptions.hpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ namespace pthread {
5959

6060
private:
6161
std::string _message;
62-
//const char *_message;
6362
int _pthread_errno;
6463

6564
};
@@ -109,16 +108,12 @@ namespace pthread {
109108
class condition_variable_exception: public pthread_exception {
110109
public:
111110

112-
/** thrown when mutex actions fail
111+
/** thrown when condition variable actions fail
113112
*
114113
* @param message short description
115114
* @param pthread_errno error returned by the pthread function
116115
*/
117-
condition_variable_exception( const std::string &message, const int pthread_errno = -1);
118-
119-
virtual ~condition_variable_exception(){
120-
// Intentionally unimplemented...
121-
};
116+
explicit condition_variable_exception( const std::string &message = "conditional_variable_exception", const int pthread_errno = -1);
122117
};
123118

124119
/** thrown to indicate that something went wrong with a thread */

include/pthread/mutex.hpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,15 @@ namespace pthread {
4646
void lock();
4747

4848
/**
49-
The function pthread_mutex_trylock is identical to pthread_mutex_lock except tha
50-
if the mutex object referenced by mutex is currently locked (by any thread,
51-
including the current thread), the call returns immediately.
52-
53-
@throw mutex_exception if error conditions preventing this method to succeed.
54-
@see lock
49+
* The function pthread_mutex_trylock is identical to pthread_mutex_lock except that
50+
* if the mutex object referenced by mutex is currently locked (by any thread,
51+
* including the current thread), the call returns immediately.
52+
*
53+
* @return
54+
* @throw mutex_exception if error conditions preventing this method to succeed.
55+
* @see lock
5556
*/
56-
void try_lock();
57+
bool try_lock();
5758

5859
/**
5960
The pthread_mutex_unlock function releases the mutex object referenced by mutex. The manner in which a mutex is released is dependent upon the mutex's type attribute. If there are threads blocked on the mutex object referenced by mutex when unlock is called, resulting in the mutex becoming available, the scheduling policy is used to determine which thread shall acquire the mutex.

include/pthread/pthread.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
namespace pthread {
3434

3535
/** @return library version */
36-
extern "C" const char *cpp_pthread_version();
36+
const char *cpp_pthread_version();
3737

3838
}
3939
#endif /* pthread_pthread_hpp */

include/pthread/sync_queue.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ namespace pthread {
5353
*/
5454
void put (const T& item);
5555

56-
/** Put an item in the queue (wait if size >= max_size).
56+
/** Put an item in the queue.
57+
*
58+
* If the queue size is greater or equal to max_size, then wait for the wiat-time millis for the queue to empty a bit.
5759
*
5860
* @param item item to store in the queue
5961
* @param wait_time millis to wait for the queue to free a slo
@@ -62,13 +64,13 @@ namespace pthread {
6264

6365
/** Get an item from the queue.
6466
*
65-
* If the queue is empty, get waits for an item to be put.
67+
* If the queue is empty, the method blocks until an item is entered in the queue.
6668
*
6769
* @param item item that will receive an item found onto the queue.
6870
*/
6971
void get ( T& item);
7072

71-
/** Get an item from the queue, if empty wait for one during duration milliseconds.
73+
/** Get an item from the queue, if the queue is empty, then wait for an element wait_time milliseconds.
7274
*
7375
* @param item item that will receive an item found onto the queue.
7476
* @param wait_time duration we are willing to wait for a new item.

src/condition_variable.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,13 @@ namespace pthread {
9191
}
9292

9393
condition_variable::~condition_variable () {
94+
pthread_cond_destroy(&_condition);
95+
/* NOSONAR
9496
int rc = pthread_cond_destroy(&_condition);
9597
if (rc != 0){
96-
throw pthread_exception("pthread condition variable destroy failed.", rc);
98+
throw condition_variable_exception("pthread condition variable destroy failed.", rc);
9799
}
100+
*/
98101
}
99102

100103
} // namespace pthread

src/mutex.cpp

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,38 +10,43 @@
1010

1111
namespace pthread {
1212

13-
mutex::mutex () {
14-
auto rc = pthread_mutex_init (&_mutex, NULL);
15-
if ( rc != 0 ) {
16-
throw mutex_exception ( "In constructor of mutex pthread_mutex_init(&mutex, NULL) failed. ", rc );
13+
mutex::mutex() {
14+
auto rc = pthread_mutex_init(&_mutex, NULL);
15+
if (rc != 0) {
16+
throw mutex_exception("In constructor of mutex pthread_mutex_init(&mutex, NULL) failed. ", rc);
17+
}
1718
}
18-
}
1919

20-
mutex::~mutex () {
21-
pthread_mutex_destroy (&_mutex);
22-
}
20+
mutex::~mutex() {
21+
pthread_mutex_destroy(&_mutex);
22+
}
2323

24-
void mutex::lock () {
25-
int rc = -1;
26-
rc = pthread_mutex_lock ( &_mutex );
27-
if ( rc != 0 ){
28-
throw mutex_exception("pthread_mutex_lock failed.", rc);
24+
void mutex::lock() {
25+
int rc = -1;
26+
rc = pthread_mutex_lock(&_mutex);
27+
if (rc != 0) {
28+
throw mutex_exception("pthread_mutex_lock failed.", rc);
29+
}
2930
}
30-
}
3131

32-
void mutex::try_lock () {
32+
bool mutex::try_lock() {
33+
bool status = false;
34+
35+
auto rc = pthread_mutex_trylock(&_mutex);
36+
if (rc == 0) {
37+
status = true;
38+
} else {
39+
throw mutex_exception("pthread_mutex_trylock failed, already locked.", rc);
40+
}
3341

34-
auto rc = pthread_mutex_trylock ( &_mutex );
35-
if ( rc != 0 ){
36-
throw mutex_exception("pthread_mutex_trylock failed, already locked.", rc);
42+
return status ;
3743
}
38-
}
3944

40-
void mutex::unlock () {
41-
auto rc = pthread_mutex_unlock ( &_mutex );
42-
if ( rc != 0 ){
43-
throw mutex_exception("pthread_mutex_unlock failed.", rc);
45+
void mutex::unlock() {
46+
auto rc = pthread_mutex_unlock(&_mutex);
47+
if (rc != 0) {
48+
throw mutex_exception("pthread_mutex_unlock failed.", rc);
49+
}
4450
}
45-
}
4651

4752
}

tests/CMakeLists.txt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ if (GCOV AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU"))
33
set(GCOV_LIB gcov)
44
endif()
55

6-
message(STATUS "Add GoogleTest cpp_thread_tests")
7-
add_executable(cpp_thread_tests concurrency_tests.cpp exceptions_tests.cpp synchronized_queue_tests.cpp)
6+
add_executable(cpp_thread_tests concurrency_tests.cpp exceptions_tests.cpp )
87
target_link_libraries(cpp_thread_tests GTest::GTest GTest::gtest_main cpp-pthread-static ${GCOV_LIB})
9-
108
add_test(NAME cpp_thread_tests COMMAND cpp_thread_tests)
9+
10+
add_executable(synchronized_queue_tests synchronized_queue_tests.cpp)
11+
target_link_libraries(synchronized_queue_tests GTest::GTest GTest::gtest_main cpp-pthread-static ${GCOV_LIB})
12+
add_test(NAME synchronized_queue_tests COMMAND synchronized_queue_tests)
13+

tests/concurrency_tests.cpp

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ TEST(concurrency, mutex) {
1818
try {
1919
pthread::lock_guard<pthread::mutex> lock(mutex);
2020
success = true;
21-
// std::cout << "in critical section (mutex)" << std::endl;
22-
2321
} catch ( std::exception &err) {
2422
std::cerr << "something went wrong: " << err.what() << std::endl;
2523
}catch ( ... ){
@@ -54,4 +52,74 @@ TEST(concurrency, read_write_lock) {
5452
}
5553

5654
EXPECT_TRUE(success);
57-
}
55+
}
56+
57+
TEST(concurrency, condition_variable_wait_for){
58+
pthread::condition_variable condition;
59+
pthread::mutex mutex;
60+
bool stop_waiting = true;
61+
62+
/* wait 1s for condition to be signaled. When returning from the wait_for method call, the mutex is locked.
63+
*
64+
* Therefore we expect, try_lock to throw an exception to signal that the mutex is already locked.
65+
*/
66+
EXPECT_EQ(pthread::cv_status::timedout, condition.wait_for(mutex, 1*1000));
67+
EXPECT_THROW(mutex.try_lock(), pthread::pthread_exception);
68+
mutex.unlock(); // free to lock
69+
70+
{
71+
pthread::lock_guard<pthread::mutex> lock{mutex};
72+
EXPECT_EQ(pthread::cv_status::timedout, condition.wait_for(lock, 1 * 1000));
73+
}
74+
75+
{
76+
pthread::lock_guard<pthread::mutex> lock{mutex};
77+
EXPECT_EQ(true, condition.wait_for(lock, 1 * 1000, [stop_waiting]{
78+
std::cout << "running lambda, stop_waiting : " << stop_waiting << std::endl ;
79+
return stop_waiting;
80+
}
81+
)
82+
);
83+
}
84+
85+
86+
{
87+
pthread::lock_guard<pthread::mutex> lock{mutex};
88+
EXPECT_EQ(false, condition.wait_for(lock, 1 * 1000, [stop_waiting]{
89+
std::cout << "running lambda, stop_waiting : " << stop_waiting << std::endl ;
90+
return ! stop_waiting;
91+
}
92+
)
93+
);
94+
}
95+
}
96+
97+
/* NOSONAR for later use
98+
class test_thread: public pthread::abstract_thread{
99+
public:
100+
void run() noexcept override{
101+
pthread::this_thread::sleep_for(5*1000);
102+
std::cout << "thread is waiting for mutex" << std::endl;
103+
pthread::lock_guard<pthread::mutex> lock(*_mutex);
104+
std::cout << "thread got mutex" << std::endl;
105+
}
106+
107+
test_thread( pthread::mutex *mutex): _mutex(mutex){
108+
109+
}
110+
private:
111+
pthread::mutex *_mutex;
112+
};
113+
114+
pthread::mutex mutex;
115+
116+
test_thread thread{&mutex};
117+
thread.start();
118+
{
119+
pthread::lock_guard<pthread::mutex> lock(mutex);
120+
pthread::this_thread::sleep_for(10*1000);
121+
}
122+
123+
thread.join();
124+
125+
*/

0 commit comments

Comments
 (0)