~ubuntu-branches/ubuntu/saucy/dee/saucy-proposed

« back to all changes in this revision

Viewing changes to src/dee-peer.c

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release, Michal Hruby, Ubuntu daily release
  • Date: 2013-07-18 02:01:41 UTC
  • mfrom: (1.1.32)
  • Revision ID: package-import@ubuntu.com-20130718020141-9j7ginvwipv2ff3s
Tags: 1.2.5ubuntu1+13.10.20130718-0ubuntu1
[ Michal Hruby ]
* Use GWeakRef to make DeePeer and DeeSharedModel more thread-safe.

[ Ubuntu daily release ]
* Automatic snapshot from revision 421

Show diffs side-by-side

added added

removed removed

Lines of Context:
88
88
  
89
89
  /* The GDBus filter id, so we can uninstall our message filter again */
90
90
  guint   filter_id;
91
 
  
 
91
 
92
92
  /* GDBus id for the DBus signal subscriptions */
93
93
  guint   dbus_signals_id;
94
94
 
215
215
 
216
216
static gchar**       dee_peer_real_list_peers       (DeePeer *self);
217
217
 
218
 
  /* GObject methods */
 
218
/* GObject methods */
219
219
static void
220
 
dee_peer_finalize (GObject *object)
 
220
dee_peer_dispose (GObject *object)
221
221
{
222
222
  DeePeerPrivate *priv;
223
223
  GSList *match_iter;
232
232
       * _before_ dropping the swarm name because gdbus currently does a
233
233
       * sync dbus call to release the name which makes us race against
234
234
       * getting a NameOwnerChanged */
 
235
      /* The removal of the filter rules also has to be done in dispose,
 
236
       * not finalize, cause the filter callback can ref this object and
 
237
       * therefore postpone finalization, although that shouldn't happen,
 
238
       * as this uses locking and the call will not return until all current
 
239
       * invocations of the filter callback finish. */
235
240
      g_dbus_connection_remove_filter (priv->connection, priv->filter_id);
236
241
      
237
242
      for (match_iter = priv->match_rules;
253
258
      g_object_unref (priv->connection);
254
259
      priv->connection = NULL;
255
260
    }
 
261
  
 
262
  if (priv->match_rules)
 
263
    {
 
264
      g_slist_free (priv->match_rules);
 
265
      priv->match_rules = NULL;
 
266
    }
256
267
 
257
268
  /* Stop trying to own the swarm name.
258
269
   * See implementation note above */
269
280
      priv->name_watcher_id = 0;
270
281
    }
271
282
 
 
283
  G_OBJECT_CLASS (dee_peer_parent_class)->dispose (object);
 
284
}
 
285
 
 
286
static void
 
287
dee_peer_finalize (GObject *object)
 
288
{
 
289
  DeePeerPrivate *priv;
 
290
 
 
291
  priv = DEE_PEER (object)->priv;
 
292
 
272
293
  if (priv->list_cancellable != NULL)
273
294
    {
274
295
      g_cancellable_cancel (priv->list_cancellable);
288
309
      priv->swarm_path = NULL;
289
310
    }
290
311
  if (priv->swarm_leader)
291
 
      {
292
 
        g_free (priv->swarm_leader);
293
 
        priv->swarm_leader = NULL;
294
 
      }
 
312
    {
 
313
      g_free (priv->swarm_leader);
 
314
      priv->swarm_leader = NULL;
 
315
    }
295
316
  if (priv->peers)
296
317
    {
297
318
      g_hash_table_destroy (priv->peers);
298
319
      priv->peers = NULL;
299
320
    }
300
 
  if (priv->match_rules)
301
 
    {
302
 
      g_slist_free (priv->match_rules);
303
 
      priv->match_rules = NULL;
304
 
    }
305
321
  if (priv->lock != NULL)
306
322
    {
307
323
#if GLIB_CHECK_VERSION(2, 31, 16)
421
437
  GObjectClass *obj_class = G_OBJECT_CLASS (klass);
422
438
  GParamSpec   *pspec;
423
439
 
 
440
  obj_class->dispose      = dee_peer_dispose;
424
441
  obj_class->finalize     = dee_peer_finalize;
425
442
  obj_class->set_property = dee_peer_set_property;
426
443
  obj_class->get_property = dee_peer_get_property;
959
976
  g_free (dummy);
960
977
}
961
978
 
 
979
static void
 
980
dispose_weak_ref (gpointer data)
 
981
{
 
982
  GWeakRef *weak_ref = (GWeakRef*) data;
 
983
  g_weak_ref_clear (weak_ref);
 
984
  g_free (data);
 
985
}
 
986
 
962
987
/* Called when we get the bus connection the first time. */
963
988
static void
964
989
on_bus_acquired (GDBusConnection *connection,
967
992
{
968
993
  DeePeer        *self;
969
994
  DeePeerPrivate *priv;
 
995
  GWeakRef       *weak_ref;
 
996
  GPtrArray      *ptr_array;
970
997
  
971
998
  g_return_if_fail (DEE_IS_PEER (user_data));
972
999
 
977
1004
 
978
1005
  g_signal_emit (self, _peer_signals[CONNECTION_ACQUIRED], 0, priv->connection);
979
1006
 
 
1007
  /* Using GPtrArray as a ref-count container for the weak ref */
 
1008
  weak_ref = (GWeakRef*) g_new (GWeakRef, 1);
 
1009
  g_weak_ref_init (weak_ref, self);
 
1010
  ptr_array = g_ptr_array_new_full (1, dispose_weak_ref);
 
1011
  g_ptr_array_add (ptr_array, weak_ref);
 
1012
 
980
1013
  priv->filter_id = g_dbus_connection_add_filter (priv->connection,
981
1014
                                                  gdbus_message_filter,
982
 
                                                  self, /* self */
983
 
                                                  NULL);
 
1015
                                                  ptr_array,
 
1016
                                                  (GDestroyNotify) g_ptr_array_unref);
984
1017
  
985
1018
  /* Detect when someone joins the swarm */
986
1019
  install_match_rule (self,
1062
1095
 
1063
1096
  self = DEE_PEER (user_data);
1064
1097
  priv = self->priv;
1065
 
  
 
1098
 
1066
1099
  if (priv->is_swarm_leader)
1067
1100
    {      
1068
1101
      /* We signal the change of swarm leadership in on_ping_received(),
1508
1541
static gboolean
1509
1542
transfer_to_mainloop (gpointer *args)
1510
1543
{
 
1544
  GPtrArray *ptr_array;
 
1545
  GWeakRef *weak_ref;
 
1546
  GObject *object;
1511
1547
  GFunc cb = (GFunc) args[0];
1512
1548
 
1513
 
  cb (args[1], args[2]);
1514
 
  g_object_unref (args[1]);
 
1549
  ptr_array = (GPtrArray*) args[1];
 
1550
  weak_ref = (GWeakRef*) g_ptr_array_index (ptr_array, 0);
 
1551
 
 
1552
  object = (GObject*) g_weak_ref_get (weak_ref);
 
1553
  if (object != NULL)
 
1554
    {
 
1555
      cb (object, args[2]);
 
1556
      g_object_unref (object);
 
1557
    }
 
1558
 
 
1559
  g_ptr_array_unref (ptr_array);
1515
1560
  g_free (args[2]);
1516
1561
  g_free (args);
1517
1562
 
1527
1572
gdbus_message_filter (GDBusConnection *connection,
1528
1573
                      GDBusMessage    *msg,
1529
1574
                      gboolean         incoming,
1530
 
                       gpointer        user_data)
 
1575
                      gpointer         user_data)
1531
1576
{
1532
1577
  DeePeer          *self;
1533
1578
  DeePeerPrivate   *priv;
1534
1579
  GVariant         *body;
1535
1580
  GDBusMessageType  msg_type;
1536
 
  gchar            *swarm_name = NULL;
1537
 
  gchar            *peer_address = NULL;
1538
1581
  const gchar      *sender_address;
1539
1582
  gpointer         *data;
1540
 
 
1541
 
  g_return_val_if_fail (DEE_IS_PEER (user_data), msg);
1542
 
 
1543
 
  self = DEE_PEER (user_data);
1544
 
  priv = self->priv;
 
1583
  GPtrArray        *ptr_array;
 
1584
  GWeakRef         *weak_ref;
 
1585
 
 
1586
  ptr_array = (GPtrArray*) user_data;
 
1587
  weak_ref = (GWeakRef*) g_ptr_array_index (ptr_array, 0);
1545
1588
  body = g_dbus_message_get_body (msg);
1546
1589
  sender_address = g_dbus_message_get_sender (msg);
1547
1590
  msg_type = g_dbus_message_get_message_type (msg);
1569
1612
      g_strcmp0 (sender_address, g_dbus_connection_get_unique_name (connection)) != 0 &&
1570
1613
      body != NULL)
1571
1614
    {
 
1615
      gchar *swarm_name;
 
1616
 
 
1617
      self = (DeePeer*) g_weak_ref_get (weak_ref);
 
1618
      if (self == NULL) return msg;
 
1619
      priv = self->priv;
 
1620
 
1572
1621
      g_variant_get (body, "(su)", &swarm_name, NULL);
1573
1622
      if (g_strcmp0 (swarm_name, priv->swarm_name) == 0)
1574
1623
        {
1575
1624
          /* Call on_join_received() in the main loop */
1576
 
          data = g_new (gpointer, 2);
 
1625
          data = g_new (gpointer, 3);
1577
1626
          data[0] = on_join_received;
1578
 
          data[1] = g_object_ref (self);
 
1627
          data[1] = g_ptr_array_ref (ptr_array);
1579
1628
          data[2] = g_strdup (sender_address);
1580
1629
          g_idle_add ((GSourceFunc) transfer_to_mainloop, data);
1581
1630
        }
 
1631
 
 
1632
      g_object_unref (self);
 
1633
      g_free (swarm_name);
1582
1634
    }
1583
1635
  else if (check_signal (msg, "org.freedesktop.DBus", "NameOwnerChanged", NULL) && body != NULL)
1584
 
    {      
1585
 
      gchar *old_address, *new_address;
 
1636
    {
 
1637
      gchar *old_address, *new_address, *peer_address;
1586
1638
      gboolean should_emit_bye;
1587
1639
 
 
1640
      self = (DeePeer*) g_weak_ref_get (weak_ref);
 
1641
      if (self == NULL) return msg;
 
1642
      priv = self->priv;
 
1643
 
1588
1644
      g_variant_get (body, "(sss)", &peer_address, &old_address, &new_address);
1589
1645
 
1590
1646
      /* Check if a known peer dropped off the bus and emit the Bye signal
1603
1659
      if (should_emit_bye)
1604
1660
        {
1605
1661
          /* Call emit_bye() in the main loop */
1606
 
          data = g_new (gpointer, 2);
 
1662
          data = g_new (gpointer, 3);
1607
1663
          data[0] = emit_bye;
1608
 
          data[1] = g_object_ref (self);
 
1664
          data[1] = g_ptr_array_ref (ptr_array);
1609
1665
          data[2] = peer_address; // own
1610
1666
          g_idle_add ((GSourceFunc) transfer_to_mainloop, data);
1611
1667
          peer_address = NULL;
1612
1668
        }
 
1669
      g_object_unref (self);
1613
1670
      g_free (old_address);
1614
1671
      g_free (new_address);
 
1672
      g_free (peer_address);
1615
1673
    }
1616
 
  else if (check_method (msg, DEE_PEER_DBUS_IFACE, "List", priv->swarm_path))
 
1674
  else
1617
1675
    {
1618
 
      /* We don't want to go through the whole GDBus interface/introspection
1619
 
       * setup just to export the List method. We just handle this particular
1620
 
       * method inline */
1621
 
      GDBusMessage *reply;
1622
 
      reply = g_dbus_message_new_method_reply (msg);
1623
 
      g_dbus_message_set_body (reply, build_peer_list (self));
1624
 
      g_dbus_connection_send_message (connection,
1625
 
                                      reply,
1626
 
                                      G_DBUS_SEND_MESSAGE_FLAGS_NONE,
1627
 
                                      NULL,   /* out serial */
1628
 
                                      NULL);  /* error */
1629
 
      g_object_unref (reply);
1630
 
 
1631
 
      /* Convince GDBus that we handled this message by returning NULL */
1632
 
      return NULL;
 
1676
      self = (DeePeer*) g_weak_ref_get (weak_ref);
 
1677
      if (self == NULL) return msg;
 
1678
      priv = self->priv;
 
1679
 
 
1680
      if (check_method (msg, DEE_PEER_DBUS_IFACE, "List", priv->swarm_path))
 
1681
        {
 
1682
          /* We don't want to go through the whole GDBus
 
1683
           * interface/introspection setup just to export the List method.
 
1684
           * We just handle this particular method inline */
 
1685
          GDBusMessage *reply;
 
1686
          reply = g_dbus_message_new_method_reply (msg);
 
1687
          g_dbus_message_set_body (reply, build_peer_list (self));
 
1688
          g_dbus_connection_send_message (connection,
 
1689
                                          reply,
 
1690
                                          G_DBUS_SEND_MESSAGE_FLAGS_NONE,
 
1691
                                          NULL,   /* out serial */
 
1692
                                          NULL);  /* error */
 
1693
          g_object_unref (reply);
 
1694
 
 
1695
          g_object_unref (self);
 
1696
          /* Convince GDBus that we handled this message by returning NULL */
 
1697
          return NULL;
 
1698
        }
 
1699
      g_object_unref (self);
1633
1700
    }
1634
 
  
1635
 
  g_free (swarm_name);
1636
 
  g_free (peer_address);
1637
1701
 
1638
1702
  return msg;
1639
1703
}