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