OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 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 #include "ppapi/shared_impl/resource_tracker.h" | |
6 | |
7 #include "ppapi/shared_impl/id_assignment.h" | |
8 #include "ppapi/shared_impl/resource.h" | |
9 | |
10 namespace ppapi { | |
11 | |
12 ResourceTracker::ResourceTracker() : last_resource_value_(0) { | |
13 } | |
14 | |
15 ResourceTracker::~ResourceTracker() { | |
16 } | |
17 | |
18 Resource* ResourceTracker::GetResource(PP_Resource res) const { | |
19 ResourceMap::const_iterator i = live_resources_.find(res); | |
20 if (i == live_resources_.end()) | |
21 return NULL; | |
22 return i->second.first; | |
23 } | |
24 | |
25 bool ResourceTracker::AddRefResource(PP_Resource res) { | |
26 DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) | |
27 << res << " is not a PP_Resource."; | |
28 ResourceMap::iterator i = live_resources_.find(res); | |
29 if (i == live_resources_.end()) | |
30 return false; | |
31 | |
32 // Prevent overflow of refcount. | |
33 if (i->second.second == | |
34 std::numeric_limits<ResourceAndRefCount::second_type>::max()) | |
35 return false; | |
36 | |
37 // When we go from 0 to 1 plugin ref count, keep an additional "real" ref | |
38 // on its behalf. | |
39 if (i->second.second == 0) | |
40 i->second.first->AddRef(); | |
41 | |
42 i->second.second++; | |
43 return true; | |
44 } | |
45 | |
46 bool ResourceTracker::ReleaseResource(PP_Resource res) { | |
47 DLOG_IF(ERROR, !CheckIdType(res, PP_ID_TYPE_RESOURCE)) | |
48 << res << " is not a PP_Resource."; | |
49 ResourceMap::iterator i = live_resources_.find(res); | |
50 if (i == live_resources_.end()) | |
51 return false; | |
52 | |
53 // Prevent underflow of refcount. | |
54 if (i->second.second == 0) | |
55 return false; | |
56 | |
57 i->second.second--; | |
58 if (i->second.second == 0) { | |
59 i->second.first->LastPluginRefWasDeleted(); | |
60 | |
61 // When we go from 0 to 1 plugin ref count, free the additional "real" ref | |
dmichael (off chromium)
2011/08/17 19:02:54
1 to 0
| |
62 // on its behalf. THIS WILL MOST LIKELY RELEASE THE OBJECT AND REMOVE IT | |
63 // FROM OUR LIST. | |
64 i->second.first->Release(); | |
65 } | |
66 return true; | |
dmichael (off chromium)
2011/08/17 19:02:54
The return value seems to be true if the resource
| |
67 } | |
68 | |
69 void ResourceTracker::DidCreateInstance(PP_Instance instance) { | |
70 // Due to the infrastructure of some tests, the instance is registered | |
71 // twice in a few cases. It would be nice not to do that and assert here | |
72 // instead. | |
73 if (instance_map_.find(instance) != instance_map_.end()) | |
74 return; | |
75 instance_map_[instance] = linked_ptr<InstanceData>(new InstanceData); | |
76 } | |
77 | |
78 void ResourceTracker::DidDeleteInstance(PP_Instance instance) { | |
79 InstanceMap::iterator found_instance = instance_map_.find(instance); | |
80 | |
81 // Due to the infrastructure of some tests, the instance is uyregistered | |
dmichael (off chromium)
2011/08/17 19:02:54
uyregistered->unregistered
| |
82 // twice in a few cases. It would be nice not to do that and assert here | |
83 // instead. | |
84 if (found_instance == instance_map_.end()) | |
85 return; | |
86 | |
87 InstanceData& data = *found_instance->second; | |
88 | |
89 // Force release all plugin references to resources associated with the | |
90 // deleted instance. Make a copy since as we iterate through them, each one | |
91 // will remove itself from the tracking info individually. | |
92 ResourceSet to_delete = data.resources; | |
93 ResourceSet::iterator cur = to_delete.begin(); | |
94 while (cur != to_delete.end()) { | |
95 // Note that it's remotely possible for the object to already be deleted | |
96 // from the live resources. One case is if a resource object is holding | |
97 // the last ref to another. When we release the first one, it will release | |
98 // the second one. So the second one will be gone when we eventually get | |
99 // to it. | |
100 ResourceMap::iterator found_resource = live_resources_.find(*cur); | |
101 if (found_resource != live_resources_.end()) { | |
102 Resource* resource = found_resource->second.first; | |
103 if (found_resource->second.second > 0) { | |
104 resource->LastPluginRefWasDeleted(); | |
105 found_resource->second.second = 0; | |
106 | |
107 // This will most likely delete the resource object and remove it | |
108 // from the live_resources_ list. | |
109 resource->Release(); | |
110 } | |
111 } | |
112 | |
113 cur++; | |
114 } | |
115 | |
116 // In general the above pass will delete all the resources and there won't | |
117 // be any left in the map. However, if parts of the implementation are still | |
118 // holding on to internal refs, we need to tell them that the instance is | |
119 // gone. | |
120 to_delete = data.resources; | |
121 cur = to_delete.begin(); | |
122 while (cur != to_delete.end()) { | |
123 ResourceMap::iterator found_resource = live_resources_.find(*cur); | |
124 if (found_resource != live_resources_.end()) | |
125 found_resource->second.first->InstanceWasDeleted(); | |
126 cur++; | |
127 } | |
128 | |
129 instance_map_.erase(instance); | |
130 } | |
131 | |
132 int ResourceTracker::GetLiveObjectsForInstance(PP_Instance instance) const { | |
133 InstanceMap::const_iterator found = instance_map_.find(instance); | |
134 if (found == instance_map_.end()) | |
135 return 0; | |
136 return static_cast<int>(found->second->resources.size()); | |
137 } | |
138 | |
139 PP_Resource ResourceTracker::AddResource(Resource* object) { | |
140 // If the plugin manages to create too many resources, don't do crazy stuff. | |
dmichael (off chromium)
2011/08/17 19:02:54
Now that we're generating a resource for each inpu
| |
141 if (last_resource_value_ == kMaxPPId) | |
142 return 0; | |
143 | |
144 // If you hit this somebody forgot to call DidCreateInstance or the resource | |
145 // was created with an invalid PP_Instance. | |
146 DCHECK(instance_map_.find(object->pp_instance()) != instance_map_.end()); | |
147 | |
148 PP_Resource new_id = MakeTypedId(++last_resource_value_, PP_ID_TYPE_RESOURCE); | |
149 instance_map_[object->pp_instance()]->resources.insert(new_id); | |
150 | |
151 live_resources_[new_id] = ResourceAndRefCount(object, 0); | |
152 return new_id; | |
153 } | |
154 | |
155 void ResourceTracker::RemoveResource(Resource* object) { | |
156 PP_Resource pp_resource = object->pp_resource(); | |
157 if (object->pp_instance()) | |
158 instance_map_[object->pp_instance()]->resources.erase(pp_resource); | |
159 live_resources_.erase(pp_resource); | |
160 } | |
161 | |
162 | |
163 } // namespace ppapi | |
OLD | NEW |