~ci-train-bot/unity/unity-ubuntu-artful-2985

« back to all changes in this revision

Viewing changes to UnityCore/GLibSignal.cpp

  • Committer: Bileto Bot
  • Author(s): Marco Trevisan (Treviño)
  • Date: 2017-07-21 08:51:47 UTC
  • mfrom: (4245.2.8 glib-signals-blocking)
  • Revision ID: ci-train-bot@canonical.com-20170721085147-igxr8b0w8wpe0fj8
GLibSignal: allow to block, unblock signals

Added support also to SignalManager, changed a bit the interface

Approved by: Andrea Azzarone

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
  Disconnect();
36
36
}
37
37
 
38
 
void SignalBase::Disconnect()
 
38
bool SignalBase::Disconnect()
39
39
{
 
40
  bool disconnected = false;
 
41
 
40
42
  if (connection_id_ && G_IS_OBJECT(object_))
41
43
  {
42
44
    g_signal_handler_disconnect(object_, connection_id_);
43
45
    g_object_remove_weak_pointer(object_, reinterpret_cast<gpointer*>(&object_));
 
46
    disconnected = true;
44
47
  }
45
48
 
46
49
  object_ = nullptr;
47
50
  connection_id_ = 0;
 
51
  return disconnected;
 
52
}
 
53
 
 
54
bool SignalBase::Block() const
 
55
{
 
56
  bool blocked = false;
 
57
 
 
58
  if (connection_id_ && G_IS_OBJECT(object_))
 
59
  {
 
60
    g_signal_handler_block(object_, connection_id_);
 
61
    blocked = true;
 
62
  }
 
63
 
 
64
  return blocked;
 
65
}
 
66
 
 
67
bool SignalBase::Unblock() const
 
68
{
 
69
  bool unblocked = false;
 
70
 
 
71
  if (connection_id_ && G_IS_OBJECT(object_))
 
72
  {
 
73
    g_signal_handler_unblock(object_, connection_id_);
 
74
    unblocked = true;
 
75
  }
 
76
 
 
77
  return unblocked;
48
78
}
49
79
 
50
80
GObject* SignalBase::object() const
75
105
// was too messy to try and write a copy constructor/operator that would steal
76
106
// from "other" and make the new one the owner. Not only did it create
77
107
// opportunity for random bugs, it also made the API bad.
78
 
void SignalManager::Add(SignalBase* signal)
 
108
SignalBase::Ptr SignalManager::Add(SignalBase* signal)
79
109
{
80
 
  Add(SignalBase::Ptr(signal));
 
110
  return Add(SignalBase::Ptr(signal));
81
111
}
82
112
 
83
 
void SignalManager::Add(SignalBase::Ptr const& signal)
 
113
SignalBase::Ptr SignalManager::Add(SignalBase::Ptr const& signal)
84
114
{
85
115
  connections_.push_back(signal);
86
116
  g_object_weak_ref(signal->object(), (GWeakNotify)&OnObjectDestroyed, this);
87
 
}
88
 
 
89
 
void SignalManager::OnObjectDestroyed(SignalManager* self, GObject* old_obj)
90
 
{
91
 
  for (auto it = self->connections_.begin(); it != self->connections_.end();)
92
 
  {
93
 
    auto const& signal = *it;
94
 
 
95
 
    // When an object has been destroyed, the signal member is nullified,
96
 
    // so at this point we can be sure that removing signal with a null object,
97
 
    // means removing invalid signals.
98
 
    if (!signal->object())
99
 
    {
100
 
      it = self->connections_.erase(it);
101
 
    }
102
 
    else
103
 
    {
104
 
      ++it;
105
 
    }
106
 
  }
 
117
  return signal;
107
118
}
108
119
 
109
120
// This uses void* to keep in line with the g_signal* functions
110
121
// (it allows you to pass in a GObject without casting up).
111
 
void SignalManager::Disconnect(void* object, std::string const& signal_name)
 
122
bool SignalManager::ForeachMatchedSignal(void* object, std::string const& signal_name, std::function<void(SignalBase::Ptr const&)> action, bool erase_after)
112
123
{
113
 
  bool all_signals = signal_name.empty();
 
124
  bool action_performed = false;
 
125
  bool all_objects = (object == reinterpret_cast<void*>(std::numeric_limits<uintptr_t>::max()));
 
126
  bool all_signals = all_objects || signal_name.empty();
114
127
 
115
128
  for (auto it = connections_.begin(); it != connections_.end();)
116
129
  {
117
130
    auto const& signal = *it;
118
131
 
119
 
    if (signal->object() == object && (all_signals || signal->name() == signal_name))
 
132
    if ((all_objects || signal->object() == object) && (all_signals || signal->name() == signal_name))
120
133
    {
121
 
      g_object_weak_unref(signal->object(), (GWeakNotify)&OnObjectDestroyed, this);
122
 
      it = connections_.erase(it);
 
134
      if (action)
 
135
      {
 
136
        action_performed = true;
 
137
        action(signal);
 
138
      }
 
139
 
 
140
      it = erase_after ? connections_.erase(it) : ++it;
123
141
    }
124
142
    else
125
143
    {
126
144
      ++it;
127
145
    }
128
146
  }
 
147
 
 
148
  return action_performed;
 
149
}
 
150
 
 
151
void SignalManager::OnObjectDestroyed(SignalManager* self, GObject* old_obj)
 
152
{
 
153
  self->ForeachMatchedSignal(nullptr, "", nullptr, /*erase_after*/ true);
 
154
}
 
155
 
 
156
bool SignalManager::Block(void* object, std::string const& signal_name)
 
157
{
 
158
  return ForeachMatchedSignal(object, signal_name, [this] (SignalBase::Ptr const& signal) {
 
159
    signal->Block();
 
160
  });
 
161
}
 
162
 
 
163
bool SignalManager::Unblock(void* object, std::string const& signal_name)
 
164
{
 
165
  return ForeachMatchedSignal(object, signal_name, [this] (SignalBase::Ptr const& signal) {
 
166
    signal->Unblock();
 
167
  });
 
168
}
 
169
 
 
170
bool SignalManager::Disconnect(void* object, std::string const& signal_name)
 
171
{
 
172
  return ForeachMatchedSignal(object, signal_name, [this] (SignalBase::Ptr const& signal) {
 
173
    g_object_weak_unref(signal->object(), (GWeakNotify)&OnObjectDestroyed, this);
 
174
  }, true);
129
175
}
130
176
 
131
177
}