|
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/var_tracker.h" | |
6 | |
7 #include <limits> | |
8 | |
9 #include "base/logging.h" | |
10 #include "ppapi/shared_impl/id_assignment.h" | |
11 #include "ppapi/shared_impl/var.h" | |
12 | |
13 namespace ppapi { | |
14 | |
15 VarTracker::VarInfo::VarInfo() | |
16 : var(), | |
17 ref_count(0), | |
18 track_with_no_reference_count(0) { | |
19 } | |
20 | |
21 VarTracker::VarInfo::VarInfo(Var* v, int input_ref_count) | |
22 : var(v), | |
23 ref_count(input_ref_count), | |
24 track_with_no_reference_count(0) { | |
25 } | |
26 | |
27 VarTracker::VarTracker() : last_var_id_(0) { | |
28 } | |
29 | |
30 VarTracker::~VarTracker() { | |
31 } | |
32 | |
33 int32 VarTracker::AddVar(Var* var) { | |
34 return AddVarInternal(var, true); | |
35 } | |
36 | |
37 Var* VarTracker::GetVar(int32 var_id) const { | |
38 VarMap::const_iterator result = live_vars_.find(var_id); | |
39 if (result == live_vars_.end()) | |
40 return NULL; | |
41 return result->second.var.get(); | |
42 } | |
43 | |
44 Var* VarTracker::GetVar(const PP_Var& var) const { | |
45 if (!IsVarTypeRefcounted(var.type)) | |
46 return NULL; | |
47 return GetVar(static_cast<int32>(var.value.as_id)); | |
48 } | |
49 | |
50 bool VarTracker::AddRefVar(int32 var_id) { | |
51 DLOG_IF(ERROR, !CheckIdType(var_id, PP_ID_TYPE_VAR)) | |
dmichael (off chromium)
2011/08/08 22:13:59
I'm having trouble figuring out where the var type
brettw
2011/08/09 17:08:09
VarTracker::AddVarInternal calls MakeTypedId.
| |
52 << var_id << " is not a PP_Var ID."; | |
53 VarMap::iterator found = live_vars_.find(var_id); | |
54 if (found == live_vars_.end()) { | |
55 NOTREACHED(); // Invalid var. | |
56 return false; | |
57 } | |
58 | |
59 VarInfo& info = found->second; | |
60 if (info.ref_count == 0) { | |
61 // All live vars with no refcount should be tracked objects. | |
62 DCHECK(info.track_with_no_reference_count > 0); | |
63 DCHECK(info.var->GetType() == PP_VARTYPE_OBJECT); | |
64 | |
65 TrackedObjectGettingOneRef(found); | |
66 } | |
67 | |
68 // Basic refcount increment. | |
69 info.ref_count++; | |
70 return true; | |
71 } | |
72 | |
73 bool VarTracker::AddRefVar(const PP_Var& var) { | |
74 if (!IsVarTypeRefcounted(var.type)) | |
75 return false; | |
76 return AddRefVar(static_cast<int32>(var.value.as_id)); | |
77 } | |
78 | |
79 bool VarTracker::ReleaseVar(int32 var_id) { | |
80 DLOG_IF(ERROR, !CheckIdType(var_id, PP_ID_TYPE_VAR)) | |
81 << var_id << " is not a PP_Var ID."; | |
82 VarMap::iterator found = live_vars_.find(var_id); | |
83 if (found == live_vars_.end()) { | |
84 NOTREACHED() << "Unref-ing an invalid var"; | |
85 return false; | |
86 } | |
87 | |
88 VarInfo& info = found->second; | |
89 if (info.ref_count == 0) { | |
90 NOTREACHED() << "Releasing an object with zero ref"; | |
91 return false; | |
92 } | |
93 info.ref_count--; | |
94 | |
95 if (info.ref_count == 0) { | |
96 if (info.var->GetType() == PP_VARTYPE_OBJECT) { | |
97 // Objects have special requirements and may not necessarily be released | |
98 // when the refcount goes to 0. | |
99 ObjectGettingZeroRef(found); | |
100 } else { | |
101 // All other var types can just be released. | |
102 DCHECK(info.track_with_no_reference_count == 0); | |
103 live_vars_.erase(found); | |
104 } | |
105 } | |
106 return true; | |
107 } | |
108 | |
109 bool VarTracker::ReleaseVar(const PP_Var& var) { | |
110 if (!IsVarTypeRefcounted(var.type)) | |
111 return false; | |
112 return ReleaseVar(static_cast<int32>(var.value.as_id)); | |
113 } | |
114 | |
115 int32 VarTracker::AddVarInternal(Var* var, bool take_ref) { | |
116 // If the plugin manages to create 1B strings... | |
dmichael (off chromium)
2011/08/08 22:13:59
This is splitting hairs, but I think it's more lik
| |
117 if (last_var_id_ == std::numeric_limits<int32>::max() >> kPPIdTypeBits) | |
118 return 0; | |
119 | |
120 // Add the resource with plugin use-count 1. | |
dmichael (off chromium)
2011/08/08 22:13:59
Update comment to account for take_ref? Or just re
| |
121 int32 new_id = MakeTypedId(++last_var_id_, PP_ID_TYPE_VAR); | |
122 live_vars_.insert(std::make_pair(new_id, VarInfo(var, take_ref ? 1 : 0))); | |
123 | |
124 return new_id; | |
125 } | |
126 | |
127 VarTracker::VarMap::iterator VarTracker::GetLiveVar(int32 id) { | |
128 return live_vars_.find(id); | |
129 } | |
130 | |
131 VarTracker::VarMap::iterator VarTracker::GetLiveVar(const PP_Var& var) { | |
132 return live_vars_.find(static_cast<int32>(var.value.as_id)); | |
133 } | |
134 | |
135 VarTracker::VarMap::const_iterator VarTracker::GetLiveVar( | |
136 const PP_Var& var) const { | |
137 return live_vars_.find(static_cast<int32>(var.value.as_id)); | |
138 } | |
139 | |
140 bool VarTracker::IsVarTypeRefcounted(PP_VarType type) const { | |
141 return type == PP_VARTYPE_STRING || type == PP_VARTYPE_OBJECT; | |
142 } | |
143 | |
144 void VarTracker::TrackedObjectGettingOneRef(VarMap::const_iterator obj) { | |
145 // Anybody using tracked objects should override this. | |
146 NOTREACHED(); | |
147 } | |
148 | |
149 void VarTracker::ObjectGettingZeroRef(VarMap::iterator iter) { | |
150 DeleteObjectInfoIfNecessary(iter); | |
151 } | |
152 | |
153 bool VarTracker::DeleteObjectInfoIfNecessary(VarMap::iterator iter) { | |
154 if (iter->second.ref_count != 0 || | |
155 iter->second.track_with_no_reference_count != 0) | |
156 return false; // Object still alive. | |
157 live_vars_.erase(iter); | |
158 return true; | |
159 } | |
160 | |
161 } // namespace ppapi | |
OLD | NEW |