[glibmm] Add Gio:SocketSource, SignalSocket and Socket::create_source()



commit 1e626a1885e99f7fb120505ee2b9427f1fc6c1d1
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Thu May 15 13:09:07 2014 +0200

    Add Gio:SocketSource, SignalSocket and Socket::create_source()
    
    * .gitignore: Add !gio/giomm/socketsource.[cc|h].
    * gio/giomm.h:
    * gio/giomm/filelist.am: Add socketsource.h.
    * gio/giomm/socketsource.[cc|h]: New files. SocketSource and SignalSocket.
    * gio/src/socket.[ccg|hg]: Add create_source().
    Remove many trailing blanks in socket.hg.
    * glib/glibmm/main.[cc|h]: Add functions required when a class derived from
    Source is defined in another file. Bug #725281.

 .gitignore                |    4 ++
 gio/giomm.h               |    1 +
 gio/giomm/filelist.am     |    4 +-
 gio/giomm/socketsource.cc |  101 +++++++++++++++++++++++++++++++++++++++
 gio/giomm/socketsource.h  |  115 +++++++++++++++++++++++++++++++++++++++++++++
 gio/src/socket.ccg        |    9 ++++
 gio/src/socket.hg         |  107 ++++++++++++++++++++++++++----------------
 glib/glibmm/main.cc       |   39 +++++++++++++++
 glib/glibmm/main.h        |   23 +++++++--
 9 files changed, 357 insertions(+), 46 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index a472604..d5a8d64 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,10 +84,12 @@ giommconfig.h
 !/gio/giomm/contenttype.cc
 !/gio/giomm/init.cc
 !/gio/giomm/slot_async.cc
+!/gio/giomm/socketsource.cc
 /gio/giomm/*.h
 !/gio/giomm/contenttype.h
 !/gio/giomm/init.h
 !/gio/giomm/slot_async.h
+!/gio/giomm/socketsource.h
 !/gio/giomm/wrap_init.h
 
 # glib/
@@ -149,6 +151,8 @@ giommconfig.h
 /glib/glibmm/variant.h
 /glib/glibmm/variant_basictypes.cc
 /glib/glibmm/variant_basictypes.h
+/glib/glibmm/variantdict.cc
+/glib/glibmm/variantdict.h
 /glib/glibmm/variantiter.cc
 /glib/glibmm/variantiter.h
 /glib/glibmm/varianttype.cc
diff --git a/gio/giomm.h b/gio/giomm.h
index 5f31f09..1199a2f 100644
--- a/gio/giomm.h
+++ b/gio/giomm.h
@@ -124,6 +124,7 @@
 #include <giomm/socketcontrolmessage.h>
 #include <giomm/socketlistener.h>
 #include <giomm/socketservice.h>
+#include <giomm/socketsource.h>
 #include <giomm/srvtarget.h>
 #include <giomm/tcpconnection.h>
 #include <giomm/themedicon.h>
diff --git a/gio/giomm/filelist.am b/gio/giomm/filelist.am
index ceee372..24c0784 100644
--- a/gio/giomm/filelist.am
+++ b/gio/giomm/filelist.am
@@ -4,6 +4,6 @@ giomm_files_built_cc = $(giomm_files_used_hg:.hg=.cc) wrap_init.cc
 giomm_files_built_h  = $(giomm_files_used_hg:.hg=.h)
 giomm_files_built_ph = $(patsubst %.hg,private/%_p.h,$(giomm_files_used_hg))
 
-giomm_files_extra_cc = contenttype.cc init.cc slot_async.cc
-giomm_files_extra_h  = contenttype.h init.h wrap_init.h
+giomm_files_extra_cc = contenttype.cc init.cc slot_async.cc socketsource.cc
+giomm_files_extra_h  = contenttype.h init.h socketsource.h wrap_init.h
 giomm_files_extra_ph =
diff --git a/gio/giomm/socketsource.cc b/gio/giomm/socketsource.cc
new file mode 100644
index 0000000..f17b41a
--- /dev/null
+++ b/gio/giomm/socketsource.cc
@@ -0,0 +1,101 @@
+/* Copyright (C) 2014 The giomm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <giomm/socketsource.h>
+#include <giomm/socket.h>
+#include <glibmm/exceptionhandler.h>
+#include <glibmm/wrap.h>
+#include <gio/gio.h>
+
+namespace
+{
+
+gboolean giomm_generic_socket_callback(sigc::slot_base* slot, GIOCondition condition)
+{
+  g_return_val_if_fail(slot != 0, 0);
+
+  try
+  {
+    // Recreate the specific slot from the generic slot node.
+    return (*static_cast<sigc::slot<bool, Glib::IOCondition>*>(slot))((Glib::IOCondition)condition);
+  }
+  catch (...)
+  {
+    Glib::exception_handlers_invoke();
+  }
+  return 0;
+}
+
+gboolean giomm_signalsocket_callback(GSocket*, GIOCondition condition, void* user_data)
+{
+  sigc::slot_base* const slot = Glib::Source::get_slot_from_connection_node(user_data);
+  return giomm_generic_socket_callback(slot, condition);
+}
+
+gboolean giomm_socketsource_callback(GSocket*, GIOCondition condition, void* user_data)
+{
+  sigc::slot_base* const slot = Glib::Source::get_slot_from_callback_data(user_data);
+  return giomm_generic_socket_callback(slot, condition);
+}
+
+} // anonymous namespace
+
+
+namespace Gio
+{
+
+/**** Glib::SignalSocket *******************************************************/
+
+inline
+SignalSocket::SignalSocket(GMainContext* context)
+:
+  context_(context)
+{}
+
+sigc::connection SignalSocket::connect(const sigc::slot<bool,Glib::IOCondition>& slot,
+                                       const Glib::RefPtr<Socket>& socket, Glib::IOCondition condition,
+                                       const Glib::RefPtr<Cancellable>& cancellable, int priority)
+{
+  GSource* const source = g_socket_create_source(socket->gobj(), (GIOCondition)condition, 
Glib::unwrap(cancellable));
+  return Glib::Source::attach_signal_source(slot, priority, source, context_,
+                                            (GSourceFunc)&giomm_signalsocket_callback);
+}
+
+SignalSocket signal_socket(const Glib::RefPtr<Glib::MainContext>& context)
+{
+  return SignalSocket(Glib::unwrap(context)); // 0 means default context
+}
+
+/**** Glib::SocketSource *******************************************************/
+
+// static
+Glib::RefPtr<SocketSource> SocketSource::create(const Glib::RefPtr<Socket>& socket, Glib::IOCondition 
condition,
+                                                const Glib::RefPtr<Cancellable>& cancellable)
+{
+  return Glib::RefPtr<SocketSource>(new SocketSource(socket, condition, cancellable));
+}
+
+SocketSource::SocketSource(const Glib::RefPtr<Socket>& socket, Glib::IOCondition condition,
+                           const Glib::RefPtr<Cancellable>& cancellable)
+:
+  IOSource(g_socket_create_source(socket->gobj(), (GIOCondition)condition, Glib::unwrap(cancellable)),
+           (GSourceFunc)&giomm_socketsource_callback)
+{}
+
+SocketSource::~SocketSource()
+{}
+
+} // namespace Gio
diff --git a/gio/giomm/socketsource.h b/gio/giomm/socketsource.h
new file mode 100644
index 0000000..f166d75
--- /dev/null
+++ b/gio/giomm/socketsource.h
@@ -0,0 +1,115 @@
+#ifndef _GIOMM_SOCKETSOURCE_H
+#define _GIOMM_SOCKETSOURCE_H
+
+/* Copyright (C) 2014 The giomm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glibmm/refptr.h>
+#include <glibmm/main.h>
+#include <glibmm/priorities.h>
+#include <giomm/cancellable.h>
+#include <sigc++/sigc++.h>
+
+namespace Gio
+{
+class Socket;
+
+/** @newin{2,42}
+ * @ingroup NetworkIO
+ */
+class SignalSocket
+{
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  explicit inline SignalSocket(GMainContext* context);
+#endif
+
+  /** Connects an I/O handler that watches a socket.
+   * @code
+   * bool io_handler(Glib::IOCondition io_condition) { ... }
+   * Gio::signal_socket().connect(sigc::ptr_fun(&io_handler), socket, Glib::IO_IN | Glib::IO_OUT);
+   * @endcode
+   * is equivalent to:
+   * @code
+   * bool io_handler(Glib::IOCondition io_condition) { ... }
+   * const Glib::RefPtr<Gio::SocketSource> socket_source = Gio::SocketSource::create(socket, Glib::IO_IN | 
Glib::IO_OUT);
+   * socket_source->connect(sigc::ptr_fun(&io_handler));
+   * socket_source->attach(Glib::MainContext::get_default());
+   * @endcode
+   *
+   * This method is not thread-safe. You should call it, or manipulate the
+   * returned sigc::connection object, only from the thread where the SignalSocket
+   * object's MainContext runs.
+   *
+   * @newin{2,42}
+   * @param slot A slot to call when polling @a socket results in an event that matches @a condition.
+   * The event will be passed as a parameter to @a slot.
+   * If <tt>io_handler()</tt> returns <tt>false</tt> the handler is disconnected.
+   * @param socket The Socket object to watch.
+   * @param condition The conditions to watch for.
+   * @param cancellable A Cancellable object which can be used to cancel the source,
+   *        which will cause the source to trigger, reporting the current condition
+   *        (which is likely 0 unless cancellation happened at the same time as a condition change).
+   *        You can check for this in the callback using Cancellable::is_cancelled().
+   * @param priority The priority of the new event source.
+   * @return A connection handle, which can be used to disconnect the handler.
+   */
+  sigc::connection connect(const sigc::slot<bool, Glib::IOCondition>& slot,
+    const Glib::RefPtr<Socket>& socket, Glib::IOCondition condition,
+    const Glib::RefPtr<Cancellable>& cancellable = Glib::RefPtr<Cancellable>(),
+    int priority = Glib::PRIORITY_DEFAULT);
+
+private:
+  GMainContext* context_;
+
+  // no copy assignment
+  SignalSocket& operator=(const SignalSocket&);
+};
+
+
+/** Convenience socket signal.
+ * @param context The main context to which the signal shall be attached.
+ * @return A signal proxy; you want to use SignalSocket::connect().
+ *
+ * @newin{2,42}
+ * @ingroup NetworkIO
+ */
+SignalSocket signal_socket(const Glib::RefPtr<Glib::MainContext>& context = 
Glib::RefPtr<Glib::MainContext>());
+
+
+/** An event source that can monitor a Gio::Socket.
+ * @see Gio::Socket::create_source().
+ *
+ * @newin{2,42}
+ * @ingroup NetworkIO
+ */
+class SocketSource : public Glib::IOSource
+{
+public:
+  typedef Gio::SocketSource CppObjectType;
+
+  static Glib::RefPtr<SocketSource> create(const Glib::RefPtr<Socket>& socket, Glib::IOCondition condition,
+    const Glib::RefPtr<Cancellable>& cancellable = Glib::RefPtr<Cancellable>());
+
+protected:
+  SocketSource(const Glib::RefPtr<Socket>& socket, Glib::IOCondition condition,
+    const Glib::RefPtr<Cancellable>& cancellable);
+  virtual ~SocketSource();
+};
+
+} // namespace Gio
+
+#endif /* _GIOMM_SOCKETSOURCE_H */
diff --git a/gio/src/socket.ccg b/gio/src/socket.ccg
index db7b095..7a4a211 100644
--- a/gio/src/socket.ccg
+++ b/gio/src/socket.ccg
@@ -20,6 +20,7 @@
 #include <gio/gio.h>
 #include <glibmm/error.h>
 #include <giomm/asyncresult.h>
+#include <giomm/socketsource.h>
 #include "slot_async.h"
 
 namespace Gio
@@ -105,4 +106,12 @@ gssize Socket::send_with_blocking(gchar* buffer, gsize size, bool blocking,
   return retvalue;
 }
 
+Glib::RefPtr<SocketSource> Socket::create_source(Glib::IOCondition condition, const 
Glib::RefPtr<Cancellable>& cancellable)
+{
+  // The corresponding unreference() takes place in the dtor
+  // of the Glib::RefPtr<Socket> object below.
+  reference();
+  return SocketSource::create(Glib::RefPtr<Socket>(this), condition, cancellable);
+}
+
 } // namespace Gio
diff --git a/gio/src/socket.hg b/gio/src/socket.hg
index f0bce7b..55236a4 100644
--- a/gio/src/socket.hg
+++ b/gio/src/socket.hg
@@ -31,6 +31,7 @@ _PINCLUDE(glibmm/private/object_p.h)
 
 namespace Gio
 {
+class SocketSource;
 
 _WRAP_ENUM(SocketType, GSocketType)
 _WRAP_ENUM(SocketProtocol, GSocketProtocol)
@@ -120,36 +121,36 @@ public:
   static Glib::RefPtr<Socket> create_from_fd(int fd, const Glib::RefPtr<Cancellable>&
                                              cancellable = Glib::RefPtr<Cancellable>());
 
-  /** When a socket is created it is attached to an address family, but it doesn't 
-   * have an address in this family. Socket::bind() assigns the address (sometimes 
+  /** When a socket is created it is attached to an address family, but it doesn't
+   * have an address in this family. Socket::bind() assigns the address (sometimes
    * called name) of the socket.
    *
-   * It is generally required to bind to a local address before you can receive 
-   * connections. (See Socket::listen() and Socket::accept()). In certain situations, 
-   * you may also want to bind a socket that will be used to initiate connections, 
+   * It is generally required to bind to a local address before you can receive
+   * connections. (See Socket::listen() and Socket::accept()). In certain situations,
+   * you may also want to bind a socket that will be used to initiate connections,
    * though this is not normally required.
    *
-   * If socket is a TCP socket, then @a allow_reuse controls the setting of the SO_REUSEADDR 
-   * socket option; normally it should be <tt>true</tt> for server sockets (sockets that you 
-   * will eventually call Socket::accept() on), and <tt>false</tt> for client sockets. 
-   * (Failing to set this flag on a server socket may cause Socket::bind() to 
-   * throw Gio::Error with ADDRESS_IN_USE if the server program 
+   * If socket is a TCP socket, then @a allow_reuse controls the setting of the SO_REUSEADDR
+   * socket option; normally it should be <tt>true</tt> for server sockets (sockets that you
+   * will eventually call Socket::accept() on), and <tt>false</tt> for client sockets.
+   * (Failing to set this flag on a server socket may cause Socket::bind() to
+   * throw Gio::Error with ADDRESS_IN_USE if the server program
    * is stopped and then immediately restarted.)
    *
-   * If socket is a UDP socket, then @a allow_reuse determines whether or not 
-   * other UDP sockets can be bound to the same address at the same time. In particular, 
-   * you can have several UDP sockets bound to the same address, and they will all 
-   * receive all of the multicast and broadcast packets sent to that address. 
+   * If socket is a UDP socket, then @a allow_reuse determines whether or not
+   * other UDP sockets can be bound to the same address at the same time. In particular,
+   * you can have several UDP sockets bound to the same address, and they will all
+   * receive all of the multicast and broadcast packets sent to that address.
    * (The behavior of unicast UDP packets to an address with multiple listeners is not defined.)
    *
-   * @param address a SocketAddress specifying the local address.       
+   * @param address a SocketAddress specifying the local address.
    * @param allow_reuse whether to allow reusing this address
    *
    * @throw Gio::Error
    */
   _WRAP_METHOD(void bind(const Glib::RefPtr<SocketAddress>& address, bool allow_reuse), g_socket_bind, 
errthrow)
-  
-  /** Marks the socket as a server socket - a socket that is used to accept 
+
+  /** Marks the socket as a server socket - a socket that is used to accept
    * incoming requests using Socket::accept().
    *
    * Before calling this the socket must be bound to a local address using Socket::bind().
@@ -159,17 +160,17 @@ public:
    * @throw Gio::Error
    */
   _WRAP_METHOD(void listen(), g_socket_listen, errthrow)
-  
-  /** Accept incoming connections on a connection-based socket. This removes the 
-   * first outstanding connection request from the listening socket and creates 
+
+  /** Accept incoming connections on a connection-based socket. This removes the
+   * first outstanding connection request from the listening socket and creates
    * a GSocket object for it.
-   * 
-   * The socket must be bound to a local address with g_socket_bind() and must 
+   *
+   * The socket must be bound to a local address with g_socket_bind() and must
    * be listening for incoming connections (Socket::listen()).
    *
-   * If there are no outstanding connections then the operation will block or 
-   * throw Gio::Error with ERROR_WOULD_BLOCK if non-blocking 
-   * I/O is enabled. To be notified of an incoming connection, wait for the 
+   * If there are no outstanding connections then the operation will block or
+   * throw Gio::Error with ERROR_WOULD_BLOCK if non-blocking
+   * I/O is enabled. To be notified of an incoming connection, wait for the
    * Glib::IO_IN condition.
    *
    * @param cancellable A Cancellable object which can be used to cancel the operation.
@@ -182,20 +183,20 @@ public:
 
   /** Connect the socket to the specified remote address.
    *
-   * For connection oriented socket this generally means we attempt to make a 
-   * connection to the address . For a connection-less socket it sets the default 
+   * For connection oriented socket this generally means we attempt to make a
+   * connection to the address . For a connection-less socket it sets the default
    * address for Socket::send() and discards all incoming datagrams from other sources.
    *
-   * Generally connection oriented sockets can only connect once, but 
+   * Generally connection oriented sockets can only connect once, but
    * connection-less sockets can connect multiple times to change the default address.
    *
-   * If the connect call needs to do network I/O it will block, unless non-blocking 
-   * I/O is enabled. Then Gio::Error with ERROR_PENDING is thrown 
-   * and the user can be notified of the connection finishing by waiting for the 
-   * Glib::IO_OUT condition. The result of the connection must then be checked 
+   * If the connect call needs to do network I/O it will block, unless non-blocking
+   * I/O is enabled. Then Gio::Error with ERROR_PENDING is thrown
+   * and the user can be notified of the connection finishing by waiting for the
+   * Glib::IO_OUT condition. The result of the connection must then be checked
    * with Socket::check_connect_result().
    *
-   * @param address    a SocketAddress specifying the remote address.   
+   * @param address    a SocketAddress specifying the remote address.
    * @param cancellable        A Cancellable object which can be used to cancel the operation.
    *
    * @throw Gio::Error
@@ -223,17 +224,43 @@ public:
   _WRAP_METHOD(void close(), g_socket_close, errthrow)
   _WRAP_METHOD(bool is_closed(), g_socket_is_closed)
 
-  //TODO: Glib::Source has no wrap() method: _WRAP_METHOD(Glib::RefPtr<Glib::Source> 
create_source(Glib::IOCondition condition, const Glib::RefPtr<Cancellable>& cancellable{?}), 
g_socket_create_source)
+  /** Creates a SocketSource that can be attached to a Glib::MainContext to monitor
+   * for the availability of the specified @a condition on the socket.
+   *
+   * Create a slot from a function to be called when @a condition is met
+   * for the socket with sigc::ptr_fun() or sigc::mem_fun() and pass
+   * it into the connect() function of the returned SocketSource object.
+   * Polling of the socket will start when you attach a Glib::MainContext
+   * object to the returned SocketSource object using its attach() function.
+   *
+   * It is meaningless to specify Glib::IO_ERR or Glib::IO_HUP in @a condition;
+   * these conditions will always be reported output if they are true.
+   *
+   * @a cancellable can be used to cancel the source, which will
+   * cause the source to trigger, reporting the current condition (which
+   * is likely 0 unless cancellation happened at the same time as a
+   * condition change). You can check for this in the callback using
+   * Cancellable::is_cancelled().
+   *
+   * If the socket has a timeout set, and it is reached before @a condition
+   * occurs, the source will then trigger anyway, reporting Glib::IO_IN or
+   * Glib::IO_OUT depending on @a condition. However, the socket will have been
+   * marked as having had a timeout, and so the next Socket I/O method
+   * you call will then fail with a Gio::IO_ERROR_TIMED_OUT.
+   *
+   * Gio::signal_socket().connect() is a simpler interface to the same functionality.
+   *
+   * @newin{2,42}
+   * @param condition A Glib::IOCondition mask to monitor.
+   * @param cancellable A Cancellable. The default value means the source is not cancellable.
+   * @return A newly allocated SocketSource.
+   */
+  Glib::RefPtr<SocketSource> create_source(Glib::IOCondition condition, const Glib::RefPtr<Cancellable>& 
cancellable = Glib::RefPtr<Cancellable>());
+  _IGNORE(g_socket_create_source)
 
   _WRAP_METHOD(void shutdown(bool shutdown_read, bool shutdown_write), g_socket_shutdown, errthrow)
   _WRAP_METHOD(bool is_connected(), g_socket_is_connected)
 
-  // TODO: non-cancellable version
-  // This won't work because Glib::Source is abstract, and Glib::IOSource has no
-  // constructor that takes a GSource*
-//#m4 _CONVERSION(`GSource*',`Glib::RefPtr<Glib::Source>',`Glib::RefPtr<Glib::Source>(new 
::Glib::Source($3))')
-  //_WRAP_METHOD(Glib::RefPtr<Glib::Source> create_source(Glib::IOCondition condition, const 
Glib::RefPtr<Cancellable>& cancellable{?}), g_socket_create_source)
-
   _WRAP_METHOD(gssize get_available_bytes() const,  g_socket_get_available_bytes)
 
   _WRAP_METHOD(Glib::IOCondition condition_check(Glib::IOCondition condition), g_socket_condition_check)
diff --git a/glib/glibmm/main.cc b/glib/glibmm/main.cc
index f6707b7..1d9d915 100644
--- a/glib/glibmm/main.cc
+++ b/glib/glibmm/main.cc
@@ -1064,6 +1064,40 @@ void Source::destroy_notify_callback(void* data)
   }
 }
 
+// static
+sigc::connection Source::attach_signal_source(const sigc::slot_base& slot, int priority,
+  GSource* source, GMainContext* context, GSourceFunc callback_func)
+{
+  SourceConnectionNode* const conn_node = new SourceConnectionNode(slot);
+  const sigc::connection connection(*conn_node->get_slot());
+
+  if (priority != G_PRIORITY_DEFAULT)
+    g_source_set_priority(source, priority);
+
+  g_source_set_callback(source, callback_func, conn_node,
+                        &SourceConnectionNode::destroy_notify_callback);
+
+  conn_node->install(source);
+  g_source_attach(source, context);
+  g_source_unref(source); // GMainContext holds a reference
+
+  return connection;
+}
+
+// static
+sigc::slot_base* Source::get_slot_from_connection_node(void* data)
+{
+  return static_cast<SourceConnectionNode*>(data)->get_slot();
+}
+
+// static
+sigc::slot_base* Source::get_slot_from_callback_data(void* data)
+{
+  SourceCallbackData* const callback_data = static_cast<SourceCallbackData*>(data);
+  g_return_val_if_fail(callback_data->node != 0, 0);
+  return callback_data->node->get_slot();
+}
+
 
 /**** Glib::TimeoutSource **************************************************/
 
@@ -1229,6 +1263,11 @@ IOSource::IOSource(const Glib::RefPtr<IOChannel>& channel, IOCondition condition
          (GSourceFunc) &glibmm_iosource_callback)
 {}
 
+IOSource::IOSource(GSource* cast_item, GSourceFunc callback_func)
+:
+  Source(cast_item, callback_func)
+{}
+
 IOSource::~IOSource()
 {}
 
diff --git a/glib/glibmm/main.h b/glib/glibmm/main.h
index 0664610..94d495c 100644
--- a/glib/glibmm/main.h
+++ b/glib/glibmm/main.h
@@ -784,8 +784,7 @@ protected:
 private:
   GSource* gobject_;
 
-#ifndef DOXGEN_SHOULD_SKIP_THIS
-
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
   static inline Source* get_wrapper(GSource* source);
 
   static const GSourceFuncs vfunc_table_;
@@ -793,11 +792,19 @@ private:
   static gboolean prepare_vfunc(GSource* source, int* timeout);
   static gboolean check_vfunc(GSource* source);
   static gboolean dispatch_vfunc(GSource* source, GSourceFunc callback, void* user_data);
+
 public:
   static void destroy_notify_callback(void* data);
-private:
+  // Used by SignalXyz, possibly in other files.
+  static sigc::connection attach_signal_source(const sigc::slot_base& slot, int priority,
+    GSource* source, GMainContext* context, GSourceFunc callback_func);
+  // Used by SignalXyz in other files.
+  static sigc::slot_base* get_slot_from_connection_node(void* data);
+  // Used by derived Source classes in other files.
+  static sigc::slot_base* get_slot_from_callback_data(void* data);
 
-#endif /* DOXGEN_SHOULD_SKIP_THIS */
+private:
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
 
   // noncopyable
   Source(const Source&);
@@ -859,6 +866,14 @@ public:
 protected:
   IOSource(int fd, IOCondition condition);
   IOSource(const Glib::RefPtr<IOChannel>& channel, IOCondition condition);
+
+  /** Wrap an existing GSource object and install the given callback function.
+   * This constructor is for use by derived types that need to wrap a GSource object.
+   * @see Source::Source(GSource*, GSourceFunc).
+   * @newin{2,42}
+   */
+  IOSource(GSource* cast_item, GSourceFunc callback_func);
+
   virtual ~IOSource();
 
   virtual bool prepare(int& timeout);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]