Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / libgtk2ui / g_object_destructor_filo.cc
blob54ed7eec94741ae1f2a2240ed196df2ba2a47e13
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
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/libgtk2ui/g_object_destructor_filo.h"
7 #include <glib-object.h>
9 #include "base/logging.h"
10 #include "base/memory/singleton.h"
12 namespace libgtk2ui {
14 GObjectDestructorFILO::GObjectDestructorFILO() {
17 GObjectDestructorFILO::~GObjectDestructorFILO() {
18 // Probably CHECK(handler_map_.empty()) would look natural here. But
19 // some tests (some views_unittests) violate this assertion.
22 // static
23 GObjectDestructorFILO* GObjectDestructorFILO::GetInstance() {
24 return base::Singleton<GObjectDestructorFILO>::get();
27 void GObjectDestructorFILO::Connect(
28 GObject* object, DestructorHook callback, void* context) {
29 const Hook hook(object, callback, context);
30 HandlerMap::iterator iter = handler_map_.find(object);
31 if (iter == handler_map_.end()) {
32 g_object_weak_ref(object, WeakNotifyThunk, this);
33 handler_map_[object].push_front(hook);
34 } else {
35 iter->second.push_front(hook);
39 void GObjectDestructorFILO::Disconnect(
40 GObject* object, DestructorHook callback, void* context) {
41 HandlerMap::iterator iter = handler_map_.find(object);
42 if (iter == handler_map_.end()) {
43 LOG(DFATAL) << "Unable to disconnect destructor hook for object " << object
44 << ": hook not found (" << callback << ", " << context << ").";
45 return;
47 HandlerList& dtors = iter->second;
48 if (dtors.empty()) {
49 LOG(DFATAL) << "Destructor list is empty for specified object " << object
50 << " Maybe it is being executed?";
51 return;
53 if (!dtors.front().equal(object, callback, context)) {
54 // Reenable this warning once this bug is fixed:
55 // http://code.google.com/p/chromium/issues/detail?id=85603
56 DVLOG(1) << "Destructors should be unregistered the reverse order they "
57 << "were registered. But for object " << object << " "
58 << "deleted hook is "<< context << ", the last queued hook is "
59 << dtors.front().context;
61 for (HandlerList::iterator i = dtors.begin(); i != dtors.end(); ++i) {
62 if (i->equal(object, callback, context)) {
63 dtors.erase(i);
64 break;
67 if (dtors.empty()) {
68 g_object_weak_unref(object, WeakNotifyThunk, this);
69 handler_map_.erase(iter);
73 void GObjectDestructorFILO::WeakNotify(GObject* where_the_object_was) {
74 HandlerMap::iterator iter = handler_map_.find(where_the_object_was);
75 DCHECK(iter != handler_map_.end());
76 DCHECK(!iter->second.empty());
78 // Save destructor list for given object into local copy to avoid reentrancy
79 // problem: if callee wants to modify the caller list.
80 HandlerList dtors;
81 iter->second.swap(dtors);
82 handler_map_.erase(iter);
84 // Execute hooks in local list in FILO order.
85 for (HandlerList::iterator i = dtors.begin(); i != dtors.end(); ++i)
86 i->callback(i->context, where_the_object_was);
89 } // namespace libgtk2ui