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