• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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