MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SafeMutex.hpp
1 /* Copyright 2008 Sun Microsystems, Inc.
2  All rights reserved. Use is subject to license terms.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16 
17 #ifndef NDB_SAFE_MUTEX_HPP
18 #define NDB_SAFE_MUTEX_HPP
19 
20 #ifdef __WIN__
21 #include <ndb_global.h>
22 #include <my_pthread.h>
23 #else
24 #include <pthread.h>
25 #endif
26 #include <assert.h>
27 #include <ndb_types.h>
28 #include <NdbOut.hpp>
29 
30 /*
31  * Recursive mutex with recursion limit >= 1. Intended for debugging.
32  * One should rewrite caller code until limit 1 works.
33  *
34  * The implementation uses a default mutex. If limit is > 1 or debug
35  * is specified then a recursive mutex is simulated. Operating system
36  * recursive mutex (if any) is not used. The simulation is several
37  * times slower. There is a unit test testSafeMutex.
38  *
39  * The caller currently is multi-threaded disk data. Here it is easy
40  * to verify that the mutex is released within a time-slice.
41  */
42 
43 class SafeMutex {
44  const char* const m_name;
45  const Uint32 m_limit; // error if usage exceeds this
46  const bool m_debug; // use recursive implementation even for limit 1
47  const bool m_simple;
48  pthread_mutex_t m_mutex;
49  pthread_cond_t m_cond;
50  pthread_t m_owner;
51  bool m_initdone;
52  Uint32 m_level;
53  Uint32 m_usage; // max level used so far
54  int m_errcode;
55  int m_errline;
56  int err(int errcode, int errline);
57  friend class NdbOut& operator<<(NdbOut&, const SafeMutex&);
58 
59 public:
60  SafeMutex(const char* name, Uint32 limit, bool debug) :
61  m_name(name),
62  m_limit(limit),
63  m_debug(debug),
64  m_simple(!(limit > 1 || debug))
65  {
66  assert(m_limit >= 1),
67  m_owner = 0; // wl4391_todo assuming numeric non-zero
68  m_initdone = false;
69  m_level = 0;
70  m_usage = 0;
71  m_errcode = 0;
72  m_errline = 0;
73  };
74  ~SafeMutex() {
75  if (m_initdone)
76  (void)destroy();
77  }
78 
79  enum {
80  // caller must crash on any error - recovery is not possible
81  ErrState = -101, // user error
82  ErrLevel = -102, // level exceeded limit
83  ErrOwner = -103, // unlock when not owner
84  ErrNolock = -104 // unlock when no lock
85  };
86  int create();
87  int destroy();
88  int lock();
89  int unlock();
90 
91 private:
92  int lock_impl();
93  int unlock_impl();
94 };
95 
96 #endif