OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #ifndef UI_BASE_GTK_G_OBJECT_DESTRUCTOR_FILO_H_ | |
6 #define UI_BASE_GTK_G_OBJECT_DESTRUCTOR_FILO_H_ | |
7 | |
8 #include <glib.h> | |
9 #include <list> | |
10 #include <map> | |
11 | |
12 #include "base/basictypes.h" | |
13 #include "ui/base/ui_base_export.h" | |
14 | |
15 template <typename T> struct DefaultSingletonTraits; | |
16 | |
17 typedef struct _GObject GObject; | |
18 | |
19 namespace ui { | |
20 | |
21 // This class hooks calls to g_object_weak_ref()/unref() and executes them in | |
22 // FILO order. This is important if there are several hooks to the single object | |
23 // (set up at different levels of class hierarchy) and the lowest hook (set up | |
24 // first) is deleting self - it must be called last (among hooks for the given | |
25 // object). Unfortunately Glib does not provide this guarantee. | |
26 // | |
27 // Use it as follows: | |
28 // | |
29 // static void OnDestroyedThunk(gpointer data, GObject *where_the_object_was) { | |
30 // reinterpret_cast<MyClass*>(data)->OnDestroyed(where_the_object_was); | |
31 // } | |
32 // void MyClass::OnDestroyed(GObject *where_the_object_was) { | |
33 // destroyed_ = true; | |
34 // delete this; | |
35 // } | |
36 // MyClass::Init() { | |
37 // ... | |
38 // ui::GObjectDestructorFILO::GetInstance()->Connect( | |
39 // G_OBJECT(my_widget), &OnDestroyedThunk, this); | |
40 // } | |
41 // MyClass::~MyClass() { | |
42 // if (!destroyed_) { | |
43 // ui::GObjectDestructorFILO::GetInstance()->Disconnect( | |
44 // G_OBJECT(my_widget), &OnDestroyedThunk, this); | |
45 // } | |
46 // } | |
47 // | |
48 // TODO(glotov): Probably worth adding ScopedGObjectDtor<T>. | |
49 // | |
50 // This class is a singleton. Not thread safe. Must be called within UI thread. | |
51 class UI_BASE_EXPORT GObjectDestructorFILO { | |
52 public: | |
53 typedef void (*DestructorHook)(void* context, GObject* where_the_object_was); | |
54 | |
55 static GObjectDestructorFILO* GetInstance(); | |
56 void Connect(GObject* object, DestructorHook callback, void* context); | |
57 void Disconnect(GObject* object, DestructorHook callback, void* context); | |
58 | |
59 private: | |
60 struct Hook { | |
61 Hook(GObject* o, DestructorHook cb, void* ctx) | |
62 : object(o), callback(cb), context(ctx) { | |
63 } | |
64 bool equal(GObject* o, DestructorHook cb, void* ctx) const { | |
65 return object == o && callback == cb && context == ctx; | |
66 } | |
67 GObject* object; | |
68 DestructorHook callback; | |
69 void* context; | |
70 }; | |
71 typedef std::list<Hook> HandlerList; | |
72 typedef std::map<GObject*, HandlerList> HandlerMap; | |
73 | |
74 GObjectDestructorFILO(); | |
75 ~GObjectDestructorFILO(); | |
76 friend struct DefaultSingletonTraits<GObjectDestructorFILO>; | |
77 | |
78 void WeakNotify(GObject* where_the_object_was); | |
79 static void WeakNotifyThunk(gpointer data, GObject* where_the_object_was) { | |
80 reinterpret_cast<GObjectDestructorFILO*>(data)->WeakNotify( | |
81 where_the_object_was); | |
82 } | |
83 | |
84 HandlerMap handler_map_; | |
85 | |
86 DISALLOW_COPY_AND_ASSIGN(GObjectDestructorFILO); | |
87 }; | |
88 | |
89 } // namespace ui | |
90 | |
91 #endif // UI_BASE_GTK_G_OBJECT_DESTRUCTOR_FILO_H_ | |
OLD | NEW |