atomic ops routed via qt
[serna.git] / sfworks / common / ThreadingPolicies.h
1 // 
2 // Copyright(c) 2009 Syntext, Inc. All Rights Reserved.
3 // Contact: info@syntext.com, http://www.syntext.com
4 // 
5 // This file is part of Syntext Serna XML Editor.
6 // 
7 // COMMERCIAL USAGE
8 // Licensees holding valid Syntext Serna commercial licenses may use this file
9 // in accordance with the Syntext Serna Commercial License Agreement provided
10 // with the software, or, alternatively, in accorance with the terms contained
11 // in a written agreement between you and Syntext, Inc.
12 // 
13 // GNU GENERAL PUBLIC LICENSE USAGE
14 // Alternatively, this file may be used under the terms of the GNU General 
15 // Public License versions 2.0 or 3.0 as published by the Free Software 
16 // Foundation and appearing in the file LICENSE.GPL included in the packaging 
17 // of this file. In addition, as a special exception, Syntext, Inc. gives you
18 // certain additional rights, which are described in the Syntext, Inc. GPL 
19 // Exception for Syntext Serna Free Edition, included in the file 
20 // GPL_EXCEPTION.txt in this package.
21 // 
22 // You should have received a copy of appropriate licenses along with this 
23 // package. If not, see <http://www.syntext.com/legal/>. If you are unsure
24 // which license is appropriate for your use, please contact the sales 
25 // department at sales@syntext.com.
26 // 
27 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 // 
30 /*! \file
31     This file contains lightweight, policy-based threading library
32     Windows part is derived from free Loki C++ library
33
34     Template classes defined below are not intended for general use;
35     rather they should be used for parametrization of other template
36     classes who needs threading policies (like Singleton, Ptr, etc).
37  */
38 #ifndef THREADING_POLICIES_H_
39 #define THREADING_POLICIES_H_
40
41 #include "common/common_defs.h"
42 #include "common/ThreadMutex.h"
43 #include <QAtomicInt>
44
45 // Specifies default threading model
46
47 #ifndef DEFAULT_THREADING
48 # ifdef MULTI_THREADED
49 #  define DEFAULT_THREADING    COMMON_NS::ObjectLevelLockable
50 #  define DEFAULT_THREADING_CL COMMON_NS::ClassLevelLockable
51 # else
52 #  define DEFAULT_THREADING    COMMON_NS::SingleThreaded
53 #  define DEFAULT_THREADING_CL COMMON_NS::SingleThreaded
54 # endif
55 #endif // DEFAULT_THREADING
56
57 COMMON_NS_BEGIN
58
59 class ThreadAtomicInt : public QAtomicInt {
60 public:
61     ThreadAtomicInt(int v) : QAtomicInt(v) {}
62     ThreadAtomicInt() {}
63 };
64
65 /*! Implementation of the SingleThreaded (no-synchronization) ThreadingModel
66     policy used by various classes.
67     It is desirable for all policies that class Lock should be constructed
68     given a reference to the host class (a class which holds the lock
69     instance). This reference is used only for ObjectLevelLockable,
70     for all other threading policies it is ignored.
71     Classes which do not initalize Lock with lock holder will not be
72     able to use ObjectLevelLockable.
73
74     T template argument is used for obtaining thread-specific type
75     traits (e.g. volatile type).
76  */
77 template <class M = NullThreadMutex>
78   class SingleThreaded {
79 public:
80     typedef ThreadAtomicInt AtomicInt; // no need for non-threaded now
81     typedef typename M::MutexType MutexType;
82     typedef M ThreadMutexClass;
83
84     enum { multiThreaded = false }; // not really multithreaded
85
86     /*! A lock guard primitive
87      */
88     class Lock
89     {
90     public:
91         Lock() {}
92         Lock(const SingleThreaded&) {}
93         Lock(const Lock&) {}
94         ~Lock() {} // GCC warning buster
95     };
96     // out-of-class traits use only
97     typedef M VolatileType;
98 };
99
100 /*! An implementation of ObjectLevelLockable ThreadingModel policy.
101  */
102 template <class M = ThreadMutex>
103   class ObjectLevelLockable {
104 public:
105     typedef ThreadAtomicInt AtomicInt;
106     typedef typename M::MutexType MutexType;
107     typedef M ThreadMutexClass;
108
109     enum { multiThreaded = true };
110
111     ObjectLevelLockable() {
112         M::initialize(&mtx_);
113     }
114
115     ~ObjectLevelLockable() {
116         M::destroy(&mtx_);
117     }
118     class Lock;
119     friend class Lock;
120
121     class Lock
122     {
123     private:
124         ObjectLevelLockable& host_;
125
126         Lock& operator=(const Lock&);
127     public:
128         Lock(ObjectLevelLockable& host) : host_(host)
129         {
130             M::lock(&host_.mtx_);
131         }
132         ~Lock()
133         {
134             M::unlock(&host_.mtx_);
135         }
136         Lock(const Lock& other) : host_(other.host_) {}
137     };
138     // out-of-class traits use only
139     typedef volatile M VolatileType;
140
141 private:
142     MutexType mtx_;
143 };
144
145 template <class M = ThreadMutex>
146   class ClassLevelLockable {
147 public:
148     typedef ThreadAtomicInt AtomicInt;
149     typedef typename M::MutexType MutexType;
150     typedef M ThreadMutexClass;
151     
152     enum { multiThreaded = true };
153
154     class Lock;
155     friend class Lock;
156
157     class Lock
158     {
159         Lock& operator=(const Lock&);
160     public:
161         Lock()
162         {
163             if (!initialized_) {
164                 M::initialize(&mtx_);
165                 initialized_ = true;
166             }
167             M::lock(&mtx_);
168         }
169         Lock(ClassLevelLockable&)
170         {
171             if (!initialized_) {
172                 M::initialize(&mtx_);
173                 initialized_ = true;
174             }
175             M::lock(&mtx_);
176         }
177         ~Lock()
178         {
179             M::unlock(&mtx_);
180         }
181         Lock(const Lock&) {} // do nothing on copy
182     };
183     // out-of-class traits use only
184     typedef volatile M VolatileType;
185
186 private:
187     static MutexType mtx_;
188     static bool initialized_;
189
190     struct Initializer;
191     friend struct Initializer;
192     struct Initializer
193     {
194         Initializer()
195         {
196             if (!initialized_)
197                 M::initialize(&mtx_);
198             initialized_ = true;
199         }
200         ~Initializer()
201         {
202             if (initialized_)
203                 M::destroy(&mtx_);
204         }
205     };
206     static Initializer initializer_;
207 };
208
209 template <class M> typename ClassLevelLockable<M>::MutexType
210     ClassLevelLockable<M>::mtx_;
211 template <class M> bool ClassLevelLockable<M>::initialized_ = false;
212 template <class M> typename ClassLevelLockable<M>::Initializer
213     ClassLevelLockable<M>::initializer_;
214
215 COMMON_NS_END
216
217 #endif // THREADING_POLICIES_H_