Chromium Code Reviews| 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 void 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; | |
| 31 | |
| 32 // Prevent overflow of refcount. | |
| 33 if (i->second.second == | |
| 34 std::numeric_limits<ResourceAndRefCount::second_type>::max()) | |
| 35 return; | |
| 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; | |
| 44 } | |
| 45 | |
| 46 void 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; | |
| 52 | |
| 53 // Prevent underflow of refcount. | |
| 54 if (i->second.second == 0) | |
| 55 return; | |
| 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 21:35:51
0 to 1 -> 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; | |
|
dmichael (off chromium)
2011/08/17 21:35:51
nit: the last return is unnecessary here and in Ad
| |
| 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 21:35:51
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. | |
| 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 |