summaryrefslogtreecommitdiffstats
path: root/ppapi/shared_impl/var_tracker.cc
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-09 23:14:13 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-09 23:14:13 +0000
commit2bbd2c670008e30aaaef6c3c25ae37e0c17f8c3f (patch)
tree79595eeb026dd29841a7380fd7753f992c2e466b /ppapi/shared_impl/var_tracker.cc
parent32131b9030d8313f7adc9b765f706ffbee7ca709 (diff)
downloadchromium_src-2bbd2c670008e30aaaef6c3c25ae37e0c17f8c3f.zip
chromium_src-2bbd2c670008e30aaaef6c3c25ae37e0c17f8c3f.tar.gz
chromium_src-2bbd2c670008e30aaaef6c3c25ae37e0c17f8c3f.tar.bz2
Unify var tracking between webkit and the proxy.
This replaces the var tracking in the proxy with the var tracking in the shared_impl that's used by the implementation. It adds a new ProxyObjectVar to be the proxied plugin analog of NPObjectVar in the impl. This new object just keeps track of the host data. The tricky part is to make the var tracker able to do all the crazy messaging. This adds some virtual functions to the shared var tracker that we override in the plugin in PluginVarTracker. This removes the calls to the GetLiveObjectsForInstance in the var deprecated test. It turns out this function really can't be implemented properly in the proxy, and I don't know why it even worked before. A Release() call posts a non-nestable task so the object isn't released until later. So to implement the proxy for GetLiveObjectsForInstance we would also need to post a non-nestable task. But when the test runs we're getting called from within the plugin, so blocking on a non-nestable task deadlocks. So I just gave up and deleted the parts of the test that uses it. TEST=included BUG=none Review URL: http://codereview.chromium.org/7578001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96094 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/shared_impl/var_tracker.cc')
-rw-r--r--ppapi/shared_impl/var_tracker.cc161
1 files changed, 161 insertions, 0 deletions
diff --git a/ppapi/shared_impl/var_tracker.cc b/ppapi/shared_impl/var_tracker.cc
new file mode 100644
index 0000000..7f7157e
--- /dev/null
+++ b/ppapi/shared_impl/var_tracker.cc
@@ -0,0 +1,161 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/shared_impl/var_tracker.h"
+
+#include <limits>
+
+#include "base/logging.h"
+#include "ppapi/shared_impl/id_assignment.h"
+#include "ppapi/shared_impl/var.h"
+
+namespace ppapi {
+
+VarTracker::VarInfo::VarInfo()
+ : var(),
+ ref_count(0),
+ track_with_no_reference_count(0) {
+}
+
+VarTracker::VarInfo::VarInfo(Var* v, int input_ref_count)
+ : var(v),
+ ref_count(input_ref_count),
+ track_with_no_reference_count(0) {
+}
+
+VarTracker::VarTracker() : last_var_id_(0) {
+}
+
+VarTracker::~VarTracker() {
+}
+
+int32 VarTracker::AddVar(Var* var) {
+ return AddVarInternal(var, ADD_VAR_TAKE_ONE_REFERENCE);
+}
+
+Var* VarTracker::GetVar(int32 var_id) const {
+ VarMap::const_iterator result = live_vars_.find(var_id);
+ if (result == live_vars_.end())
+ return NULL;
+ return result->second.var.get();
+}
+
+Var* VarTracker::GetVar(const PP_Var& var) const {
+ if (!IsVarTypeRefcounted(var.type))
+ return NULL;
+ return GetVar(static_cast<int32>(var.value.as_id));
+}
+
+bool VarTracker::AddRefVar(int32 var_id) {
+ DLOG_IF(ERROR, !CheckIdType(var_id, PP_ID_TYPE_VAR))
+ << var_id << " is not a PP_Var ID.";
+ VarMap::iterator found = live_vars_.find(var_id);
+ if (found == live_vars_.end()) {
+ NOTREACHED(); // Invalid var.
+ return false;
+ }
+
+ VarInfo& info = found->second;
+ if (info.ref_count == 0) {
+ // All live vars with no refcount should be tracked objects.
+ DCHECK(info.track_with_no_reference_count > 0);
+ DCHECK(info.var->GetType() == PP_VARTYPE_OBJECT);
+
+ TrackedObjectGettingOneRef(found);
+ }
+
+ // Basic refcount increment.
+ info.ref_count++;
+ return true;
+}
+
+bool VarTracker::AddRefVar(const PP_Var& var) {
+ if (!IsVarTypeRefcounted(var.type))
+ return false;
+ return AddRefVar(static_cast<int32>(var.value.as_id));
+}
+
+bool VarTracker::ReleaseVar(int32 var_id) {
+ DLOG_IF(ERROR, !CheckIdType(var_id, PP_ID_TYPE_VAR))
+ << var_id << " is not a PP_Var ID.";
+ VarMap::iterator found = live_vars_.find(var_id);
+ if (found == live_vars_.end()) {
+ NOTREACHED() << "Unref-ing an invalid var";
+ return false;
+ }
+
+ VarInfo& info = found->second;
+ if (info.ref_count == 0) {
+ NOTREACHED() << "Releasing an object with zero ref";
+ return false;
+ }
+ info.ref_count--;
+
+ if (info.ref_count == 0) {
+ if (info.var->GetType() == PP_VARTYPE_OBJECT) {
+ // Objects have special requirements and may not necessarily be released
+ // when the refcount goes to 0.
+ ObjectGettingZeroRef(found);
+ } else {
+ // All other var types can just be released.
+ DCHECK(info.track_with_no_reference_count == 0);
+ live_vars_.erase(found);
+ }
+ }
+ return true;
+}
+
+bool VarTracker::ReleaseVar(const PP_Var& var) {
+ if (!IsVarTypeRefcounted(var.type))
+ return false;
+ return ReleaseVar(static_cast<int32>(var.value.as_id));
+}
+
+int32 VarTracker::AddVarInternal(Var* var, AddVarRefMode mode) {
+ // If the plugin manages to create millions of strings.
+ if (last_var_id_ == std::numeric_limits<int32>::max() >> kPPIdTypeBits)
+ return 0;
+
+ int32 new_id = MakeTypedId(++last_var_id_, PP_ID_TYPE_VAR);
+ live_vars_.insert(std::make_pair(new_id,
+ VarInfo(var, mode == ADD_VAR_TAKE_ONE_REFERENCE ? 1 : 0)));
+
+ return new_id;
+}
+
+VarTracker::VarMap::iterator VarTracker::GetLiveVar(int32 id) {
+ return live_vars_.find(id);
+}
+
+VarTracker::VarMap::iterator VarTracker::GetLiveVar(const PP_Var& var) {
+ return live_vars_.find(static_cast<int32>(var.value.as_id));
+}
+
+VarTracker::VarMap::const_iterator VarTracker::GetLiveVar(
+ const PP_Var& var) const {
+ return live_vars_.find(static_cast<int32>(var.value.as_id));
+}
+
+bool VarTracker::IsVarTypeRefcounted(PP_VarType type) const {
+ return type == PP_VARTYPE_STRING || type == PP_VARTYPE_OBJECT;
+}
+
+void VarTracker::TrackedObjectGettingOneRef(VarMap::const_iterator obj) {
+ // Anybody using tracked objects should override this.
+ NOTREACHED();
+}
+
+void VarTracker::ObjectGettingZeroRef(VarMap::iterator iter) {
+ DeleteObjectInfoIfNecessary(iter);
+}
+
+bool VarTracker::DeleteObjectInfoIfNecessary(VarMap::iterator iter) {
+ if (iter->second.ref_count != 0 ||
+ iter->second.track_with_no_reference_count != 0)
+ return false; // Object still alive.
+ live_vars_.erase(iter);
+ return true;
+}
+
+} // namespace ppapi