Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(163)

Side by Side Diff: ppapi/utility/completion_callback_factory_thread_traits.h

Issue 10696157: Add support for threadsafe completion callback factory. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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/module.h"
9 #include "ppapi/utility/threading/lock.h"
10
viettrungluu 2012/07/10 22:47:58 You should probably include ppapi/cpp/logging.h.
11 /// @file
12 /// Defines the traits structures for threadsafety of a completion callback
13 /// factory. We provide threadsafe and non-threadsafe version. The threadsafe
14 /// version is always correct (if you follow the thread usage rules of the
15 /// callback factory), but if you know your object will only be used on one
16 /// thread, you can uses the non-threadsafe version.
17 ///
18 /// The traits defines three nested classes to perform reference counting,
19 /// locks, and scoped locking.
20
21 namespace pp {
22
23 /// The threadsafe version of thread traits. Using this class as the "traits"
viettrungluu 2012/07/10 22:47:58 s/threadsafe/thread-safe/
24 /// template argument to a completion callback factory will make it "somewhat
25 /// thread-friendly." It will allow you to create completion callbacks from
26 /// background threads and post them to another thread to run.
27 ///
28 /// Care still must be taken to ensure that the completion callbacks are
29 /// executed on the same thread that the factory is destroyed on to avoid a
30 /// race on destruction.
31 ///
32 /// Implementation note: this uses a lock instead of atomic add instructions.
33 /// The number of platforms we need to support right now makes atomic
34 /// operations unweildy for this case that we don't actually use that often.
viettrungluu 2012/07/10 22:47:58 s/unweildy/unwieldy/
35 /// As a further optimization, we can add support for this.
viettrungluu 2012/07/10 22:47:58 s/\.$/ later./ ?
36 class ThreadSafeThreadTraits {
37 public:
38 class RefCount {
39 public:
40 /// Default constructor. In debug mode, this checks that the object is being
41 /// created on the main thread.
42 RefCount() : ref_(0) {
43 }
44
45 /// AddRef() increments the reference counter.
46 ///
47 /// @return An int32_t with the incremented reference counter.
48 int32_t AddRef() {
49 AutoLock lock(lock_);
50 return ++ref_;
51 }
52
53 /// Release() decrements the reference counter.
54 ///
55 /// @return An int32_t with the decremeneted reference counter.
56 int32_t Release() {
57 AutoLock lock(lock_);
58 return --ref_;
viettrungluu 2012/07/10 22:47:58 Maybe it's worth having a PP_DCHECK(ref > 0)?
59 }
60
61 private:
62 Lock lock_;
63 int32_t ref_;
64 };
viettrungluu 2012/07/10 22:47:58 Maybe you should disallow copy/assign?
65
66 typedef pp::Lock Lock;
67 typedef pp::AutoLock AutoLock;
68 };
69
70 /// The non-threadsafe version of thread traits. Using this class as the
71 /// "traits" template argument to a completion callback factory will make it
72 /// not threadsafe but with potential extra performance.
73 class NonThreadSafeThreadTraits {
74 public:
75 /// A simple reference counter that is not thread-safe.
76 ///
77 /// <strong>Note:</strong> in Debug mode, it checks that it is either called
78 /// on the main thread, or always called on another thread.
79 class RefCount {
80 public:
81 /// Default constructor. In debug mode, this checks that the object is being
82 /// created on the main thread.
83 RefCount() : ref_(0) {
84 #ifndef NDEBUG
85 is_main_thread_ = Module::Get()->core()->IsMainThread();
86 #endif
87 }
88
89 /// Destructor.
90 ~RefCount() {
91 PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread());
92 }
93
94 /// AddRef() increments the reference counter.
95 ///
96 /// @return An int32_t with the incremented reference counter.
97 int32_t AddRef() {
98 PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread());
99 return ++ref_;
100 }
101
102 /// Release() decrements the reference counter.
103 ///
104 /// @return An int32_t with the decremeneted reference counter.
105 int32_t Release() {
106 PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread());
107 return --ref_;
108 }
109
110 private:
111 int32_t ref_;
112 #ifndef NDEBUG
113 bool is_main_thread_;
viettrungluu 2012/07/10 22:47:58 I'm not entirely convinced that we should even let
114 #endif
115 };
viettrungluu 2012/07/10 22:47:58 "
116
117 /// A simple object that acts like a lock but does nothing.
118 ///
119 /// MStrong>Note:</strong> in Debug mode, it checks that it is either
120 /// called on the main thread, or always called on another thread. It also
121 /// asserts that the called does not recursively lock.
viettrungluu 2012/07/10 22:47:58 s/called/caller/ ?
122 class Lock {
123 public:
124 Lock() {
125 #ifndef NDEBUG
126 is_main_thread_ = Module::Get()->core()->IsMainThread();
127 lock_held_ = false;
128 #endif
129 }
130
131 ~Lock() {
132 PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread());
133 PP_DCHECK(!lock_held_);
viettrungluu 2012/07/10 22:47:58 I don't think it's documented anywhere that locks
134 }
135
136 /// Acquires the fake "lock". This does nothing except perform checks in
137 /// debug mode.
138 void Acquire() {
139 #ifndef NDEBUG
140 PP_DCHECK(!lock_held_);
141 lock_held_ = true;
142 #endif
143 }
144
145 /// Releases the fake "lock". This does nothing except perform checks in
146 /// debug mode.
147 void Release() {
148 #ifndef NDEBUG
149 PP_DCHECK(lock_held_);
150 lock_held_ = false;
151 #endif
152 }
153
154 private:
155 #ifndef NDEBUG
156 bool is_main_thread_;
157 bool lock_held_;
158 #endif
159 };
160
161 class AutoLock {
viettrungluu 2012/07/10 22:47:58 It feels kind of dumb that you have to repeat the
162 public:
163 explicit AutoLock(Lock& lock) : lock_(lock) {
164 lock_.Acquire();
165 }
166 ~AutoLock() {
167 lock_.Release();
168 }
169
170 private:
171 Lock& lock_;
172 };
173 };
174
175 } // namespace pp
176
177 #endif // PPAPI_UTILITY_THREAD_SAFE_THREAD_TRAITS_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698