1    	#include "condition_variable_debug.h"
2    	#include "common/mutex_debug.h"
3    	
4    	namespace ceph {
5    	
6    	condition_variable_debug::condition_variable_debug()
7    	  : waiter_mutex{nullptr}
8    	{
9    	  int r = pthread_cond_init(&cond, nullptr);
10   	  if (r) {
11   	    throw std::system_error(r, std::generic_category());
12   	  }
13   	}
14   	
15   	condition_variable_debug::~condition_variable_debug()
16   	{
17   	  pthread_cond_destroy(&cond);
18   	}
19   	
20   	void condition_variable_debug::wait(std::unique_lock<mutex_debug>& lock)
21   	{
22   	  // make sure this cond is used with one mutex only
23   	  ceph_assert(waiter_mutex == nullptr ||
24   	         waiter_mutex == lock.mutex());
25   	  waiter_mutex = lock.mutex();
26   	  ceph_assert(waiter_mutex->is_locked());
27   	  waiter_mutex->_pre_unlock();
28   	  if (int r = pthread_cond_wait(&cond, waiter_mutex->native_handle());
29   	      r != 0) {
(1) Event exception_thrown: An exception of type "std::system_error" is thrown.
30   	    throw std::system_error(r, std::generic_category());
31   	  }
32   	  waiter_mutex->_post_lock();
33   	}
34   	
35   	void condition_variable_debug::notify_one()
36   	{
37   	  // make sure signaler is holding the waiter's lock.
38   	  ceph_assert(waiter_mutex == nullptr ||
39   	         waiter_mutex->is_locked());
40   	  if (int r = pthread_cond_signal(&cond); r != 0) {
41   	    throw std::system_error(r, std::generic_category());
42   	  }
43   	}
44   	
45   	void condition_variable_debug::notify_all(bool sloppy)
46   	{
47   	  if (!sloppy) {
48   	    // make sure signaler is holding the waiter's lock.
49   	    ceph_assert(waiter_mutex == NULL ||
50   	                waiter_mutex->is_locked());
51   	  }
52   	  if (int r = pthread_cond_broadcast(&cond); r != 0 && !sloppy) {
53   	    throw std::system_error(r, std::generic_category());
54   	  }
55   	}
56   	
57   	std::cv_status condition_variable_debug::_wait_until(mutex_debug* mutex,
58   	                                                     timespec* ts)
59   	{
60   	  // make sure this cond is used with one mutex only
61   	  ceph_assert(waiter_mutex == nullptr ||
62   	         waiter_mutex == mutex);
63   	  waiter_mutex = mutex;
64   	  ceph_assert(waiter_mutex->is_locked());
65   	
66   	  waiter_mutex->_pre_unlock();
67   	  int r = pthread_cond_timedwait(&cond, waiter_mutex->native_handle(), ts);
68   	  waiter_mutex->_post_lock();
69   	  switch (r) {
70   	  case 0:
71   	    return std::cv_status::no_timeout;
72   	  case ETIMEDOUT:
73   	    return std::cv_status::timeout;
74   	  default:
75   	    throw std::system_error(r, std::generic_category());
76   	  }
77   	}
78   	
79   	} // namespace ceph
80