Imported Upstream version 1.3.99.4
[platform/upstream/syncevolution.git] / src / syncevo / ThreadSupport.h
1 /*
2  * Copyright (C) 2013 Intel Corporation
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) version 3.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301  USA
18  */
19
20 #ifndef INCL_THREAD_SUPPORT
21 # define INCL_THREAD_SUPPORT
22
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #ifdef HAVE_GLIB
28 # include <glib.h>
29 #else
30 # define GLIB_CHECK_VERSION(major, minor, revision) 0
31 #endif
32
33 #include <boost/shared_ptr.hpp>
34
35 #include <syncevo/declarations.h>
36 SE_BEGIN_CXX
37
38 // The revised threading API we use below was introduced in glib 2.3.2
39 // The fallback for older glib is to not offer thread support.
40 // The classes are still defined, they just don't do anything.
41 #if GLIB_CHECK_VERSION(2, 32, 0)
42 # define HAVE_THREAD_SUPPORT
43
44 /**
45  * Core building block for mutices.
46  */
47 template<class M, void (*_lock)(M *), void (*_unlock)(M *)> class MutexTemplate
48 {
49  protected:
50     M m_mutex;
51
52  public:
53     /**
54      * Created when locking the mutex. When the last copy of it
55      * gets destroyed, the mutex gets unlocked again.
56      */
57     class Guard : private boost::shared_ptr<M>
58     {
59         Guard(M *mutex) throw () :
60            boost::shared_ptr<M>(mutex, _unlock)
61         {}
62         friend class MutexTemplate;
63
64     public:
65         Guard() throw()
66         {}
67
68         void unlock() throw()
69         {
70             boost::shared_ptr<M>::reset();
71         }
72     };
73
74     /**
75      * Lock the mutex and return a handle that'll automatically
76      * unlock the mutex when the last copy gets destroyed.
77      */
78     Guard lock() throw ()
79     {
80         _lock(&m_mutex);
81         return Guard(&m_mutex);
82     }
83
84     M *get() { return &m_mutex; }
85     operator M * () { return &m_mutex; }
86 };
87
88 /**
89  * Initializes a mutex which was allocated dynamically
90  * on the heap or stack and frees allocated resources
91  * when done. It's an error to free a locked mutex.
92  */
93 template<class M, void (*_lock)(M *), void (*_unlock)(M *), void (*_init)(M *), void (*_clear)(M *)> class DynMutexTemplate :
94     public MutexTemplate<M, _lock, _unlock>
95 {
96  public:
97     DynMutexTemplate()
98     {
99         _init(MutexTemplate<M, _lock, _unlock>::get());
100     }
101     ~DynMutexTemplate()
102     {
103         _clear(MutexTemplate<M, _lock, _unlock>::get());
104     }
105 };
106
107 typedef MutexTemplate<GMutex, g_mutex_lock, g_mutex_unlock> Mutex;
108 typedef DynMutexTemplate<GMutex, g_mutex_lock, g_mutex_unlock, g_mutex_init, g_mutex_clear> DynMutex;
109 typedef MutexTemplate<GRecMutex, g_rec_mutex_lock, g_rec_mutex_unlock> RecMutex;
110 typedef DynMutexTemplate<GRecMutex, g_rec_mutex_lock, g_rec_mutex_unlock, g_rec_mutex_init, g_rec_mutex_clear> DynRecMutex;
111
112 class Cond
113 {
114     GCond m_cond;
115
116  public:
117     Cond() { g_cond_init(&m_cond); }
118     ~Cond() { g_cond_clear(&m_cond); }
119
120     void signal() { g_cond_signal(&m_cond); }
121     template<class M> void wait(M &m) { g_cond_wait(&m_cond, m); }
122 };
123
124 #else
125
126 # undef HAVE_THREAD_SUPPORT
127
128 /**
129  * Fallback just to get code compiled.
130  */
131 class DummyMutex
132 {
133  public:
134     class Guard
135     {
136     public:
137         void unlock() throw() {}
138     };
139
140     Guard lock() throw() { return Guard(); }
141 };
142
143 typedef DummyMutex Mutex;
144 typedef DummyMutex DynMutex;
145 typedef DummyMutex RecMutex;
146 typedef DummyMutex RecDynMutex;
147
148 class Cond
149 {
150  public:
151     void signal() {}
152     template<class M> void wait(M &m) {}
153 };
154
155 #endif
156
157 SE_END_CXX
158
159 #endif // INCL_THREAD_SUPPORT