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"
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.
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
);
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
<< ").";
47 HandlerList
& dtors
= iter
->second
;
49 LOG(DFATAL
) << "Destructor list is empty for specified object " << object
50 << " Maybe it is being executed?";
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
)) {
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.
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