- add sources.
[platform/framework/web/crosswalk.git] / src / ppapi / utility / completion_callback_factory_thread_traits.h
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef PPAPI_UTILITY_THREAD_SAFE_THREAD_TRAITS_H_
6 #define PPAPI_UTILITY_THREAD_SAFE_THREAD_TRAITS_H_
7
8 #include "ppapi/cpp/logging.h"
9 #include "ppapi/cpp/module.h"
10 #include "ppapi/utility/threading/lock.h"
11
12 /// @file
13 /// Defines the traits structures for thread-safety of a completion callback
14 /// factory. We provide thread-safe and non-thread-safe version. The thread-safe
15 /// version is always correct (if you follow the thread usage rules of the
16 /// callback factory), but if you know your object will only be used on one
17 /// thread, you can uses the non-thread-safe version.
18 ///
19 /// The traits defines three nested classes to perform reference counting,
20 /// locks, and scoped locking.
21
22 namespace pp {
23
24 /// The thread-safe version of thread traits. Using this class as the "traits"
25 /// template argument to a completion callback factory will make it "somewhat
26 /// thread-friendly." It will allow you to create completion callbacks from
27 /// background threads and post them to another thread to run.
28 ///
29 /// Care still must be taken to ensure that the completion callbacks are
30 /// executed on the same thread that the factory is destroyed on to avoid a
31 /// race on destruction.
32 ///
33 /// Implementation note: this uses a lock instead of atomic add instructions.
34 /// The number of platforms we need to support right now makes atomic
35 /// operations unwieldy for this case that we don't actually use that often.
36 /// As a further optimization, we can add support for this later.
37 class ThreadSafeThreadTraits {
38  public:
39   class RefCount {
40    public:
41     /// Default constructor. In debug mode, this checks that the object is being
42     /// created on the main thread.
43     RefCount() : ref_(0) {
44     }
45
46     /// AddRef() increments the reference counter.
47     ///
48     /// @return An int32_t with the incremented reference counter.
49     int32_t AddRef() {
50       AutoLock lock(lock_);
51       return ++ref_;
52     }
53
54     /// Release() decrements the reference counter.
55     ///
56     /// @return An int32_t with the decremeneted reference counter.
57     int32_t Release() {
58       AutoLock lock(lock_);
59       PP_DCHECK(ref_ > 0);
60       return --ref_;
61     }
62
63    private:
64     Lock lock_;
65     int32_t ref_;
66   };
67
68   typedef pp::Lock Lock;
69   typedef pp::AutoLock AutoLock;
70 };
71
72 /// The non-thread-safe version of thread traits. Using this class as the
73 /// "traits" template argument to a completion callback factory will make it
74 /// not thread-safe but with potential extra performance.
75 class NonThreadSafeThreadTraits {
76  public:
77   /// A simple reference counter that is not thread-safe.
78   ///
79   /// <strong>Note:</strong> in Debug mode, it checks that it is either called
80   /// on the main thread, or always called on another thread.
81   class RefCount {
82    public:
83     /// Default constructor. In debug mode, this checks that the object is being
84     /// created on the main thread.
85     RefCount() : ref_(0) {
86 #ifndef NDEBUG
87       is_main_thread_ = Module::Get()->core()->IsMainThread();
88 #endif
89     }
90
91     /// Destructor.
92     ~RefCount() {
93       PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread());
94     }
95
96     /// AddRef() increments the reference counter.
97     ///
98     /// @return An int32_t with the incremented reference counter.
99     int32_t AddRef() {
100       PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread());
101       return ++ref_;
102     }
103
104     /// Release() decrements the reference counter.
105     ///
106     /// @return An int32_t with the decremeneted reference counter.
107     int32_t Release() {
108       PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread());
109       return --ref_;
110     }
111
112    private:
113     int32_t ref_;
114 #ifndef NDEBUG
115     bool is_main_thread_;
116 #endif
117   };
118
119   /// A simple object that acts like a lock but does nothing.
120   ///
121   /// <strong>Note:</strong> in Debug mode, it checks that it is either
122   /// called on the main thread, or always called on another thread. It also
123   /// asserts that the caller does not recursively lock.
124   class Lock {
125    public:
126     Lock() {
127 #ifndef NDEBUG
128       is_main_thread_ = Module::Get()->core()->IsMainThread();
129       lock_held_ = false;
130 #endif
131     }
132
133     ~Lock() {
134       PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread());
135     }
136
137     /// Acquires the fake "lock". This does nothing except perform checks in
138     /// debug mode.
139     void Acquire() {
140 #ifndef NDEBUG
141       PP_DCHECK(!lock_held_);
142       lock_held_ = true;
143 #endif
144     }
145
146     /// Releases the fake "lock". This does nothing except perform checks in
147     /// debug mode.
148     void Release() {
149 #ifndef NDEBUG
150       PP_DCHECK(lock_held_);
151       lock_held_ = false;
152 #endif
153     }
154
155    private:
156 #ifndef NDEBUG
157     bool is_main_thread_;
158     bool lock_held_;
159 #endif
160   };
161
162   class AutoLock {
163    public:
164     explicit AutoLock(Lock& lock) : lock_(lock) {
165       lock_.Acquire();
166     }
167     ~AutoLock() {
168       lock_.Release();
169     }
170
171    private:
172     Lock& lock_;
173   };
174 };
175
176 }  // namespace pp
177
178 #endif  // PPAPI_UTILITY_THREAD_SAFE_THREAD_TRAITS_H_