OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ppapi/shared_impl/resource_tracker.h" | 5 #include "ppapi/shared_impl/resource_tracker.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "ppapi/shared_impl/callback_tracker.h" | 10 #include "ppapi/shared_impl/callback_tracker.h" |
11 #include "ppapi/shared_impl/id_assignment.h" | 11 #include "ppapi/shared_impl/id_assignment.h" |
12 #include "ppapi/shared_impl/ppapi_globals.h" | 12 #include "ppapi/shared_impl/ppapi_globals.h" |
13 #include "ppapi/shared_impl/proxy_lock.h" | 13 #include "ppapi/shared_impl/proxy_lock.h" |
14 #include "ppapi/shared_impl/resource.h" | 14 #include "ppapi/shared_impl/resource.h" |
15 | 15 |
16 namespace ppapi { | 16 namespace ppapi { |
17 | 17 |
18 ResourceTracker::ResourceTracker() | 18 ResourceTracker::ResourceTracker(ThreadMode thread_mode) |
19 : last_resource_value_(0), | 19 : last_resource_value_(0), |
20 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | 20 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
| 21 if (thread_mode == SINGLE_THREADED) |
| 22 thread_checker_.reset(new base::ThreadChecker); |
21 } | 23 } |
22 | 24 |
23 ResourceTracker::~ResourceTracker() { | 25 ResourceTracker::~ResourceTracker() { |
24 } | 26 } |
25 | 27 |
| 28 void ResourceTracker::CheckThreadingPreconditions() const { |
| 29 DCHECK(!thread_checker_ || thread_checker_->CalledOnValidThread()); |
| 30 #ifndef NDEBUG |
| 31 ProxyLock::AssertAcquired(); |
| 32 #endif |
| 33 } |
| 34 |
26 Resource* ResourceTracker::GetResource(PP_Resource res) const { | 35 Resource* ResourceTracker::GetResource(PP_Resource res) const { |
27 CHECK(thread_checker_.CalledOnValidThread()); | 36 CheckThreadingPreconditions(); |
28 ProxyLock::AssertAcquired(); | |
29 ResourceMap::const_iterator i = live_resources_.find(res); | 37 ResourceMap::const_iterator i = live_resources_.find(res); |
30 if (i == live_resources_.end()) | 38 if (i == live_resources_.end()) |
31 return NULL; | 39 return NULL; |
32 return i->second.first; | 40 return i->second.first; |
33 } | 41 } |
34 | 42 |
35 void ResourceTracker::AddRefResource(PP_Resource res) { | 43 void ResourceTracker::AddRefResource(PP_Resource res) { |
36 CHECK(thread_checker_.CalledOnValidThread()); | 44 CheckThreadingPreconditions(); |
37 DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) | 45 DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) |
38 << res << " is not a PP_Resource."; | 46 << res << " is not a PP_Resource."; |
39 ResourceMap::iterator i = live_resources_.find(res); | 47 ResourceMap::iterator i = live_resources_.find(res); |
40 if (i == live_resources_.end()) | 48 if (i == live_resources_.end()) |
41 return; | 49 return; |
42 | 50 |
43 // Prevent overflow of refcount. | 51 // Prevent overflow of refcount. |
44 if (i->second.second == | 52 if (i->second.second == |
45 std::numeric_limits<ResourceAndRefCount::second_type>::max()) | 53 std::numeric_limits<ResourceAndRefCount::second_type>::max()) |
46 return; | 54 return; |
47 | 55 |
48 // When we go from 0 to 1 plugin ref count, keep an additional "real" ref | 56 // When we go from 0 to 1 plugin ref count, keep an additional "real" ref |
49 // on its behalf. | 57 // on its behalf. |
50 if (i->second.second == 0) | 58 if (i->second.second == 0) |
51 i->second.first->AddRef(); | 59 i->second.first->AddRef(); |
52 | 60 |
53 i->second.second++; | 61 i->second.second++; |
54 return; | 62 return; |
55 } | 63 } |
56 | 64 |
57 void ResourceTracker::ReleaseResource(PP_Resource res) { | 65 void ResourceTracker::ReleaseResource(PP_Resource res) { |
58 CHECK(thread_checker_.CalledOnValidThread()); | 66 CheckThreadingPreconditions(); |
59 DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) | 67 DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) |
60 << res << " is not a PP_Resource."; | 68 << res << " is not a PP_Resource."; |
61 ResourceMap::iterator i = live_resources_.find(res); | 69 ResourceMap::iterator i = live_resources_.find(res); |
62 if (i == live_resources_.end()) | 70 if (i == live_resources_.end()) |
63 return; | 71 return; |
64 | 72 |
65 // Prevent underflow of refcount. | 73 // Prevent underflow of refcount. |
66 if (i->second.second == 0) | 74 if (i->second.second == 0) |
67 return; | 75 return; |
68 | 76 |
(...skipping 10 matching lines...) Expand all Loading... |
79 | 87 |
80 void ResourceTracker::ReleaseResourceSoon(PP_Resource res) { | 88 void ResourceTracker::ReleaseResourceSoon(PP_Resource res) { |
81 MessageLoop::current()->PostNonNestableTask( | 89 MessageLoop::current()->PostNonNestableTask( |
82 FROM_HERE, | 90 FROM_HERE, |
83 RunWhileLocked(base::Bind(&ResourceTracker::ReleaseResource, | 91 RunWhileLocked(base::Bind(&ResourceTracker::ReleaseResource, |
84 weak_ptr_factory_.GetWeakPtr(), | 92 weak_ptr_factory_.GetWeakPtr(), |
85 res))); | 93 res))); |
86 } | 94 } |
87 | 95 |
88 void ResourceTracker::DidCreateInstance(PP_Instance instance) { | 96 void ResourceTracker::DidCreateInstance(PP_Instance instance) { |
89 CHECK(thread_checker_.CalledOnValidThread()); | 97 CheckThreadingPreconditions(); |
90 // Due to the infrastructure of some tests, the instance is registered | 98 // Due to the infrastructure of some tests, the instance is registered |
91 // twice in a few cases. It would be nice not to do that and assert here | 99 // twice in a few cases. It would be nice not to do that and assert here |
92 // instead. | 100 // instead. |
93 if (instance_map_.find(instance) != instance_map_.end()) | 101 if (instance_map_.find(instance) != instance_map_.end()) |
94 return; | 102 return; |
95 instance_map_[instance] = linked_ptr<InstanceData>(new InstanceData); | 103 instance_map_[instance] = linked_ptr<InstanceData>(new InstanceData); |
96 } | 104 } |
97 | 105 |
98 void ResourceTracker::DidDeleteInstance(PP_Instance instance) { | 106 void ResourceTracker::DidDeleteInstance(PP_Instance instance) { |
99 CHECK(thread_checker_.CalledOnValidThread()); | 107 CheckThreadingPreconditions(); |
100 InstanceMap::iterator found_instance = instance_map_.find(instance); | 108 InstanceMap::iterator found_instance = instance_map_.find(instance); |
101 | 109 |
102 // Due to the infrastructure of some tests, the instance is unregistered | 110 // Due to the infrastructure of some tests, the instance is unregistered |
103 // twice in a few cases. It would be nice not to do that and assert here | 111 // twice in a few cases. It would be nice not to do that and assert here |
104 // instead. | 112 // instead. |
105 if (found_instance == instance_map_.end()) | 113 if (found_instance == instance_map_.end()) |
106 return; | 114 return; |
107 | 115 |
108 InstanceData& data = *found_instance->second; | 116 InstanceData& data = *found_instance->second; |
109 | 117 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 ResourceMap::iterator found_resource = live_resources_.find(*cur); | 152 ResourceMap::iterator found_resource = live_resources_.find(*cur); |
145 if (found_resource != live_resources_.end()) | 153 if (found_resource != live_resources_.end()) |
146 found_resource->second.first->NotifyInstanceWasDeleted(); | 154 found_resource->second.first->NotifyInstanceWasDeleted(); |
147 cur++; | 155 cur++; |
148 } | 156 } |
149 | 157 |
150 instance_map_.erase(instance); | 158 instance_map_.erase(instance); |
151 } | 159 } |
152 | 160 |
153 int ResourceTracker::GetLiveObjectsForInstance(PP_Instance instance) const { | 161 int ResourceTracker::GetLiveObjectsForInstance(PP_Instance instance) const { |
154 CHECK(thread_checker_.CalledOnValidThread()); | 162 CheckThreadingPreconditions(); |
155 InstanceMap::const_iterator found = instance_map_.find(instance); | 163 InstanceMap::const_iterator found = instance_map_.find(instance); |
156 if (found == instance_map_.end()) | 164 if (found == instance_map_.end()) |
157 return 0; | 165 return 0; |
158 return static_cast<int>(found->second->resources.size()); | 166 return static_cast<int>(found->second->resources.size()); |
159 } | 167 } |
160 | 168 |
161 PP_Resource ResourceTracker::AddResource(Resource* object) { | 169 PP_Resource ResourceTracker::AddResource(Resource* object) { |
162 CHECK(thread_checker_.CalledOnValidThread()); | 170 CheckThreadingPreconditions(); |
163 // If the plugin manages to create too many resources, don't do crazy stuff. | 171 // If the plugin manages to create too many resources, don't do crazy stuff. |
164 if (last_resource_value_ == kMaxPPId) | 172 if (last_resource_value_ == kMaxPPId) |
165 return 0; | 173 return 0; |
166 | 174 |
167 // Allocate an ID. Note there's a rare error condition below that means we | 175 // Allocate an ID. Note there's a rare error condition below that means we |
168 // could end up not using |new_id|, but that's harmless. | 176 // could end up not using |new_id|, but that's harmless. |
169 PP_Resource new_id = MakeTypedId(++last_resource_value_, PP_ID_TYPE_RESOURCE); | 177 PP_Resource new_id = MakeTypedId(++last_resource_value_, PP_ID_TYPE_RESOURCE); |
170 | 178 |
171 // Some objects have a 0 instance, meaning they aren't associated with any | 179 // Some objects have a 0 instance, meaning they aren't associated with any |
172 // instance, so they won't be in |instance_map_|. This is (as of this writing) | 180 // instance, so they won't be in |instance_map_|. This is (as of this writing) |
(...skipping 11 matching lines...) Expand all Loading... |
184 return 0; | 192 return 0; |
185 } | 193 } |
186 found->second->resources.insert(new_id); | 194 found->second->resources.insert(new_id); |
187 } | 195 } |
188 | 196 |
189 live_resources_[new_id] = ResourceAndRefCount(object, 0); | 197 live_resources_[new_id] = ResourceAndRefCount(object, 0); |
190 return new_id; | 198 return new_id; |
191 } | 199 } |
192 | 200 |
193 void ResourceTracker::RemoveResource(Resource* object) { | 201 void ResourceTracker::RemoveResource(Resource* object) { |
194 CHECK(thread_checker_.CalledOnValidThread()); | 202 CheckThreadingPreconditions(); |
195 PP_Resource pp_resource = object->pp_resource(); | 203 PP_Resource pp_resource = object->pp_resource(); |
196 InstanceMap::iterator found = instance_map_.find(object->pp_instance()); | 204 InstanceMap::iterator found = instance_map_.find(object->pp_instance()); |
197 if (found != instance_map_.end()) | 205 if (found != instance_map_.end()) |
198 found->second->resources.erase(pp_resource); | 206 found->second->resources.erase(pp_resource); |
199 live_resources_.erase(pp_resource); | 207 live_resources_.erase(pp_resource); |
200 } | 208 } |
201 | 209 |
202 void ResourceTracker::LastPluginRefWasDeleted(Resource* object) { | 210 void ResourceTracker::LastPluginRefWasDeleted(Resource* object) { |
203 // Bug http://crbug.com/134611 indicates that sometimes the resource tracker | 211 // Bug http://crbug.com/134611 indicates that sometimes the resource tracker |
204 // is null here. This should never be the case since if we have a resource in | 212 // is null here. This should never be the case since if we have a resource in |
(...skipping 10 matching lines...) Expand all Loading... |
215 CHECK(object->pp_instance() || is_message_loop); | 223 CHECK(object->pp_instance() || is_message_loop); |
216 CallbackTracker* callback_tracker = | 224 CallbackTracker* callback_tracker = |
217 PpapiGlobals::Get()->GetCallbackTrackerForInstance(object->pp_instance()); | 225 PpapiGlobals::Get()->GetCallbackTrackerForInstance(object->pp_instance()); |
218 CHECK(callback_tracker || is_message_loop); | 226 CHECK(callback_tracker || is_message_loop); |
219 if (callback_tracker) | 227 if (callback_tracker) |
220 callback_tracker->PostAbortForResource(object->pp_resource()); | 228 callback_tracker->PostAbortForResource(object->pp_resource()); |
221 object->NotifyLastPluginRefWasDeleted(); | 229 object->NotifyLastPluginRefWasDeleted(); |
222 } | 230 } |
223 | 231 |
224 } // namespace ppapi | 232 } // namespace ppapi |
OLD | NEW |