Imported Upstream version 2.51.6 upstream/2.51.6
authorDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 7 Sep 2020 07:18:41 +0000 (00:18 -0700)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 7 Sep 2020 07:18:41 +0000 (00:18 -0700)
135 files changed:
.gitignore
NEWS
configure.ac
docs/Makefile_web.am_fragment
examples/Makefile.am
examples/child_watch/main.cc
examples/network/socket-client.cc
examples/network/socket-server.cc
examples/thread/thread.cc [new file with mode: 0644]
examples/thread/threadpool.cc [new file with mode: 0644]
gio/giomm.h
gio/giomm/socketsource.cc
gio/giomm/socketsource.h
gio/src/action.hg
gio/src/actiongroup.hg
gio/src/actionmap.ccg
gio/src/actionmap.hg
gio/src/appinfo.hg
gio/src/application.ccg
gio/src/application.hg
gio/src/asyncresult.hg
gio/src/bufferedinputstream.hg
gio/src/cancellable.hg
gio/src/dbusactiongroup.hg
gio/src/dbusconnection.hg
gio/src/dbusinterface.hg
gio/src/dbusinterfacevtable.hg
gio/src/dbusownname.hg
gio/src/dbusproxy.hg
gio/src/dbussubtreevtable.hg
gio/src/dbuswatchname.hg
gio/src/desktopappinfo.hg
gio/src/drive.hg
gio/src/file.hg
gio/src/fileinfo.hg
gio/src/fileiostream.hg
gio/src/filelist.am
gio/src/fileoutputstream.hg
gio/src/gio_vfuncs.defs
gio/src/inputstream.hg
gio/src/liststore.hg
gio/src/memoryinputstream.ccg
gio/src/memoryinputstream.hg
gio/src/menu.hg
gio/src/menuattributeiter.hg
gio/src/menuitem.ccg
gio/src/menuitem.hg
gio/src/menumodel.hg
gio/src/mount.hg
gio/src/mountoperation.hg
gio/src/networkmonitor.hg
gio/src/notification.hg
gio/src/outputstream.hg
gio/src/pollableinputstream.hg
gio/src/pollableoutputstream.hg
gio/src/propertyaction.ccg [deleted file]
gio/src/propertyaction.hg [deleted file]
gio/src/remoteactiongroup.hg
gio/src/resolver.hg
gio/src/settings.ccg
gio/src/settings.hg
gio/src/settingsschemakey.hg
gio/src/simpleaction.hg
gio/src/simpleactiongroup.hg
gio/src/socketclient.hg
gio/src/tlsconnection.hg
gio/src/unixsocketaddress.hg
gio/src/volumemonitor.hg
glib/glibmm.h
glib/glibmm.pc.in
glib/glibmm/class.cc
glib/glibmm/class.h
glib/glibmm/dispatcher.cc
glib/glibmm/dispatcher.h
glib/glibmm/exceptionhandler.cc
glib/glibmm/exceptionhandler.h
glib/glibmm/extraclassinit.cc [deleted file]
glib/glibmm/extraclassinit.h [deleted file]
glib/glibmm/filelist.am
glib/glibmm/init.cc
glib/glibmm/init.h
glib/glibmm/interface.cc
glib/glibmm/main.cc
glib/glibmm/main.h
glib/glibmm/object.cc
glib/glibmm/objectbase.cc
glib/glibmm/objectbase.h
glib/glibmm/propertyproxy_base.cc
glib/glibmm/propertyproxy_base.h
glib/glibmm/refptr.h
glib/glibmm/signalproxy.cc
glib/glibmm/signalproxy.h
glib/glibmm/signalproxy_connectionnode.cc
glib/glibmm/signalproxy_connectionnode.h
glib/glibmm/threadpool.cc [new file with mode: 0644]
glib/glibmm/threadpool.h [new file with mode: 0644]
glib/glibmm/ustring.h
glib/glibmm/utility.h
glib/src/balancedtree.hg
glib/src/binding.hg
glib/src/bytearray.hg
glib/src/checksum.hg
glib/src/date.ccg
glib/src/date.hg
glib/src/filelist.am
glib/src/keyfile.hg
glib/src/miscutils.ccg
glib/src/miscutils.hg
glib/src/nodetree.hg
glib/src/optioncontext.hg
glib/src/optiongroup.hg
glib/src/spawn.hg
glib/src/thread.ccg [new file with mode: 0644]
glib/src/thread.hg [new file with mode: 0644]
glib/src/threads.ccg [new file with mode: 0644]
glib/src/threads.hg [new file with mode: 0644]
glib/src/value_basictypes.cc.m4
glib/src/value_basictypes.h.m4
glib/src/valuearray.ccg [new file with mode: 0644]
glib/src/valuearray.hg [new file with mode: 0644]
glib/src/variant.ccg
glib/src/variant.hg
glib/src/varianttype.ccg
glib/src/varianttype.hg
tests/Makefile.am
tests/giomm_listmodel/main.cc
tests/giomm_stream_vfuncs/main.cc [deleted file]
tests/glibmm_interface_move/main.cc
tests/glibmm_nodetree/main.cc
tests/glibmm_valuearray/main.cc [new file with mode: 0644]
tests/glibmm_variant/main.cc
tools/Makefile.am
tools/m4/convert_gio.m4
tools/m4/signal.m4
tools/test_scripts/testheaders.sh

index 434a9a8..f66dece 100644 (file)
@@ -52,8 +52,8 @@ giommconfig.h
 /docs/reference/Doxyfile
 /docs/reference/doxygen.log
 /docs/reference/doxygen*.db
-/docs/reference/glibmm-*.devhelp2
-/docs/reference/glibmm-*.tag
+/docs/reference/glibmm-2.4.devhelp2
+/docs/reference/glibmm-2.4.tag
 /docs/reference/html/
 
 # examples/
@@ -75,6 +75,8 @@ giommconfig.h
 /examples/settings/gschemas.compiled
 /examples/thread/dispatcher
 /examples/thread/dispatcher2
+/examples/thread/thread
+/examples/thread/threadpool
 
 # gio/
 /gio/giomm-*.pc
@@ -137,6 +139,10 @@ giommconfig.h
 /glib/glibmm/shell.h
 /glib/glibmm/spawn.cc
 /glib/glibmm/spawn.h
+/glib/glibmm/thread.cc
+/glib/glibmm/thread.h
+/glib/glibmm/threads.cc
+/glib/glibmm/threads.h
 /glib/glibmm/timezone.cc
 /glib/glibmm/timezone.h
 /glib/glibmm/unicode.cc
@@ -145,6 +151,8 @@ giommconfig.h
 /glib/glibmm/uriutils.h
 /glib/glibmm/value_basictypes.cc
 /glib/glibmm/value_basictypes.h
+/glib/glibmm/valuearray.cc
+/glib/glibmm/valuearray.h
 /glib/glibmm/variant.cc
 /glib/glibmm/variant.h
 /glib/glibmm/variant_basictypes.cc
diff --git a/NEWS b/NEWS
index cb86808..bbf2711 100644 (file)
--- a/NEWS
+++ b/NEWS
-2.51.5
+2.51.6:
 
-Gio:
-* Application: get_default(): Correct the reference counting.
-  (KJell Ahlstedt) Bug #779936 (James Legg)
-* Add PropertyAction.
-  (Kjell Ahlstedt)
+This is version 2.51.6 of glibmm-2.24. Ignore versions 2.51.1 to 2.51.5 of
+unstable glibmm-2.52. Unstable glibmm-2.52 is now unstable glibmm-2.54,
+leaving the 2.51/52 version numbers again for use by stable glibmm-2.52.
 
 Glib:
-* Remove Glib::unconst() because it is unused and unnecessary.
-  (Kjell Ahlstedt)
-* Variant: Add template specialization for std::tuple,
-  and a test.
-  (Alexander Rössler, Kjell Ahlstedt) Bug #777791
-
-
-2.51.2 (unstable):
-Distro packagers should probably not package this yet.
-
-Glib:
-* Object construction: Add custom class init and instance init functions
-  An extra class init function is useful in Gtk::WidgetCustomDraw and
-  Gtk::WidgetCustomSnapshot.
-  (Kjell Ahlstedt) Bug #775348
+* Dispatcher:
+  - autodeduce the type of the fd field.
+  (Marcin Kolny) Bug #772074
+  - Don't cast a HANDLE to an int on Windows.
+  (Kjell Ahlstedt) Bug #772074
+* ustring: Add cbegin() and cend().
+  (Murray Cumming)
 
 Gio:
-* Action: #include <glibmm/variant.h>, for convenience.
+* Action: Include variant.h in the heaer.
   (Daniel Boles) Bug #777953
-* SimpleAction: Make set_state() public.
-  (Daniel Boles) Bug #777953
-
-Documentation:
-* Glib::Variant: Explain how to create "maybe" type.
-  (Daniel Boles) Bug #778219
-
-
-2.51.1.2 (unstable):
-Distro packagers should probably not package this yet.
-
-Glib:
-* Remove some deprecated API
-  (Kjell Ahlstedt)
-* Variant: Remove the string specializations of cast_dynamic.
-  (Kjell Ahlstedt)
-* Glib::VariantType: Add get_item_types(), removing first() and
-  next().
-  (Kjell Ahlstedt) Bug #775741
-
-
-Gio:
-* init(): Set the global locale.
-  (Kjell Ahlstedt) Bug #661588
-* ActionBase: get_state_hint_variant() now returns VariantContainerBase.
-  (Kjell Ahlstedt)
-* ActionMap: add_action_with_parameter(): Register the parameter type,
-  to make this work.
-  (Daniel Boles) Bug #774444
-* ActionResult: Add is_tagged_vfunc().
-  (Kjell Ahlstedt)
-* Glib::Dispatcher: Implement the pimpl idiom
-  (Kjell Ahlstedt) Bug #651942
-* File, FileInfo, FileIOStream, FileOutputStream: Use Glib::ustring for
-  (UTF-8) file attributes of string type.
-  (Kjell Ahlstedt) Bug #615950
-* NetworkMonitor: Derive from Gio::Initable.
-  (Kjell Ahlstedt)
-* RemoteActionGroup: Rename some vfuncs to add _full().
-  (Murray Cumming)
-
-Documentation:
-* ActionMap:
-  - ActivateSlot: Mention add_action_bool().
-  - ActivateWithParameterSlot: Be more specific.
-  (Daniel Boles) Bug #774444
-
-Build:
-* Update the Visual Studio project files.
-  (Chun-wei Fan)
-* Some minor cppcheck fixes.
-  (Murray Cumming)
-
-
-2.51.1.1 (unstable):
-
-General:
-* Remove no_default_handler in some _WRAP_SIGNAL()s
-  This allows application developers to simply override
-  the default on_*() signal handlers for these signals too,
-  as they can already with most other signals.
-  If you are using, for instance, the -Wsuggest-override
-  compiler option, watch out for new compiler warnings suggesting
-  that your existing signal handler should now be marked with the
-  override keyword - that means you should do so but you should
-  also stop connecting the signal handler in your code.
-  (Kjell Ahlstedt)
-* Build: examples/Makefile.am: Re-insert the dispatcher examples
-  (Kjell Ahlstedt)
-
-Glib:
-* Dispatcher: Don't cast a HANDLE to an int on Windows.
-  (Kjell Ahlstedt) Bug #772074
-* ObjectBase:
-  - Remove connect_property_changed_with_return()
-  and let connect_property_changed() return a sigc::connection.
-  (Kjell Ahlstedt)
-  - Use std::forward_list for interface class pointers.
-  (Kjell Ahlstedt)
-  - Replace extra_object_base_data map by instance data.
-  (Kjell Ahlstedt)
-* ObjectBase: overload get_property().
-  (Marcin Kolny)
-* Main, IOSource: autodeduce type of fd field.
-  (Marcin Kolny) Bug #770274
-* Settings: Add property_settings_schema(), and update
-  signal_changed().
-  (Kjell Ahlstedt)
-* Settings: Make set_enum() + set_flags() usable
+* Application: get_default(): Correct the reference counting.
+  (Kjell Ahlstedt) Bug #779936
+* Settings:
+  - Really add set_enum() and set_flags().
   (djb) Bug #774647
-* SettingsSchemaKey: Add missing value/range methods
-  (Daniel Boles) Bug #774903
-* SignalProxyNormal: Remove connect_() and connect_notify_(),
-  adding connect_impl().
-  (Kjell Ahlstedt)
-* Rename SignalProxyDetailed to SignalProxyDetailedBase, and
-  SignalProxyDetailedAnyType to SignalProxyDetailed.
-  Remove SignalProxyDetailed# aliases (# = 0..6).
-  (Kjell Ahlstedt)
-* Source: Replace extra_source_data by instance data.
-  (Kjell Ahlstedt) Bug #561885
-
-Gio:
-* ActionMap::add_action_vfunc(): Const correction.
-  (Murray Cumming)
-* Application: Add dbus_register/unregister_vfunc.
-  (Ritesh Khadgaray, Kjell Ahlstedt) Bug #762191
-* Menu: insert/prepend/add_item(): Const correction.
-  (Murray Cumming)
-* MenuAttributeIter: get_value(): Const correction.
-  (Murray Cumming)
-* MenuModel: get_item_atribute(): const correction.
-  (Murray Cumming)
-* RemoteActionGroup: Derive from Gio::ActionGroup.
-  (Murray Cumming)
+  - Writable-change-event signal: Correct the type of the key parameter.
+  (Marcin Kolny) Bug #773977
+* SettingsSchemaSource: get_default(): Correct the refcounting.
+  (Marcin Kolny) Bug #774593
 
-Gio::Dbus:
+Gio::DBus:
 * Proxy: Fix memory leak in get_cached_property_names().
   (Kjell Ahlstedt) Bug #775210
-* Proxy: Derive from (and implement) Gio::DBus::Interface.
-  (Murray Cumming)
-
-
-2.51.1 (unstable):
 
-This is the first release of the glibmm-2.52 API/ABI.
-It installs in parallel with the gtkmm-2.4 API/ABI, of which
-the most recent version is glibmm 2.50. We know that is a bit
-confusing. We are taking the opportunity to do this glibmm ABI
-break while GTK+ (and therefore gtkmm) is also doing an ABI
-break. But we cannot call this glibmm-3.0 because there is no
-glib 3.0.
+Documentation:
+* Glib::Variant: Improve documentation of maybe types.
+  (Daniel Boles) Bug #778219
+* Gio::ActionMap: Clarify doc of ActivateWithParameterSlot
+  (Daniel Boles)
 
 Build:
-* Require C++14.
-  (Murray Cumming)
-* Use libsigc++-3.0 instead of libsigc++-2.0.
-  https://www.murrayc.com/permalink/2016/03/07/libsigc-3-0-very-variadic/
-  (Murray Cumming)
-* Remove lots of deprecated API.
-  (Kjell Ahlstedt)
-
-Gio:
-* BufferedInputStream, InputStream, OutputStream: Add vfuncs,
-  allowing implementation in C++.
-  (Krzysztof KosiÅ„ski, Kjell Ahlstedt) Bug #572471
-* SettingsSchemaSource::get_default(): Correct the reference count.
-  (Marcin Kolny) Bug #774593
-* Settings: Fix type of 'key' parameter of writable-change-event signal
-  (Marcin Kolny) Bug #773977
-
-Glib:
-* ustring: Add cbegin() and cend().
+* Visual Studio builds: "Install" the .pdb files
+  (Chun-wei Fan)
 
 
 2.50.0:
@@ -221,7 +81,7 @@ gmmproc:
 * Remove DocsParser::non_object_method_name()
   (Kjell Ahlstedt)
 * swap() implementations: Use std::swap().
-  (Murray Cumming)
+  (Murray Cumming <murrayc@murrayc.com>
 
 Documentation:
 * Gio::SocketService: Update the class documentation
index 32353dc..4877b19 100644 (file)
@@ -15,7 +15,7 @@
 ## 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/>.
 
-AC_INIT([glibmm], [2.51.5],
+AC_INIT([glibmm], [2.51.6],
         [http://bugzilla.gnome.org/enter_bug.cgi?product=glibmm],
         [glibmm], [http://www.gtkmm.org/])
 AC_PREREQ([2.59])
@@ -31,8 +31,8 @@ AM_MAINTAINER_MODE
 AC_ARG_VAR([ACLOCAL_FLAGS], [aclocal flags, e.g. -I <macro dir>])
 
 MM_PREREQ([0.9.10])
-MM_INIT_MODULE([glibmm-2.52])
-MM_INIT_MODULE([giomm-2.52])
+MM_INIT_MODULE([glibmm-2.4])
+MM_INIT_MODULE([giomm-2.4])
 
 # Copy the mm-common .pl scripts into docs/,
 # and use them from there,
@@ -43,7 +43,7 @@ MM_CONFIG_DOCTOOL_DIR([docs])
 AC_SUBST([LIBGLIBMM_SO_VERSION], [4:0:3])
 
 AC_PROG_CXX
-MM_AX_CXX_COMPILE_STDCXX([14], [noext],[mandatory])
+MM_AX_CXX_COMPILE_STDCXX([11], [noext],[mandatory])
 
 AC_DISABLE_STATIC
 LT_INIT([win32-dll])
@@ -64,7 +64,7 @@ AS_IF([test "x$enable_static" = xyes],
 
 glibreq='2.0 >= 2.50.0'
 
-GLIBMM_MODULES="sigc++-3.0 >= 2.99.5 glib-$glibreq gobject-$glibreq gmodule-$glibreq"
+GLIBMM_MODULES="sigc++-2.0 >= 2.9.1 glib-$glibreq gobject-$glibreq gmodule-$glibreq"
 GIOMM_MODULES="$GLIBMM_MODULES gio-$glibreq"
 test "x$glibmm_host_windows" = xyes || GIOMM_MODULES="$GIOMM_MODULES gio-unix-$glibreq"
 
@@ -114,16 +114,10 @@ MM_ARG_WITH_TAGFILE_DOC([libsigc++-2.0.tag], [sigc++-2.0])
 # Check whether --enable-debug-refcounting was given.
 GLIBMM_ARG_ENABLE_DEBUG_REFCOUNTING
 
-glibmm_warnings_fatal='-pedantic -Wall -Wextra -Wformat-security -Wsuggest-override -Wshadow -Wno-long-long'
 # Evaluate the --enable-warnings=level option.
 MM_ARG_ENABLE_WARNINGS([GLIBMM_WXXFLAGS],
                        [-Wall],
-                       [$glibmm_warnings_fatal],
-                       [G SIGCXX])
-
-MM_ARG_ENABLE_WARNINGS([GLIBMM_INTERFACE_TEST_WXXFLAGS],
-                       [-Wall],
-                       [$glibmm_warnings_fatal -Wno-unused-function],
+                       [-pedantic -Wall -Wextra -Wformat-security -Wsuggest-override -Wshadow -Wno-long-long],
                        [G SIGCXX])
 
 # Offer the ability to omit some API from the library,
index e3bdb00..9ac3ad8 100644 (file)
@@ -1,8 +1,8 @@
 web_host = gtkmm.org
-web_path_gtkmm = /home/murrayc/gtkmm.org/docs/glibmm-2.52/
-#web_path_gtkmm = /home/groups/g/gt/gtkmm/htdocs/docs/glibmm-2.52/
+web_path_gtkmm = /home/murrayc/gtkmm.org/docs/glibmm-2.4/
+#web_path_gtkmm = /home/groups/g/gt/gtkmm/htdocs/docs/glibmm-2.4/
 web_path_docs = $(web_path_gtkmm)docs/
 rsync_args = -vz --rsh ssh
 
-gtkmm_docdir = $(datadir)/doc/glibmm-2.52/docs
+gtkmm_docdir = $(datadir)/doc/glibmm-2.4/docs
 
index a32cfb8..0de871a 100644 (file)
@@ -32,9 +32,11 @@ check_PROGRAMS =                     \
        options/example                 \
        properties/example              \
        regex/example                   \
-       settings/settings \
-       thread/dispatcher \
-       thread/dispatcher2
+       settings/settings               \
+       thread/dispatcher               \
+       thread/dispatcher2              \
+       thread/thread                   \
+       thread/threadpool
 
 glibmm_includes = -I$(top_builddir)/glib $(if $(srcdir:.=),-I$(top_srcdir)/glib)
 giomm_includes  = -I$(top_builddir)/gio $(if $(srcdir:.=),-I$(top_srcdir)/gio)
@@ -49,6 +51,7 @@ local_libgiomm  = $(top_builddir)/gio/giomm/libgiomm-$(GIOMM_API_VERSION).la
 
 LDADD        = $(GLIBMM_LIBS) $(local_libglibmm)
 giomm_ldadd  = $(GIOMM_LIBS) $(local_libglibmm) $(local_libgiomm)
+thread_ldadd = $(GLIBMM_LIBS) $(local_libglibmm)
 
 child_watch_child_watch_SOURCES  = child_watch/main.cc
 iochannel_stream_example_SOURCES =     \
@@ -65,7 +68,13 @@ properties_example_SOURCES = properties/properties_example.cc
 regex_example_SOURCES      = regex/main.cc
 
 thread_dispatcher_SOURCES  = thread/dispatcher.cc
+thread_dispatcher_LDADD    = $(thread_ldadd)
 thread_dispatcher2_SOURCES = thread/dispatcher2.cc
+thread_dispatcher2_LDADD   = $(thread_ldadd)
+thread_thread_SOURCES      = thread/thread.cc
+thread_thread_LDADD        = $(thread_ldadd)
+thread_threadpool_SOURCES  = thread/threadpool.cc
+thread_threadpool_LDADD    = $(thread_ldadd)
 
 # giomm examples
 dbus_session_bus_service_SOURCES = dbus/session_bus_service.cc
index a995f5a..7738904 100644 (file)
@@ -25,7 +25,7 @@ using namespace std;
 class ChildWatch : public sigc::trackable
 {
 public:
-  explicit ChildWatch(const Glib::RefPtr<Glib::MainLoop>& mainLoop) : m_mainLoop(mainLoop) {}
+  ChildWatch(const Glib::RefPtr<Glib::MainLoop>& mainLoop) : m_mainLoop(mainLoop) {}
 
   void on_child_exited(GPid pid, int status);
   void run(); // fork a child and call signal_child_watch
index dcb8e90..c364d9b 100644 (file)
@@ -128,7 +128,7 @@ cancel_thread(Glib::RefPtr<Gio::Cancellable> cancellable)
 class JoinAndDelete
 {
 public:
-  void operator()(std::thread* thread) const
+  void operator()(std::thread* thread)
   {
     stop_thread = true;
     cond_thread.notify_all();
index 5f25442..fb9d6ea 100644 (file)
@@ -134,7 +134,7 @@ cancel_thread(Glib::RefPtr<Gio::Cancellable> cancellable)
 class JoinAndDelete
 {
 public:
-  void operator()(std::thread* thread) const
+  void operator()(std::thread* thread)
   {
     stop_thread = true;
     cond_thread.notify_all();
diff --git a/examples/thread/thread.cc b/examples/thread/thread.cc
new file mode 100644 (file)
index 0000000..7af2735
--- /dev/null
@@ -0,0 +1,126 @@
+
+#include <condition_variable>
+#include <iostream>
+#include <memory>
+#include <mutex>
+#include <queue>
+#include <thread>
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+/* For using noexcept on Visual Studio 2013 */
+#include <glibmmconfig.h>
+#endif
+#include <glibmm/init.h>
+#include <glibmm/random.h>
+#include <glibmm/timer.h>
+
+namespace
+{
+
+class MessageQueue
+{
+public:
+  MessageQueue();
+  ~MessageQueue();
+
+  void producer();
+  void consumer();
+
+private:
+  std::mutex mutex_;
+  std::condition_variable cond_push_;
+  std::condition_variable cond_pop_;
+  std::queue<int> queue_;
+};
+
+MessageQueue::MessageQueue()
+{
+}
+
+MessageQueue::~MessageQueue()
+{
+}
+
+void
+MessageQueue::producer()
+{
+  Glib::Rand rand(1234);
+
+  for (auto i = 0; i < 200; ++i)
+  {
+    {
+      std::unique_lock<std::mutex> lock(mutex_);
+
+      cond_pop_.wait(lock, [this]() -> bool { return queue_.size() < 64; });
+
+      queue_.push(i);
+      std::cout << '*';
+      std::cout.flush();
+
+      // We unlock before notifying, because that is what the documentation suggests:
+      // http://en.cppreference.com/w/cpp/thread/condition_variable
+      lock.unlock();
+      cond_push_.notify_one();
+    }
+
+    if (rand.get_bool())
+      continue;
+
+    Glib::usleep(rand.get_int_range(0, 100000));
+  }
+}
+
+void
+MessageQueue::consumer()
+{
+  Glib::Rand rand(4567);
+
+  for (;;)
+  {
+    {
+      std::unique_lock<std::mutex> lock(mutex_);
+
+      cond_push_.wait(lock, [this]() -> bool { return !queue_.empty(); });
+
+      const int i = queue_.front();
+      queue_.pop();
+      std::cout << "\x08 \x08";
+      std::cout.flush();
+
+      // We unlock before notifying, because that is what the documentation suggests:
+      // http://en.cppreference.com/w/cpp/thread/condition_variable
+      lock.unlock();
+      cond_pop_.notify_one();
+
+      if (i >= 199)
+        break;
+    }
+
+    if (rand.get_bool())
+      continue;
+
+    Glib::usleep(rand.get_int_range(10000, 200000));
+  }
+}
+}
+
+int
+main(int, char**)
+{
+  Glib::init();
+
+  MessageQueue queue;
+
+  // TODO: Use std::make_unique() when we use C++14:
+  const auto producer =
+    std::unique_ptr<std::thread>(new std::thread(&MessageQueue::producer, &queue));
+
+  const auto consumer =
+    std::unique_ptr<std::thread>(new std::thread(&MessageQueue::consumer, &queue));
+
+  producer->join();
+  consumer->join();
+
+  std::cout << std::endl;
+
+  return 0;
+}
diff --git a/examples/thread/threadpool.cc b/examples/thread/threadpool.cc
new file mode 100644 (file)
index 0000000..885962b
--- /dev/null
@@ -0,0 +1,68 @@
+
+#include <iostream>
+#include <mutex>
+#include <thread>
+
+// TODO: Remove this example sometime. Glib::ThreadPool is deprecated.
+// TODO: Maybe use std::async() instead?
+#undef GLIBMM_DISABLE_DEPRECATED
+
+#include <glibmmconfig.h>
+
+#ifdef GLIBMM_DISABLE_DEPRECATED
+int
+main(int, char**)
+{
+  // If glibmm is configured with --disable-deprecated-api,
+  // GLIBMM_DISABLE_DEPRECATED is defined in glibmmconfig.h.
+  std::cout << "Glib::ThreadPool not available because deprecated API has been disabled."
+            << std::endl;
+  return 77; // Tell automake's test harness to skip this test.
+}
+
+#else
+
+#include <glibmm/random.h>
+#include <glibmm/threadpool.h>
+#include <glibmm/timer.h>
+
+namespace
+{
+
+std::mutex mutex;
+
+void
+print_char(char c)
+{
+  Glib::Rand rand;
+
+  for (auto i = 0; i < 100; ++i)
+  {
+    {
+      std::lock_guard<std::mutex> lock(mutex);
+      std::cout << c;
+      std::cout.flush();
+    }
+    Glib::usleep(rand.get_int_range(10000, 100000));
+  }
+}
+
+} // anonymous namespace
+
+int
+main(int, char**)
+{
+  Glib::ThreadPool pool(10);
+
+  for (auto c = 'a'; c <= 'z'; ++c)
+  {
+    pool.push(sigc::bind(sigc::ptr_fun(&print_char), c));
+  }
+
+  pool.shutdown();
+
+  std::cout << std::endl;
+
+  return 0;
+}
+#endif // GLIBMM_DISABLE_DEPRECATED
index 8d5376b..a7c0a91 100644 (file)
 #include <giomm/permission.h>
 #include <giomm/pollableinputstream.h>
 #include <giomm/pollableoutputstream.h>
-#include <giomm/propertyaction.h>
 #include <giomm/proxy.h>
 #include <giomm/proxyaddress.h>
 #include <giomm/proxyresolver.h>
index 4284261..af1e974 100644 (file)
@@ -31,7 +31,7 @@ giomm_generic_socket_callback(sigc::slot_base* slot, GIOCondition condition)
   try
   {
     // Recreate the specific slot from the generic slot node.
-    return (*static_cast<sigc::slot<bool(Glib::IOCondition)>*>(slot))((Glib::IOCondition)condition);
+    return (*static_cast<sigc::slot<bool, Glib::IOCondition>*>(slot))((Glib::IOCondition)condition);
   }
   catch (...)
   {
@@ -66,7 +66,7 @@ inline SignalSocket::SignalSocket(GMainContext* context) : context_(context)
 }
 
 sigc::connection
-SignalSocket::connect(const sigc::slot<bool(Glib::IOCondition)>& slot,
+SignalSocket::connect(const sigc::slot<bool, Glib::IOCondition>& slot,
   const Glib::RefPtr<Socket>& socket, Glib::IOCondition condition,
   const Glib::RefPtr<Cancellable>& cancellable, int priority)
 {
index feadfb0..c1345c6 100644 (file)
@@ -69,7 +69,7 @@ public:
    * @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,
+  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);
index 067a230..f05d226 100644 (file)
@@ -96,7 +96,10 @@ public:
   template <typename T_Value>
   void get_state_hint(T_Value& value) const;
 
-  _WRAP_METHOD(Glib::VariantContainerBase get_state_hint_variant() const, g_action_get_state_hint)
+  //TODO: When we can break ABI, Return a Glib::VariantContainerBase,
+  // as we already do for ActionGroup::get_action_state_hint(),
+  // because that is what this returns (to specify a range).
+  _WRAP_METHOD(Glib::VariantBase get_state_hint_variant() const, g_action_get_state_hint)
 
   _WRAP_METHOD(bool get_enabled() const, g_action_get_enabled)
 
@@ -125,6 +128,8 @@ public:
 
   _WRAP_METHOD(void change_state_variant(const Glib::VariantBase& value), g_action_change_state)
 
+  _WRAP_METHOD(void change_state(const Glib::VariantBase& value), g_action_change_state, deprecated "Use the templated method instead, passing a normal C++ type.")
+
   /** Queries the current state of the action.
    *
    * If the action is not stateful then a null Variant will be returned.  If the
@@ -161,6 +166,8 @@ public:
 
   _WRAP_METHOD(void activate_variant(const Glib::VariantBase& parameter), g_action_activate)
 
+  _WRAP_METHOD(void activate(const Glib::VariantBase& parameter), g_action_activate, deprecated "Use the templated method instead, passing a normal C++ type.")
+
   _WRAP_METHOD(static bool name_is_valid(const Glib::ustring& action_name), g_action_name_is_valid )
 
   /** Parses a detailed action name into its separate name and target components.
index 6d250ba..d8f9c10 100644 (file)
@@ -75,6 +75,9 @@ public:
   _WRAP_METHOD(Glib::VariantType get_action_parameter_type(const Glib::ustring& action_name) const, g_action_group_get_action_parameter_type)
   _WRAP_METHOD(Glib::VariantType get_action_state_type(const Glib::ustring& action_name) const, g_action_group_get_action_state_type)
 
+
+  _WRAP_METHOD(Glib::VariantContainerBase get_action_state_hint(const Glib::ustring& action_name) const, g_action_group_get_action_state_hint, deprecated "Use the get_action_state() method that takes an output parameter instead.")
+
   //TODO: How do we check for a nullptr Variant?
   /**
    * Requests a hint about the valid range of values for the state of the
@@ -101,6 +104,9 @@ public:
 
   _WRAP_METHOD(Glib::VariantContainerBase get_action_state_hint_variant(const Glib::ustring& action_name) const, g_action_group_get_action_state_hint)
 
+
+  _WRAP_METHOD(Glib::VariantBase get_action_state(const Glib::ustring& action_name) const, g_action_group_get_action_state, deprecated "Use the get_action_state() method that takes an output parameter instead.")
+
   //TODO: How do we check for a nullptr Variant?
   /** Queries the current state of the named action within the action group.
    *
index ff79bbd..da803bb 100644 (file)
@@ -32,19 +32,19 @@ ActionMap::add_action(const Glib::ustring& name)
 }
 
 Glib::RefPtr<SimpleAction>
-ActionMap::add_action(const Glib::ustring& name, const ActivateSlot& slot)
+ActionMap::add_action_with_parameter(
+  const Glib::ustring& name, const ActivateWithParameterSlot& slot)
 {
   auto action = add_action(name);
-  action->signal_activate().connect(sigc::hide(slot));
+  action->signal_activate().connect(slot);
   return action;
 }
 
 Glib::RefPtr<SimpleAction>
-ActionMap::add_action_with_parameter(
-  const Glib::ustring& name, const Glib::VariantType& parameter_type, const ActivateWithParameterSlot& slot)
+ActionMap::add_action(const Glib::ustring& name, const ActivateSlot& slot)
 {
-  auto action = SimpleAction::create(name, parameter_type);
-  action->signal_activate().connect(slot);
+  auto action = add_action(name);
+  action->signal_activate().connect(sigc::hide(slot));
   return action;
 }
 
index 28b6492..6e59a62 100644 (file)
@@ -31,6 +31,10 @@ namespace Gio
 
 class Action;
 
+//TODO: Instead derive from ActionGroup, when we can break ABI,
+//because the GActionMap interface requires the GActionGroup interface.
+//LoadableIcon does a similar thing correctly, for instance.
+
 /** ActionMap - Interface for action containers.
  * The ActionMap interface is implemented by ActionGroup implementations that
  * operate by containing a number of named Action instances, such as
@@ -45,17 +49,20 @@ class ActionMap : public Glib::Interface
 {
   _CLASS_INTERFACE(ActionMap, GActionMap, G_ACTION_MAP, GActionMapInterface)
 
-  // The various add_action...() methods are our equivalent for g_action_map_add_action_entries().
-  _IGNORE(g_action_map_add_action_entries)
-
 public:
-  _WRAP_METHOD(void add_action(const Glib::RefPtr<Action>& action), g_action_map_add_action)
-  _WRAP_METHOD(void remove_action(const Glib::ustring& action_name), g_action_map_remove_action)
-
   _WRAP_METHOD(Glib::RefPtr<Action> lookup_action(const Glib::ustring& action_name), g_action_map_lookup_action, refreturn)
   _WRAP_METHOD(Glib::RefPtr<const Action> lookup_action(const Glib::ustring& action_name) const, g_action_map_lookup_action, constversion, refreturn)
 
+  /** A Slot to be called when an action has been activated,
+   * passing a parameter of a specified type.
+   * See add_action_with_parameter().
+   *
+   * For instance,
+   * void on_slot_activated(const Glib::VariantBase& parameter);
+   */
+  using ActivateWithParameterSlot = sigc::slot<void, const Glib::VariantBase&>;
 
+  //This is an equivalent for g_action_map_add_action_entries().
   /** A convenience method for creating a SimpleAction instance
    * and adding it to the ActionMap.
    *
@@ -64,15 +71,7 @@ public:
    */
   Glib::RefPtr<SimpleAction> add_action(const Glib::ustring& name);
 
-  /** A Slot to be called when an action has been activated,
-   * without passing a parameter to the slot.
-   * See add_action() and add_action_bool().
-   *
-   * For instance,
-   * void on_slot_activated();
-   */
-  using ActivateSlot = sigc::slot<void()>;
-
+  //This is an equivalent for g_action_map_add_action_entries().
   /** A convenience method for creating a SimpleAction instance
    * and adding it to the ActionMap.
    *
@@ -80,27 +79,26 @@ public:
    * @param slot The callback method to be called when the action is activated.
    * @return The Action.
    */
-  Glib::RefPtr<SimpleAction> add_action(const Glib::ustring& name, const ActivateSlot& slot);
-
+  Glib::RefPtr<SimpleAction> add_action_with_parameter(const Glib::ustring& name, const ActivateWithParameterSlot& slot);
+  _IGNORE(g_action_map_add_action_entries)
 
   /** A Slot to be called when an action has been activated,
-   * passing a parameter of a specified type.
-   * See add_action_with_parameter().
+   * without passing a parameter to the slot.
+   * See add_action() and add_action_bool().
    *
    * For instance,
-   * void on_slot_activated(const Glib::VariantBase& parameter);
+   * void on_slot_activated();
    */
-  using ActivateWithParameterSlot = sigc::slot<void(const Glib::VariantBase&)>;
+  using ActivateSlot = sigc::slot<void>;
 
   /** A convenience method for creating a SimpleAction instance
    * and adding it to the ActionMap.
    *
    * @param name The name of the Action.
-   * @param parameter_type The type of parameter to be passed to the slot.
    * @param slot The callback method to be called when the action is activated.
    * @return The Action.
    */
-  Glib::RefPtr<SimpleAction> add_action_with_parameter(const Glib::ustring& name, const Glib::VariantType& parameter_type, const ActivateWithParameterSlot& slot);
+  Glib::RefPtr<SimpleAction> add_action(const Glib::ustring& name, const ActivateSlot& slot);
 
 
   /** A convenience method for creating a boolean-stateful SimpleAction instance
@@ -139,7 +137,7 @@ public:
    * For instance,
    * void on_slot_activated(const Glib::ustring& parameter);
    */
-  using ActivateWithStringParameterSlot = sigc::slot<void(const Glib::ustring&)>;
+  using ActivateWithStringParameterSlot = sigc::slot<void, const Glib::ustring&>;
 
 //TODO: Docs: Add hints about how to specify the various possible states in the GtkBuilder XML.
   /** A convenience method for creating a string-based radio SimpleAction instance
@@ -152,7 +150,6 @@ public:
    */
   Glib::RefPtr<SimpleAction> add_action_radio_string(const Glib::ustring& name, const ActivateWithStringParameterSlot& slot, const Glib::ustring& state);
 
-
 //TODO: Docs: Add hints about how to specify the various possible states in the GtkBuilder XML.
   /** A convenience method for creating an integer-based radio SimpleAction instance
    * and adding it to the ActionMap.
@@ -169,8 +166,8 @@ public:
    * For instance,
    * void on_slot_activated(int parameter);
    */
-  using ActivateWithIntParameterSlot = sigc::slot<void(int)>;
-  
+  using ActivateWithIntParameterSlot = sigc::slot<void, int>;
+
 //TODO: Docs: Add hints about how to specify the various possible states in the GtkBuilder XML.
   /** A convenience method for creating an integer-based radio SimpleAction instance
    * and adding it to the ActionMap.
@@ -183,12 +180,16 @@ public:
   Glib::RefPtr<SimpleAction> add_action_radio_integer(const Glib::ustring& name, const ActivateWithIntParameterSlot& slot, gint32 state);
 
 
+  _WRAP_METHOD(void add_action(const Glib::RefPtr<Action>& action), g_action_map_add_action)
+  _WRAP_METHOD(void remove_action(const Glib::ustring& action_name), g_action_map_remove_action)
+
 #m4 _CONVERSION(`Glib::RefPtr<Action>', `GAction*', `Glib::unwrap($3)')
   _WRAP_VFUNC(Glib::RefPtr<Action> lookup_action(const Glib::ustring& name) const, "lookup_action", refreturn)
 
-#m4 _CONVERSION(`GAction*', `const Glib::RefPtr<Action>&', `Glib::wrap($3, true)')
-  _WRAP_VFUNC(void add_action(const Glib::RefPtr<Action>& action) const, "add_action")
-
+  //TODO: Change this to use const & when we can break ABI.
+  // ( Changing it causes a symbol lookup error when trying to run already-built applications. )
+#m4 _CONVERSION(`GAction*', `Glib::RefPtr<Action>', `Glib::wrap($3, true)')
+  _WRAP_VFUNC(void add_action(Glib::RefPtr<Action> action) const, "add_action")
   _WRAP_VFUNC(void remove_action(const Glib::ustring& name), "remove_action")
 };
 
index 238cc07..255dce6 100644 (file)
@@ -157,6 +157,10 @@ public:
   _WRAP_METHOD(bool supports_files() const, g_app_info_supports_files)
 
 #m4 _CONVERSION(`const Glib::ListHandle<std::string>&',`GList*',`$3.data()')
+  _WRAP_METHOD(bool launch_uris(const Glib::ListHandle<std::string>& uris,
+                                GAppLaunchContext* launch_context),
+               g_app_info_launch_uris,
+               errthrow, deprecated "Use the method that takes an AppLaunchContext")
 
   //TODO: I think we use Glib::ustring elsewhere for URIs:
   _WRAP_METHOD(bool launch_uris(const Glib::ListHandle<std::string>& uris,
index 97f1c27..7b53edf 100644 (file)
@@ -21,7 +21,6 @@
 #include <giomm/init.h>
 #include <cstring> // std::memset()
 #include <map>
-#include <mutex>
 #include <vector>
 
 namespace // anonymous
@@ -58,7 +57,7 @@ static void
 Application_signal_open_callback(
   GApplication* self, GFile** files, gint n_files, const gchar* hint, void* data)
 {
-  using SlotType = sigc::slot<void(const Gio::Application::type_vec_files&, const Glib::ustring&)>;
+  using SlotType = sigc::slot<void, const Gio::Application::type_vec_files&, const Glib::ustring&>;
 
   Gio::Application::type_vec_files vec_files(n_files);
   for (int i = 0; i < n_files; ++i)
@@ -93,7 +92,7 @@ Application_signal_open_notify_callback(
   GApplication* self, GFile** files, gint n_files, const gchar* hint, void* data)
 {
   using namespace Gio;
-  using SlotType = sigc::slot<void(const Application::type_vec_files&, const Glib::ustring&)>;
+  using SlotType = sigc::slot<void, const Application::type_vec_files&, const Glib::ustring&>;
 
   Application::type_vec_files vec_files(n_files);
   for (int i = 0; i < n_files; i++)
@@ -353,10 +352,10 @@ Application_Class::open_callback(GApplication* self, GFile** files, gint n_files
     (*base->open)(self, files, n_files, hint);
 }
 
-Glib::SignalProxy<void(const Application::type_vec_files&, const Glib::ustring&)>
+Glib::SignalProxy<void, const Application::type_vec_files&, const Glib::ustring&>
 Application::signal_open()
 {
-  return Glib::SignalProxy<void(const Application::type_vec_files&, const Glib::ustring&)>(
+  return Glib::SignalProxy<void, const Application::type_vec_files&, const Glib::ustring&>(
     this, &Application_signal_open_info);
 }
 
index 6b36ad3..f9432ed 100644 (file)
@@ -164,7 +164,8 @@ public:
    */
   void unset_resource_base_path();
 
-  _IGNORE(g_application_set_action_group)
+  _WRAP_METHOD(void set_action_group(const Glib::RefPtr<ActionGroup>& action_group), g_application_set_action_group,
+    deprecated "Use the Gio::ActionMap interface instead.")
 
   //Note: We would like to add a group, not just some entries,
   //so we can do pre and post parsing. See https://bugzilla.gnome.org/show_bug.cgi?id=727602
@@ -358,7 +359,7 @@ public:
 //  _WRAP_METHOD(void bind_busy_property(const Glib::RefPtr<Glib::ObjectBase>& object, const Glib::ustring& property), g_application_bind_busy_property)
 //  _WRAP_METHOD(void unbind_busy_property(const Glib::RefPtr<Glib::ObjectBase>& object, const Glib::ustring& property), g_application_unbind_busy_property)
 
-  _IGNORE_PROPERTY("action-group")
+  _WRAP_PROPERTY("action-group", Glib::RefPtr<ActionGroup>, deprecated "Use the Gio::ActionMap interface instead.")
   _WRAP_PROPERTY("application-id", Glib::ustring)
   _WRAP_PROPERTY("flags", ApplicationFlags)
   _WRAP_PROPERTY("inactivity-timeout", guint)
@@ -367,26 +368,30 @@ public:
   _WRAP_PROPERTY("resource-base-path", bool, newin "2,44")
   _WRAP_PROPERTY("is-busy", bool)
 
+//#m4 _CONVERSION(`const gchar*', `const Glib::ustring&', `Glib::ustring($3)')
+//#m4 _CONVERSION(`GVariant*', `const Glib::VariantBase&', `Glib::wrap($3, true)')
+
   _WRAP_SIGNAL(void startup(), "startup")
 
-  _WRAP_SIGNAL(void shutdown(), "shutdown", newin "2,46")
+  //TODO: Remove no_default_handler when we can break ABI
+  _WRAP_SIGNAL(void shutdown(), "shutdown", no_default_handler, newin "2,46")
 
   _WRAP_SIGNAL(void activate(), "activate")
 
   //We wrap the open signal without _WRAP_SIGNAL(), because we need to change its parameters.
   //See bug https://bugzilla.gnome.org/show_bug.cgi?id=637457
-  Glib::SignalProxy<void(const type_vec_files&, const Glib::ustring&)> signal_open();
+  Glib::SignalProxy< void,  const type_vec_files&, const Glib::ustring& > signal_open();
   _IGNORE_SIGNAL(open)
 
 #m4 _CONVERSION(`GApplicationCommandLine*', `const Glib::RefPtr<ApplicationCommandLine>&',`Glib::wrap($3, true)')
   _WRAP_SIGNAL(int command_line(const Glib::RefPtr<ApplicationCommandLine>& command_line), "command-line")
 
+  //TODO: Remove no_default_handler when we can break ABI
   //TODO: Avoid the use of the Variants in the VariantDict?
   //options must be non-const. The handler is meant to modify it. See the description
   //of add_main_option_entry(OptionType, ...).
 #m4 _CONVERSION(`GVariantDict*',`const Glib::RefPtr<Glib::VariantDict>&',`Glib::wrap($3, true)')
-#m4 _CONVERSION(`const Glib::RefPtr<Glib::VariantDict>&',`GVariantDict*',__CONVERT_REFPTR_TO_P)
-  _WRAP_SIGNAL(int handle_local_options(const Glib::RefPtr<Glib::VariantDict>& options), "handle-local-options")
+  _WRAP_SIGNAL(int handle_local_options(const Glib::RefPtr<Glib::VariantDict>& options), "handle-local-options", no_default_handler)
 
 protected:
   virtual void on_open(const type_vec_files& files, const Glib::ustring& hint);
@@ -404,6 +409,7 @@ protected:
   _WRAP_VFUNC(bool local_command_line(char**& arguments, int& exit_status), local_command_line)
 
 #m4 _CONVERSION(`GVariant*',`const Glib::VariantBase&',`Glib::wrap($3,true)')
+
   _WRAP_VFUNC(void before_emit(const Glib::VariantBase& platform_data), "before_emit")
   _WRAP_VFUNC(void after_emit(const Glib::VariantBase& platform_data), "after_emit")
 
@@ -413,10 +419,6 @@ protected:
   _WRAP_VFUNC(void quit_mainloop(), "quit_mainloop")
   _WRAP_VFUNC(void run_mainloop(), "run_mainloop")
 
-#m4 _CONVERSION(`GDBusConnection*', `const Glib::RefPtr<DBus::connection>&', `Glib::wrap($3, true)')
-#m4 _CONVERSION(`const Glib::RefPtr<DBus::Connection>&',`GDBusConnection*',__CONVERT_REFPTR_TO_P)
-  _WRAP_VFUNC(bool dbus_register(const Glib::RefPtr<DBus::Connection>& connection, const Glib::ustring& object_path), "dbus_register", errthrow)
-  _WRAP_VFUNC(void dbus_unregister(const Glib::RefPtr<DBus::Connection>& connection, const Glib::ustring& object_path), "dbus_unregister")
 
 private:
   /** This is just a way to call Glib::init() (which calls g_type_init()) before
index f0d2d68..7d9567c 100644 (file)
@@ -42,7 +42,7 @@ class AsyncResult;
  *
  * @newin{2,16}
  */
-using SlotAsyncReady = sigc::slot<void(Glib::RefPtr<AsyncResult>&)>;
+using SlotAsyncReady = sigc::slot<void, Glib::RefPtr<AsyncResult>&>;
 
 /** Provides a base class for implementing asynchronous function results.
  * Asynchronous operations are broken up into two separate operations which are chained together by a SlotAsyncReady.
@@ -106,7 +106,13 @@ class AsyncResult : public Glib::Interface
 
 public:
   _IGNORE(g_async_result_get_user_data)
-  _IGNORE(g_async_result_get_source_object)
+
+  //Note that this returns a reference, unlike most GTK+ get_*() functions,
+  //so we don't need to use refreturn.
+  _WRAP_METHOD(Glib::RefPtr<Glib::Object> get_source_object(),
+               g_async_result_get_source_object, deprecated "Use get_source_object_base()")
+  _WRAP_METHOD(Glib::RefPtr<const Glib::Object> get_source_object() const,
+               g_async_result_get_source_object, constversion, deprecated "Use get_source_object_base()")
 
   //Note that this returns a reference, unlike most GTK+ get_*() functions,
   //so we don't need to use refreturn.
@@ -117,12 +123,15 @@ public:
 
   _WRAP_METHOD(bool is_tagged(gpointer source_tag) const, g_async_result_is_tagged)
 
-  // The compiler cannot find an unwrap() for ObjectBase, because
-  // ObjectBase::BaseObjectType is not declared.
+
+  // TODO: For some reason, the compiler cannot find an unwrap() for ObjectBase.
   //#m4 _CONVERSION(`Glib::RefPtr<Glib::ObjectBase>',`GObject*',__CONVERT_REFPTR_TO_P)
 #m4 _CONVERSION(`Glib::RefPtr<Glib::ObjectBase>',`GObject*',`unwrap_objectbase_custom($3)')
-  _WRAP_VFUNC(Glib::RefPtr<Glib::ObjectBase> get_source_object(), "get_source_object")
-  _WRAP_VFUNC(bool is_tagged(gpointer source_tag), "is_tagged")
+  _WRAP_VFUNC(Glib::RefPtr<Glib::ObjectBase> get_source_object(),
+              "get_source_object")
+
+  //TODO: is_tagged() vfunc when we can break ABI.
 };
 
 } // namespace Gio
+
index 3894f95..9661d1e 100644 (file)
@@ -107,8 +107,9 @@ public:
   _WRAP_PROPERTY("buffer-size", guint)
 
 protected:
+  //TODO: When we can break ABI, add vfunc. See https://bugzilla.gnome.org/show_bug.cgi?id=572471
 #m4 _CONVERSION(`GCancellable*', `const Glib::RefPtr<Cancellable>&', `Glib::wrap($3, true)')
-  _WRAP_VFUNC(gssize fill(gssize count, const Glib::RefPtr<Cancellable>& cancellable), fill, errthrow, err_return_value -1)
+  //_WRAP_VFUNC(gssize fill(gssize count, const Glib::RefPtr<Cancellable>& cancellable), fill, errthrow, err_return_value -1)
 };
 
 } // namespace Gio
index a1cc68a..fc8bff8 100644 (file)
@@ -37,7 +37,7 @@ protected:
   _CTOR_DEFAULT
 
 public:
-  using SlotCancelledCallback = sigc::slot<void()>;
+  using SlotCancelledCallback = sigc::slot<void>;
 
   _WRAP_CREATE()
 
index ecd72ad..3872c1c 100644 (file)
@@ -39,10 +39,11 @@ _GMMPROC_EXTRA_NAMESPACE(DBus)
  * @newin{2,32}
  */
 class ActionGroup
-: public Glib::Object, public Gio::RemoteActionGroup
+: public Glib::Object, public ::Gio::ActionGroup, public RemoteActionGroup
 {
   _CLASS_GOBJECT(ActionGroup, GDBusActionGroup, G_DBUS_ACTION_GROUP, Glib::Object, GObject)
-  _IMPLEMENTS_INTERFACE(Gio::RemoteActionGroup)
+  _IMPLEMENTS_INTERFACE(::Gio::ActionGroup)
+  _IMPLEMENTS_INTERFACE(RemoteActionGroup)
 
 protected:
   _CTOR_DEFAULT
index 96b65c8..6b0e558 100644 (file)
@@ -173,9 +173,9 @@ public:
    * Glib::ustring& signal_name, const Glib::VariantContainerBase& parameters);.
    * @endcode
    */
-  using SlotSignal = sigc::slot<void(const Glib::RefPtr<Connection>&,
+  using SlotSignal = sigc::slot<voidconst Glib::RefPtr<Connection>&,
     const Glib::ustring&, const Glib::ustring&, const Glib::ustring&,
-    const Glib::ustring&, const Glib::VariantContainerBase&)>;
+    const Glib::ustring&, const Glib::VariantContainerBase&>;
 
   /** Signature for slot used in add_filter().
    *  For example,
@@ -191,9 +191,9 @@ public:
    * drop a message can simply return <tt>0</tt>.  And filter function may
    * modify a message by copying it and return the copy.
    */
-  using SlotMessageFilter = sigc::slot<Glib::RefPtr<Message>(
+  using SlotMessageFilter = sigc::slot<Glib::RefPtr<Message>,
     const Glib::RefPtr<Connection>&,
-    const Glib::RefPtr<Message>&, bool)>;
+    const Glib::RefPtr<Message>&, bool>;
 
   /** Asynchronously connects to the message bus specified by @a bus_type.
    *
index 485d2b5..ad11ea1 100644 (file)
@@ -38,6 +38,8 @@ class Object;
 
 _GMMPROC_EXTRA_NAMESPACE(DBus)
 
+//TODO: Have Proxy derive from this interface when there is an ABI break.
+
 /** Interface - Base type for D-Bus interfaces.
  * The Interface type is the base type for D-Bus interfaces both on the service
  * side (see InterfaceSkeleton) and client side (see Proxy).
index c4081e7..caf181a 100644 (file)
@@ -63,14 +63,14 @@ public:
    * @endcode
    */
   using SlotInterfaceMethodCall = sigc::slot<
-    void(
+    void,
     const Glib::RefPtr<Connection>&,
     const Glib::ustring&,
     const Glib::ustring&,
     const Glib::ustring&,
     const Glib::ustring&,
     const Glib::VariantContainerBase&,
-    const Glib::RefPtr<MethodInvocation>&)
+    const Glib::RefPtr<MethodInvocation>&
     >;
 
   /** The type for a slot which handles getting a property for a D-Bus
@@ -85,13 +85,13 @@ public:
    * @throw Glib::Error.
    */
   using SlotInterfaceGetProperty = sigc::slot<
-    void(
+    void,
     Glib::VariantBase&,
     const Glib::RefPtr<Connection>&,
     const Glib::ustring&,
     const Glib::ustring&,
     const Glib::ustring&,
-    const Glib::ustring&)
+    const Glib::ustring&
     >;
 
   /** The type for a slot which handles setting a property for a D-Bus
@@ -106,13 +106,13 @@ public:
    * @throw Glib::Error.
    */
   using SlotInterfaceSetProperty = sigc::slot<
-    bool(
+    bool,
     const Glib::RefPtr<Connection>&,
     const Glib::ustring&,
     const Glib::ustring&,
     const Glib::ustring&,
     const Glib::ustring&,
-    const Glib::VariantBase&)
+    const Glib::VariantBase&
     >;
 
   /** Constructs a new InterfaceVTable using the specified slots.
index 5944f43..8690d10 100644 (file)
@@ -35,21 +35,21 @@ _WRAP_ENUM(BusNameOwnerFlags, GBusNameOwnerFlags, s#^DBUS_##)
  * @newin{2,28}
  * @ingroup DBus
  */
-using SlotBusAcquired = sigc::slot<void(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring)>;
+using SlotBusAcquired = sigc::slot<void, const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring>;
 
 /** For example,
  * void on_name_acquired(const Glib::RefPtr<Gio::DBus::Connection>& connection,
  * const Glib::ustring& name);
  * @ingroup DBus
  */
-using SlotNameAcquired = sigc::slot<void(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring)>;
+using SlotNameAcquired = sigc::slot<void, const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring>;
 
 /** For example,
  * void on_name_lost(const Glib::RefPtr<Gio::DBus::Connection>& connection,
  * const Glib::ustring& name);
  * @ingroup DBus
  */
-using SlotNameLost = sigc::slot<void(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring)>;
+using SlotNameLost = sigc::slot<void, const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring>;
 
 //TODO: See https://bugzilla.gnome.org/show_bug.cgi?id=646427 about the apparent uselessness of SlotNameAcquired.
 //TODO: Add example from C API in class docs.
index 4e5e582..a6e7419 100644 (file)
@@ -18,7 +18,6 @@
 #include <glibmm/object.h>
 #include <giomm/asyncresult.h>
 #include <giomm/dbusintrospection.h>
-#include <giomm/dbusinterface.h>
 #include <giomm/initable.h>
 #include <giomm/asyncinitable.h>
 #include <giomm/dbusconnection.h>
@@ -65,13 +64,11 @@ _WRAP_ENUM(ProxyFlags, GDBusProxyFlags, s#^DBUS_##, NO_GTYPE)
 class Proxy
 : public Glib::Object,
   public Initable,
-  public AsyncInitable,
-  public Interface
+  public AsyncInitable
 {
   _CLASS_GOBJECT(Proxy, GDBusProxy, G_DBUS_PROXY, Glib::Object, GObject)
   _IMPLEMENTS_INTERFACE(Initable)
   _IMPLEMENTS_INTERFACE(AsyncInitable)
-  _IMPLEMENTS_INTERFACE(DBus::Interface)
 
 protected:
 
index 3c2d6d8..ead80ee 100644 (file)
@@ -67,10 +67,10 @@ public:
    * @endcode
    */
   using SlotSubtreeEnumerate = sigc::slot<
-    std::vector<Glib::ustring>(
+    std::vector<Glib::ustring>,
     const Glib::RefPtr<Connection>&,
     const Glib::ustring&,
-    const Glib::ustring&)
+    const Glib::ustring&
     >;
 
   /** The type for a slot which handles introspecting a child node.
@@ -94,11 +94,11 @@ public:
    * @endcode
    */
   using SlotSubtreeIntrospect = sigc::slot<
-    std::vector< Glib::RefPtr<Gio::DBus::InterfaceInfo> >(
+    std::vector< Glib::RefPtr<Gio::DBus::InterfaceInfo> >,
     const Glib::RefPtr<Connection>&,
     const Glib::ustring&,
     const Glib::ustring&,
-    const Glib::ustring&)
+    const Glib::ustring&
     >;
 
   /** The type for a slot which handles dispatching a remote call on a child
@@ -116,12 +116,12 @@ public:
    * @endcode
    */
   using SlotSubtreeDispatch = sigc::slot<
-    const InterfaceVTable*(
+    const InterfaceVTable*,
     const Glib::RefPtr<Connection>&,
     const Glib::ustring&,
     const Glib::ustring&,
     const Glib::ustring&,
-    const Glib::ustring&)
+    const Glib::ustring&
     >;
 
   /** Constructs a new SubtreeVTable using specified slots.
index 63cdab4..dd697ce 100644 (file)
@@ -34,14 +34,14 @@ _WRAP_ENUM(BusNameWatcherFlags, GBusNameWatcherFlags, s#^DBUS_##, NO_GTYPE)
  * const Glib::ustring& name, const Glib::ustring& name_owner);
  * @ingroup DBus
  */
-using SlotNameAppeared = sigc::slot<void(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring, const Glib::ustring&)>;
+using SlotNameAppeared = sigc::slot<void, const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring, const Glib::ustring&>;
 
 /** For example,
  * void on_name_vanished(const Glib::RefPtr<Gio::DBus::Connection>& connection,
  * const Glib::ustring& name);
  * @ingroup DBus
  */
-using SlotNameVanished = sigc::slot<void(const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring)>;
+using SlotNameVanished = sigc::slot<void, const Glib::RefPtr<Gio::DBus::Connection>&, Glib::ustring>;
 
 //TODO: Add example from C API in class docs?
 /** Starts watching @a name on the bus specified by @a bus_type and calls
index ba65428..9c08401 100644 (file)
@@ -55,8 +55,8 @@ public:
 
   _WRAP_METHOD(std::string get_filename() const, g_desktop_app_info_get_filename)
   _WRAP_METHOD(bool is_hidden() const, g_desktop_app_info_get_is_hidden)
-
-  _IGNORE(g_desktop_app_info_set_desktop_env)
+  _WRAP_METHOD(static void set_desktop_env(const std::string& desktop_env), g_desktop_app_info_set_desktop_env,
+    deprecated "Do not use this API. Since 2.42 the value of the `XDG_CURRENT_DESKTOP` environment variable will be used.")
 
 #m4 _CONVERSION(`const char* const*', `std::vector<Glib::ustring>', `Glib::ArrayHandler<Glib::ustring>::array_to_vector($3, Glib::OWNERSHIP_NONE)')
   _WRAP_METHOD(std::vector<Glib::ustring> get_keywords() const, g_desktop_app_info_get_keywords)
index 0b87d19..a4eecee 100644 (file)
@@ -153,10 +153,18 @@ public:
 
   _WRAP_METHOD(Glib::ustring get_sort_key() const,  g_drive_get_sort_key)
 
-  _WRAP_SIGNAL(void changed(), changed, newin "2,20")
-  _WRAP_SIGNAL(void disconnected(), disconnected, newin "2,20")
-  _WRAP_SIGNAL(void eject_button(), eject_button, newin "2,20")
-  _WRAP_SIGNAL(void stop_button(), stop_button)
+  /** @newin{2,20}
+   */
+  _WRAP_SIGNAL(void changed(), changed, no_default_handler)
+
+  /** @newin{2,20}
+   */
+  _WRAP_SIGNAL(void disconnected(), disconnected, no_default_handler)
+
+  /** @newin{2,20}
+   */
+  _WRAP_SIGNAL(void eject_button(), eject_button, no_default_handler)
+  _WRAP_SIGNAL(void stop_button(), stop_button, no_default_handler)
 
   //_WRAP_VFUNC(Glib::ustring get_name() const, get_name)
   //Careful of ref-counting: //_WRAP_VFUNC(Glib::RefPtr<Icon> get_icon() const, get_icon)
index f2b595a..25c182f 100644 (file)
@@ -1118,7 +1118,7 @@ public:
   /** A signal handler would be, for instance:
    * void on_file_progress(goffset current_num_bytes, goffset total_num_bytes);
    */
-  using SlotFileProgress = sigc::slot<void(goffset, goffset)>;
+  using SlotFileProgress = sigc::slot<void, goffset, goffset>;
 
   /** Copies the file source to the location specified by destination. Can not handle recursive copies of directories.
    * If the flag FILE_COPY_OVERWRITE is specified an already existing destination file is overwritten.
@@ -1399,7 +1399,7 @@ public:
 
   bool set_attributes_finish(const Glib::RefPtr<AsyncResult>& result, const Glib::RefPtr<FileInfo>& info);
 
-  _WRAP_METHOD(bool set_attribute_string(const std::string& attribute, const Glib::ustring& value, FileQueryInfoFlags flags, const Glib::RefPtr<Cancellable>& cancellable{?}),
+  _WRAP_METHOD(bool set_attribute_string(const std::string& attribute, const std::string& value, FileQueryInfoFlags flags, const Glib::RefPtr<Cancellable>& cancellable{?}),
                g_file_set_attribute_string,
                errthrow)
 
@@ -1803,7 +1803,7 @@ public:
   *
   * @newin{2,38}
   */
- using SlotFileMeasureProgress = sigc::slot<void(bool, guint64, guint64, guint64)>;
+ using SlotFileMeasureProgress = sigc::slot<void, bool, guint64, guint64, guint64>;
 
   //We do not use the {callback} syntax with _WRAP_METHOD here, because it expects to use user_data rather than progress_data.
   //We ignore the gboolean result, because we throw an exception if it is false.
@@ -2097,7 +2097,7 @@ public:
   /** A signal handler would be, for instance:
    * bool on_read_more(const char* file_contents, goffset file_size);
    */
-  using SlotReadMore = sigc::slot<bool(const char*, goffset)>;
+  using SlotReadMore = sigc::slot<bool, const char*, goffset>;
 
   //Note that slot_read_more can be nullptr but that would not be a useful method overload, because the documentation says that it would
   //then be equivalent to load_contents_async.
index 6596e47..54841f9 100644 (file)
@@ -1,3 +1,5 @@
+// -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
 /* Copyright (C) 2007 The gtkmm Development Team
  *
  * This library is free software; you can redistribute it and/or
@@ -107,7 +109,8 @@ public:
 
   _WRAP_METHOD(FileAttributeStatus get_attribute_status(const std::string& attribute) const, g_file_info_get_attribute_status)
 
-  _WRAP_METHOD(Glib::ustring get_attribute_string(const std::string& attribute) const,
+  //TODO: This should return a ustring instead: https://bugzilla.gnome.org/show_bug.cgi?id=615950#c7
+  _WRAP_METHOD(std::string get_attribute_string(const std::string& attribute) const,
                g_file_info_get_attribute_string)
 
 #m4 _CONVERSION(`char**',`std::vector<Glib::ustring>',`Glib::ArrayHandler<Glib::ustring>::array_to_vector($3, Glib::OWNERSHIP_NONE)')
@@ -132,7 +135,8 @@ public:
 
   _WRAP_METHOD(bool set_attribute_status(const std::string& attribute, FileAttributeStatus status), g_file_info_set_attribute_status)
 
-  _WRAP_METHOD(void set_attribute_string(const std::string& attribute, const Glib::ustring& attr_value),
+  //TODO: This should take a ustring value instead: https://bugzilla.gnome.org/show_bug.cgi?id=615950#c7
+  _WRAP_METHOD(void set_attribute_string(const std::string& attribute, const std::string& attr_value),
                g_file_info_set_attribute_string)
 
 #m4 _CONVERSION(`const std::vector<Glib::ustring>&',`char**',`const_cast<char**>(Glib::ArrayHandler<Glib::ustring>::vector_to_array($3).data())')
@@ -163,9 +167,11 @@ public:
   _WRAP_METHOD(bool is_symlink() const, g_file_info_get_is_symlink)
   _WRAP_METHOD(std::string get_name() const, g_file_info_get_name)
 
-  _WRAP_METHOD(Glib::ustring get_display_name() const, g_file_info_get_display_name)
+  //TODO: This should return a ustring instead. See https://bugzilla.gnome.org/show_bug.cgi?id=615950#c4
+  _WRAP_METHOD(std::string get_display_name() const, g_file_info_get_display_name)
 
-  _WRAP_METHOD(Glib::ustring get_edit_name() const, g_file_info_get_edit_name)
+  //TODO: This should return a ustring instead. See https://bugzilla.gnome.org/show_bug.cgi?id=615950#c4
+  _WRAP_METHOD(std::string get_edit_name() const, g_file_info_get_edit_name)
 
   _WRAP_METHOD(Glib::RefPtr<Icon> get_icon(), g_file_info_get_icon, refreturn)
   _WRAP_METHOD(Glib::RefPtr<const Icon> get_icon() const, g_file_info_get_icon, refreturn, constversion)
@@ -173,7 +179,8 @@ public:
   _WRAP_METHOD(Glib::RefPtr<Icon> get_symbolic_icon(), g_file_info_get_symbolic_icon, refreturn)
   _WRAP_METHOD(Glib::RefPtr<const Icon> get_symbolic_icon() const, g_file_info_get_symbolic_icon, refreturn, constversion)
 
-  _WRAP_METHOD(Glib::ustring get_content_type() const, g_file_info_get_content_type)
+  //TODO: This should return a ustring instead. See https://bugzilla.gnome.org/show_bug.cgi?id=615950#c4
+  _WRAP_METHOD(std::string get_content_type() const, g_file_info_get_content_type)
 
   _WRAP_METHOD(goffset get_size() const, g_file_info_get_size)
 
@@ -182,7 +189,8 @@ public:
 
   _WRAP_METHOD(std::string get_symlink_target() const, g_file_info_get_symlink_target)
 
-  _WRAP_METHOD(Glib::ustring get_etag() const, g_file_info_get_etag)
+  //TODO: This should return a ustring instead. See https://bugzilla.gnome.org/show_bug.cgi?id=615950#c4
+  _WRAP_METHOD(std::string get_etag() const, g_file_info_get_etag)
 
   _WRAP_METHOD(gint32 get_sort_order() const, g_file_info_get_sort_order)
   _WRAP_METHOD(void set_attribute_mask(const Glib::RefPtr<FileAttributeMatcher>& mask),
@@ -196,14 +204,17 @@ public:
   _WRAP_METHOD(void set_is_symlink(bool symlink = true), g_file_info_set_is_symlink)
   _WRAP_METHOD(void set_name(const std::string& name), g_file_info_set_name)
 
-  _WRAP_METHOD(void set_display_name(const Glib::ustring& display_name), g_file_info_set_display_name)
+  //TODO: This should take a ustring instead. See https://bugzilla.gnome.org/show_bug.cgi?id=615950#c4
+  _WRAP_METHOD(void set_display_name(const std::string& display_name), g_file_info_set_display_name)
 
-  _WRAP_METHOD(void set_edit_name(const Glib::ustring& edit_name), g_file_info_set_edit_name)
+  //TODO: This should take a ustring instead. See https://bugzilla.gnome.org/show_bug.cgi?id=615950#c4
+  _WRAP_METHOD(void set_edit_name(const std::string& edit_name), g_file_info_set_edit_name)
 
   _WRAP_METHOD(void set_icon(const Glib::RefPtr<Icon>& icon), g_file_info_set_icon)
   _WRAP_METHOD(void set_symbolic_icon(const Glib::RefPtr<Icon>& icon), g_file_info_set_symbolic_icon)
 
-  _WRAP_METHOD(void set_content_type(const Glib::ustring& content_type), g_file_info_set_content_type)
+  //TODO: This should take a ustring instead. See https://bugzilla.gnome.org/show_bug.cgi?id=615950#c4
+  _WRAP_METHOD(void set_content_type(const std::string& content_type), g_file_info_set_content_type)
 
   _WRAP_METHOD(void set_size(goffset size), g_file_info_set_size)
 
index 3f2ca9c..b015268 100644 (file)
@@ -1,3 +1,5 @@
+// -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
 /* Copyright (C) 2007 The gtkmm Development Team
  *
  * This library is free software; you can redistribute it and/or
@@ -98,7 +100,7 @@ public:
   _WRAP_METHOD(Glib::RefPtr<FileInfo> query_info_finish(const Glib::RefPtr<AsyncResult>& result),
                g_file_io_stream_query_info_finish,
                errthrow)
-  _WRAP_METHOD(Glib::ustring get_etag() const, g_file_io_stream_get_etag)
+  _WRAP_METHOD(std::string get_etag() const, g_file_io_stream_get_etag)
 
 };
 
index ca5a3ac..0095128 100644 (file)
@@ -94,7 +94,6 @@ giomm_files_any_hg =                  \
        permission.hg           \
        pollableinputstream.hg          \
        pollableoutputstream.hg         \
-       propertyaction.hg \
        proxy.hg                        \
        proxyaddress.hg                 \
        proxyresolver.hg                \
index 3539c4c..a31567b 100644 (file)
@@ -135,7 +135,7 @@ public:
                g_file_output_stream_query_info_finish,
                refreturn, errthrow)
 
-  _WRAP_METHOD(Glib::ustring get_etag() const, g_file_output_stream_get_etag)
+  _WRAP_METHOD(std::string get_etag() const, g_file_output_stream_get_etag)
 };
 
 } // namespace Gio
index f8c94da..4bcfa1e 100644 (file)
   (return-type "void")
 )
 
-(define-vfunc dbus_register
-  (of-object "GApplication")
-  (return-type "gboolean")
-  (parameters
-    '("GDBusConnection*" "connection")
-    '("const-gchar*" "object_path")
-    '("GError**" "error")
-  )
-)
-
-(define-vfunc dbus_unregister
+(define-vfunc shutdown
   (of-object "GApplication")
   (return-type "void")
-  (parameters
-    '("GDBusConnection*" "connection")
-    '("const-gchar*" "object_path")
-  )
 )
 
 ; GAsyncInitable
   (return-type "GObject*")
 )
 
-(define-vfunc is_tagged
-  (of-object "GAsyncResult")
-  (return-type "gboolean")
- (parameters
-  '("gpointer" "source_tag")
- )
-)
-
 ; GBufferedInputStream
 
 (define-vfunc fill
index 315ed86..b98da27 100644 (file)
@@ -390,10 +390,11 @@ protected:
   _WRAP_METHOD(bool set_pending(), g_input_stream_set_pending, errthrow, newin "2,50")
   _WRAP_METHOD(void clear_pending(), g_input_stream_clear_pending, newin "2,50")
 
+  //TODO: When we can break ABI, add vfuncs. See https://bugzilla.gnome.org/show_bug.cgi?id=572471
 #m4 _CONVERSION(`GCancellable*', `const Glib::RefPtr<Cancellable>&', `Glib::wrap($3, true)')
-  _WRAP_VFUNC(gssize read(void* buffer, gsize count, const Glib::RefPtr<Cancellable>& cancellable), read_fn, errthrow, err_return_value -1)
-  _WRAP_VFUNC(gssize skip(gsize count, const Glib::RefPtr<Cancellable>& cancellable), skip, errthrow, err_return_value -1)
-  _WRAP_VFUNC(bool close(const Glib::RefPtr<Cancellable>& cancellable), close_fn, errthrow)
+  //_WRAP_VFUNC(gssize read(void* buffer, gsize count, const Glib::RefPtr<Cancellable>& cancellable), read_fn, errthrow, err_return_value -1)
+  //_WRAP_VFUNC(gssize skip(gsize count, const Glib::RefPtr<Cancellable>& cancellable), skip, errthrow, err_return_value -1)
+  //_WRAP_VFUNC(bool close(const Glib::RefPtr<Cancellable>& cancellable), close_fn, errthrow)
 };
 
 } // namespace Gio
index 2b3af6c..840d739 100644 (file)
@@ -63,7 +63,7 @@ public:
    *
    * @newin{2,50}
    */
-  using SlotCompare = sigc::slot<int(const Glib::RefPtr<const Glib::ObjectBase>&, const Glib::RefPtr<const Glib::ObjectBase>&)>;
+  using SlotCompare = sigc::slot<int, const Glib::RefPtr<const Glib::ObjectBase>&, const Glib::RefPtr<const Glib::ObjectBase>&>;
 
   _WRAP_METHOD(guint insert_sorted(const Glib::RefPtr<Glib::ObjectBase>& item,
     const SlotCompare& slot{compare_func}), g_list_store_insert_sorted,
@@ -175,7 +175,7 @@ public:
    *
    * @newin{2,50}
    */
-  using SlotCompare = sigc::slot<int(const Glib::RefPtr<const T_item>&, const Glib::RefPtr<const T_item>&)>;
+  using SlotCompare = sigc::slot<int, const Glib::RefPtr<const T_item>&, const Glib::RefPtr<const T_item>&>;
 
   /** Inserts @a item at a position to be determined by the @a slot.
    *
index 38126a4..e896528 100644 (file)
@@ -30,9 +30,6 @@ public:
   {
   }
 
-  SlotWithData(const SlotWithData& src) = delete;
-  SlotWithData& operator=(const SlotWithData& src) = delete;
-
   ~SlotWithData() { delete m_slot; }
 
   void operator()() { (*m_slot)(m_data); }
@@ -65,6 +62,29 @@ destroy_data_callback(void* user_data)
 namespace Gio
 {
 
+_DEPRECATE_IFDEF_START
+void
+MemoryInputStream::add_data(const std::string& data)
+{
+  char* data_copy = g_strdup(data.c_str());
+  g_memory_input_stream_add_data(gobj(), data_copy, -1, g_free);
+}
+
+void
+MemoryInputStream::add_data(const void* data, gssize len)
+{
+  char* data_copy = nullptr;
+
+  // copy the data so that the caller doesn't need to keep the data alive
+  if (len < 0)
+    data_copy = g_strdup(static_cast<const gchar*>(data));
+  else
+    data_copy = static_cast<gchar*>(g_memdup(data, len));
+
+  g_memory_input_stream_add_data(gobj(), data_copy, len, g_free);
+}
+_DEPRECATE_IFDEF_END
+
 void
 MemoryInputStream::add_data(const void* data, gssize len, const SlotDestroyData& destroy_slot)
 {
index 156ab09..0fc03f4 100644 (file)
@@ -46,6 +46,27 @@ protected:
 public:
   _WRAP_CREATE()
 
+_DEPRECATE_IFDEF_START
+  /** Appends to data that can be read from the input stream.
+   *
+   * @param data Input data.
+   *
+   * @deprecated Use add_data() with SlotDestroyData or GDestroyNotify instead.
+   */
+  void add_data(const std::string& data);
+
+  /** Appends to data that can be read from the input stream.
+   *
+   * Note that the data will be copied internally and freed when no longer needed.
+   *
+   * @param data Input data.
+   * @param len Length of the data, may be -1 if data is a null-terminated string.
+   *
+   * @deprecated Use add_data() with SlotDestroyData or GDestroyNotify instead.
+   */
+  void add_data(const void* data, gssize len);
+_DEPRECATE_IFDEF_END
+
   _WRAP_METHOD(void add_data(const void* data, gssize len, GDestroyNotify destroy), g_memory_input_stream_add_data)
 
   /** For example,
@@ -55,7 +76,7 @@ public:
    *
    * @newin{2,40}
    */
-  using SlotDestroyData = sigc::slot<void(void*)>;
+  using SlotDestroyData = sigc::slot<void, void*>;
 
   /** Appends to data that can be read from the input stream.
    *
index e3f1d6d..ad129a9 100644 (file)
@@ -48,9 +48,10 @@ public:
 
   _WRAP_METHOD(void freeze(), g_menu_freeze)
 
-  _WRAP_METHOD(void insert_item(int position, const Glib::RefPtr<const MenuItem>& item), g_menu_insert_item)
-  _WRAP_METHOD(void prepend_item(const Glib::RefPtr<const MenuItem>& item), g_menu_prepend_item)
-  _WRAP_METHOD(void append_item(const Glib::RefPtr<const MenuItem>& item), g_menu_append_item)
+  //TODO: Make the item "const Glib::RefPtr<const MenuItem>&" when we can break ABI? The function is documented as just copying its attributes.
+  _WRAP_METHOD(void insert_item(int position, const Glib::RefPtr<MenuItem>& item), g_menu_insert_item)
+  _WRAP_METHOD(void prepend_item(const Glib::RefPtr<MenuItem>& item), g_menu_prepend_item)
+  _WRAP_METHOD(void append_item(const Glib::RefPtr<MenuItem>& item), g_menu_append_item)
   _WRAP_METHOD(void remove(int position), g_menu_remove)
   _WRAP_METHOD(void remove_all(), g_menu_remove_all)
 
@@ -62,7 +63,6 @@ public:
   _WRAP_METHOD(void prepend(const Glib::ustring& label, const Glib::ustring& detailed_action{?}), g_menu_prepend)
   _WRAP_METHOD(void append(const Glib::ustring& label, const Glib::ustring& detailed_action{?}), g_menu_append)
 
-// TODO: Should the MenuModel be const too?
   _WRAP_METHOD(void insert_section(int position, const Glib::ustring& label{?}, const Glib::RefPtr<MenuModel>& section), g_menu_insert_section)
   _WRAP_METHOD(void prepend_section(const Glib::ustring& label{?}, const Glib::RefPtr<MenuModel>& section), g_menu_prepend_section)
   _WRAP_METHOD(void append_section(const Glib::ustring& label{?}, const Glib::RefPtr<MenuModel>& section), g_menu_append_section)
index 0e2c941..c66b45e 100644 (file)
@@ -39,7 +39,10 @@ public:
 
   _WRAP_METHOD(Glib::ustring get_name() const, g_menu_attribute_iter_get_name)
 
-  _WRAP_METHOD(Glib::VariantBase get_value() const, g_menu_attribute_iter_get_value)
+  //TODO: When we can break ABI, remove the method overload and just make it const.
+  //It makes no sense to return const by value.
+  _WRAP_METHOD(Glib::VariantBase get_value(), g_menu_attribute_iter_get_value)
+  _WRAP_METHOD(const Glib::VariantBase get_value() const, g_menu_attribute_iter_get_value, constversion)
 
   _WRAP_METHOD(bool next(), g_menu_attribute_iter_next)
 };
index 2f6dc38..6912c05 100644 (file)
@@ -43,6 +43,14 @@ MenuItem::MenuItem(const Glib::RefPtr<MenuModel>& submenu) : _CONSTRUCT()
   set_submenu(submenu);
 }
 
+_DEPRECATE_IFDEF_START
+void
+MenuItem::set_action_and_target(const Glib::ustring& action)
+{
+  g_menu_item_set_action_and_target_value(gobj(), action.c_str(), nullptr);
+}
+_DEPRECATE_IFDEF_END
+
 void
 MenuItem::set_action(const Glib::ustring& action)
 {
index 3830880..5590393 100644 (file)
@@ -102,6 +102,7 @@ GMenuItem * g_menu_item_new_section                 (const Glib::ustring& label,
   //void set_attribute(const Glib::ustring& attribute, const T_Value& value) const;
 
   _WRAP_METHOD(void set_attribute_value(const Glib::ustring& attribute, const Glib::VariantBase& value), g_menu_item_set_attribute_value)
+  _WRAP_METHOD(void set_attribute(const Glib::ustring& attribute, const Glib::VariantBase& value), g_menu_item_set_attribute_value, deprecated "Use set_attribute() instead.")
   _IGNORE(g_menu_item_set_attribute)
 
 //These are documented as transfer-full, so we don't need to use refreturn.
@@ -119,11 +120,19 @@ GMenuItem * g_menu_item_new_section                 (const Glib::ustring& label,
   //void get_attribute(const Glib::ustring& attribute, T_Value& value) const;
   //_WRAP_METHOD(Glib::VariantBase get_attribute_value(const Glib::ustring& attribute, const Glib::VariantType& expected_type{?}) const, g_menu_item_get_attribute_value)
 
+  _WRAP_METHOD(Glib::VariantBase get_attribute(const Glib::ustring& attribute, const Glib::VariantType& expected_type{?}) const, g_menu_item_get_attribute_value, deprecated "Use get_attribute_value() instead.")
   _WRAP_METHOD(Glib::VariantBase get_attribute_value(const Glib::ustring& attribute, const Glib::VariantType& expected_type{?}) const, g_menu_item_get_attribute_value)
 
   // Ignore varargs function.
   _IGNORE(g_menu_item_get_attribute)
 
+_DEPRECATE_IFDEF_START
+  /** Unsets the target for the specified @a action.
+   * @deprecated Use set_action() or unset_target() instead.
+   */
+  void set_action_and_target(const Glib::ustring& action);
+_DEPRECATE_IFDEF_END
+
   /** Sets the action for the menu item.
    * See set_action_and_target().
    *
index bf29a12..696e8f5 100644 (file)
@@ -132,13 +132,16 @@ public:
 #m4begin
 dnl See the .ccg implementation for how this conversion works.
 
+  //TODO: When we can break ABI, remove the method overload and just make it const.
+  //It makes no sense to return const by value.
   _CONVERSION(`MenuAttribute',`const gchar*',`giomm_get_menu_attribute($3)')
 #m4end
 
   //TODO: Add a get_item_attribute() templated method to get values directly
   //instead of returning a Glib::VariantBase?
 
-  _WRAP_METHOD(Glib::VariantBase get_item_attribute(int item_index, MenuAttribute attribute, const Glib::VariantType& expected_type) const, g_menu_model_get_item_attribute_value)
+  _WRAP_METHOD(Glib::VariantBase get_item_attribute(int item_index, MenuAttribute attribute, const Glib::VariantType& expected_type), g_menu_model_get_item_attribute_value)
+  _WRAP_METHOD(const Glib::VariantBase get_item_attribute(int item_index, MenuAttribute attribute, const Glib::VariantType& expected_type) const, g_menu_model_get_item_attribute_value, constversion)
 
   // Ignore varargs function
   _IGNORE(g_menu_model_get_item_attribute)
index 3988452..4ad4790 100644 (file)
@@ -232,7 +232,7 @@ public:
 
   _WRAP_SIGNAL(void changed(), changed)
   _WRAP_SIGNAL(void unmounted(), unmounted)
-  _WRAP_SIGNAL(void pre_unmount(), pre_unmount)
+  _WRAP_SIGNAL(void pre_unmount(), pre_unmount, no_default_handler)
 
   //There are no properties.
 };
index a13ed1b..450de59 100644 (file)
@@ -1,3 +1,5 @@
+// -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
 /* Copyright (C) 2007 The gtkmm Development Team
  *
  * This library is free software; you can redistribute it and/or
@@ -85,12 +87,14 @@ public:
   _WRAP_SIGNAL(void ask_question(const Glib::ustring& message, const Glib::StringArrayHandle& choices), ask_question)
 
   _WRAP_SIGNAL(void reply(MountOperationResult result), reply)
-  _WRAP_SIGNAL(void aborted(), aborted)
+
+  //TODO: Remove no_default_handler when we can break ABI:
+  _WRAP_SIGNAL(void aborted(), aborted, no_default_handler)
 
   //TODO: The array of char* is not very pleasant to wrap:
   //_WRAP_SIGNAL( void show_processes(const Glib::ustring& message, GArray* processes, const gchar *choices[]);
 
-  _WRAP_SIGNAL(void show_unmount_progress(const Glib::ustring& message, gint64 time_left, gint64 bytes_left), "show_unmount_progress")
+  _WRAP_SIGNAL(void show_unmount_progress(const Glib::ustring& message, gint64 time_left, gint64 bytes_left), "show_unmount_progress", no_default_handler)
 
   _WRAP_PROPERTY("username", Glib::ustring)
   _WRAP_PROPERTY("password", Glib::ustring)
index ca84559..df55fda 100644 (file)
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <giomm/initable.h>
+#include <glibmm/interface.h>
 #include <giomm/asyncresult.h>
 #include <giomm/cancellable.h>
 #include <giomm/socketconnectable.h>
 #include <gio/gio.h>
 
 _DEFS(giomm,gio)
-_PINCLUDE(giomm/private/initable_p.h)
+_PINCLUDE(glibmm/private/interface_p.h)
 _PINCLUDE(gio/gio.h)
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
@@ -39,9 +39,9 @@ _WRAP_ENUM(NetworkConnectivity, GNetworkConnectivity, NO_GTYPE)
  *
  * @newin{2,44}
  */
-class NetworkMonitor : public Initable
+class NetworkMonitor : public Glib::Interface
 {
-  _CLASS_INTERFACE(NetworkMonitor, GNetworkMonitor, G_NETWORK_MONITOR, GNetworkMonitorInterface, Initable, GInitable)
+  _CLASS_INTERFACE(NetworkMonitor, GNetworkMonitor, G_NETWORK_MONITOR, GNetworkMonitorInterface)
 
 public:
   _WRAP_METHOD(static Glib::RefPtr<NetworkMonitor> get_default(), g_network_monitor_get_default, newin "2,44")
index de15fcf..df9a7ee 100644 (file)
@@ -71,7 +71,7 @@ public:
   _WRAP_METHOD(void set_title(const Glib::ustring& title), g_notification_set_title)
   _WRAP_METHOD(void set_body(const Glib::ustring& body), g_notification_set_body)
   _WRAP_METHOD(void set_icon(const Glib::RefPtr<Icon>& icon), g_notification_set_icon)
-  _IGNORE(g_notification_set_urgent)
+  _WRAP_METHOD(void set_urgent(bool urgent = true), g_notification_set_urgent, deprecated "Use set_priority() instead.")
   _WRAP_METHOD(void set_priority(NotificationPriority priority = NOTIFICATION_PRIORITY_NORMAL), g_notification_set_priority, newin "2,44")
 
   _WRAP_METHOD(void add_button(const Glib::ustring& label, const Glib::ustring& detailed_action), g_notification_add_button)
index 8b0c938..d1e3f41 100644 (file)
@@ -503,12 +503,13 @@ protected:
   _WRAP_METHOD(bool set_pending(), g_output_stream_set_pending, errthrow, newin "2,50")
   _WRAP_METHOD(void clear_pending(), g_output_stream_clear_pending, newin "2,50")
 
+  //TODO: When we can break ABI, add vfuncs. See https://bugzilla.gnome.org/show_bug.cgi?id=572471
 #m4 _CONVERSION(`GCancellable*', `const Glib::RefPtr<Cancellable>&', `Glib::wrap($3, true)')
 #m4 _CONVERSION(`GInputStream*', `const Glib::RefPtr<InputStream>&', `Glib::wrap($3, true)')
-  _WRAP_VFUNC(gssize write(const void* buffer, gsize count, const Glib::RefPtr<Cancellable>& cancellable), write_fn, errthrow, err_return_value -1)
-  _WRAP_VFUNC(gssize splice(const Glib::RefPtr<InputStream>& source, const Glib::RefPtr<Cancellable>& cancellable{.}, OutputStreamSpliceFlags flags{.}), splice, errthrow, err_return_value -1)
-  _WRAP_VFUNC(bool flush(const Glib::RefPtr<Cancellable>& cancellable), flush, errthrow)
-  _WRAP_VFUNC(bool close(const Glib::RefPtr<Cancellable>& cancellable), close_fn, errthrow)
+  //_WRAP_VFUNC(gssize write(const void* buffer, gsize count, const Glib::RefPtr<Cancellable>& cancellable), write_fn, errthrow, err_return_value -1)
+  //_WRAP_VFUNC(gssize splice(const Glib::RefPtr<InputStream>& source, const Glib::RefPtr<Cancellable>& cancellable{.}, OutputStreamSpliceFlags flags{.}), splice, errthrow, err_return_value -1)
+  //_WRAP_VFUNC(bool flush(const Glib::RefPtr<Cancellable>& cancellable), flush, errthrow)
+  //_WRAP_VFUNC(bool close(const Glib::RefPtr<Cancellable>& cancellable), close_fn, errthrow)
 };
 
 } // namespace Gio
index a5dcddf..b1c3178 100644 (file)
@@ -33,8 +33,6 @@ class Cancellable;
 //TODO: Instead derive from InputStream, when we can break ABI,
 //because the GPollableInputStream interface requires the GInputStream interface.
 //LoadableIcon does a similar thing correctly, for instance.
-// However, GInputStream is an actuall class, deriving from GObject,
-// but GPollableInputStream is a GInterface, that "requires" GInputStream.
 
 /** PollableInputStream - Interface for pollable input streams.
  * PollableInputStream is implemented by InputStreams that can be polled for
index 2ab20cb..c735fc6 100644 (file)
@@ -33,8 +33,6 @@ class Cancellable;
 //TODO: Instead derive from OutputStream, when we can break ABI,
 //because the GPollableOutputStream interface requires the GOutputStream interface.
 //LoadableIcon does a similar thing correctly, for instance.
-// However, GOutputStream is an actual class, deriving from GObject,
-// but GPollableOutputStream is a GInterface, that "requires" GOutputStream.
 
 /** PollableOutputStream - Interface for pollable output streams.
  * PollableOutputStream is implemented by OutputStreams that can be polled for
diff --git a/gio/src/propertyaction.ccg b/gio/src/propertyaction.ccg
deleted file mode 100644 (file)
index 85da4a8..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Copyright (C) 2017 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 <gio/gio.h>
-
-namespace Gio
-{
-
-PropertyAction::PropertyAction(const Glib::ustring& name,
-  const Glib::PropertyProxy_Base& property_proxy, bool invert_boolean)
-:
-_CONSTRUCT("name", name.c_str(), "object", property_proxy.get_object()->gobj(),
-           "property-name",  property_proxy.get_name(),
-           "invert-boolean", invert_boolean)
-{
-}
-
-} // namespace Gio
diff --git a/gio/src/propertyaction.hg b/gio/src/propertyaction.hg
deleted file mode 100644 (file)
index 5037146..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/* Copyright (C) 2017 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/object.h>
-#include <glibmm/refptr.h>
-#include <giomm/action.h>
-
-_DEFS(giomm,gio)
-_PINCLUDE(glibmm/private/object_p.h)
-
-namespace Gio
-{
-/** An Action reflecting a Glib::Object property.
- *
- * A %PropertyAction is a way to get an Action with a state value
- * reflecting and controlling the value of a Glib::Object property.
- *
- * The state of the action will correspond to the value of the property.
- * Changing it will change the property (assuming the requested value
- * matches the requirements as specified in the GParamSpec, used when the
- * property was installed).
- *
- * Only the most common types are presently supported. Booleans are
- * mapped to booleans, strings to strings, signed/unsigned integers to
- * int32/uint32 and floats and doubles to doubles.
- *
- * If the property is an enum then the state will be string-typed and
- * conversion will automatically be performed between the enum value and
- * "nick" string as per the GEnumValue table.
- *
- * Flags types are not currently supported.
- *
- * Properties of object types, boxed types and pointer types are not
- * supported and probably never will be.
- *
- * Properties of Glib::Variant types are not currently supported.
- *
- * If the property is boolean-valued then the action will have a nullptr
- * parameter type, and activating the action (with no parameter) will
- * toggle the value of the property.
- *
- * In all other cases, the parameter type will correspond to the type of
- * the property.
- *
- * The general idea here is to reduce the number of locations where a
- * particular piece of state is kept (and therefore has to be synchronised
- * between). %PropertyAction does not have a separate state that is kept
- * in sync with the property value -- its state is the property value.
- *
- * For example, it might be useful to create an Action corresponding to
- * property_visible_child_name() of a Gtk::Stack so that the current
- * page can be switched from a menu. The active radio indication in the
- * menu is then directly determined from the active page of the Gtk::Stack.
- *
- * An anti-example would be binding property_active_id() on a Gtk::ComboBox.
- * This is because the state of the combobox itself is probably uninteresting
- * and is actually being used to control something else.
- *
- * Another anti-example would be to bind to property_visible_child_name()
- * of a Gtk::Stack if this value is actually stored in Gio::Settings.
- * In that case, the real source of the value is
- * Gio::Settings. If you want an Action to control a setting stored in
- * Gio::Settings, see Gio::Settings::create_action() instead, and possibly
- * combine its use with Gio::Settings::bind().
- *
- * @newin{2,52}
- */
-class PropertyAction : public Glib::Object, public Action
-{
-  _CLASS_GOBJECT(PropertyAction, GPropertyAction, G_PROPERTY_ACTION, Glib::Object, GObject)
-  _IMPLEMENTS_INTERFACE(Action)
-
-protected:
-  PropertyAction(const Glib::ustring& name, const Glib::PropertyProxy_Base& property_proxy,
-    bool invert_boolean = false);
-
-public:
-  /** Creates an Action corresponding to the value of property @a property_proxy.
-   *
-   * The property must be existent and readable and writable (and not construct-only).
-   *
-   * This function takes a reference on the property's object and doesn't
-   * release it until the action is destroyed.
-   *
-   * @param name The name of the action to create.
-   * @param property_proxy The property to bind.
-   * @param invert_boolean If <tt>true</tt>, the state of the action will be
-   *        the negation of the property value, provided the property is boolean.
-   * @return A new %PropertyAction.
-   *
-   * @newin{2,52}
-   */
-  _WRAP_CREATE(const Glib::ustring& name, const Glib::PropertyProxy_Base& property_proxy,
-    bool invert_boolean = false)
-
-  _WRAP_PROPERTY("name", Glib::ustring, newin "2,52")
-  _WRAP_PROPERTY("parameter-type", Glib::VariantType, newin "2,52")
-  _WRAP_PROPERTY("enabled", bool, newin "2,52")
-  _WRAP_PROPERTY("state-type", Glib::VariantType, newin "2,52")
-  _WRAP_PROPERTY("state", Glib::VariantBase, newin "2,52")
-  //_WRAP_PROPERTY("object", Glib::ObjectBase) // write-only, construct-only
-  //_WRAP_PROPERTY("property-name", Glib::ustring) // write-only, construct-only
-  _WRAP_PROPERTY("invert-boolean", bool, newin "2,52")
-
-  // There are no methods (apart from ctor and create), signals or vfuncs.
-};
-
-} // namespace Gio
index 57ec71d..0ce7159 100644 (file)
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <giomm/actiongroup.h>
+#include <glibmm/interface.h>
 
 _DEFS(giomm,gio)
-_PINCLUDE(giomm/private/actiongroup_p.h)
+_PINCLUDE(glibmm/private/interface_p.h)
 _PINCLUDE(gio/gio.h)
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
@@ -30,6 +30,12 @@ typedef struct _GRemoteActionGroupInterface GRemoteActionGroupInterface;
 namespace Gio
 {
 
+
+//TODO: Instead derive from ActionGroup, when we can break ABI,
+//because the GRemoteActionGroup interface requires the GActionGroup interface.
+//LoadableIcon does a similar thing correctly, for instance.
+
+
 /** RemoteActionGroup - a ActionGroup that interacts with other processes.
  * The RemoteActionGroup interface is implemented by ActionGroup instances that
  * either transmit action invocations to other processes or receive action
@@ -51,9 +57,9 @@ namespace Gio
  * platform data for action invocations that arrive by way of D-Bus.
  * @newin{2,32}
  */
-class RemoteActionGroup : public ActionGroup
+class RemoteActionGroup : public Glib::Interface
 {
-  _CLASS_INTERFACE(RemoteActionGroup, GRemoteActionGroup, G_REMOTE_ACTION_GROUP, GRemoteActionGroupInterface, ActionGroup, GActionGroup)
+  _CLASS_INTERFACE(RemoteActionGroup, GRemoteActionGroup, G_REMOTE_ACTION_GROUP, GRemoteActionGroupInterface)
 
 public:
   _WRAP_METHOD(void activate_action(const Glib::ustring& action_name, const Glib::VariantBase& parameter, const Glib::VariantBase& platform_data), g_remote_action_group_activate_action_full)
@@ -61,8 +67,8 @@ public:
 
 #m4 _CONVERSION(`GVariant*',`const Glib::VariantBase&',`Glib::wrap($3, true)')
 
-  _WRAP_VFUNC(void activate_action_full(const Glib::ustring& action_name, const Glib::VariantBase& parameter, const Glib::VariantBase& platform_data), "activate_action_full")
-  _WRAP_VFUNC(void change_action_state_full(const Glib::ustring& action_name, const Glib::VariantBase& value, const Glib::VariantBase& platform_data), "change_action_state_full")
+  _WRAP_VFUNC(void activate_action(const Glib::ustring& action_name, const Glib::VariantBase& parameter, const Glib::VariantBase& platform_data), "activate_action_full")
+  _WRAP_VFUNC(void change_action_state(const Glib::ustring& action_name, const Glib::VariantBase& value, const Glib::VariantBase& platform_data), "change_action_state_full")
 };
 
 } // namespace Gio
index 67258e5..a958b07 100644 (file)
@@ -164,7 +164,8 @@ public:
 
   _WRAP_METHOD(std::vector<Glib::VariantContainerBase> lookup_records_finish(const Glib::RefPtr<AsyncResult>& result), g_resolver_lookup_records_finish, errthrow)
 
-  _WRAP_SIGNAL(void reload(), reload)
+  //TODO: Remove no_default_handler when we can break ABI:
+  _WRAP_SIGNAL(void reload(), reload, no_default_handler)
 };
 
 std::string hostname_to_ascii (const Glib::ustring& hostname);
index d1fca86..3ec8691 100644 (file)
@@ -18,7 +18,6 @@
 #include <gio/gio.h>
 #include <glibmm/exceptionhandler.h>
 #include <glibmm/vectorutils.h>
-#include <giomm/settingsschema.h>
 
 namespace Gio
 {
@@ -67,4 +66,14 @@ Settings::bind_writable(
   bind_writable(key, property_proxy.get_object(), property_proxy.get_name(), inverted);
 }
 
+_DEPRECATE_IFDEF_START
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+std::vector<Glib::ustring>
+Settings::list_schemas()
+{
+  return Glib::ArrayHandler<Glib::ustring>::array_to_vector(
+    g_settings_list_schemas(), Glib::OWNERSHIP_NONE);
+}
+G_GNUC_END_IGNORE_DEPRECATIONS
+_DEPRECATE_IFDEF_END
 }
index 4fc2d8d..24fd10b 100644 (file)
@@ -27,7 +27,6 @@ _PINCLUDE(glibmm/private/object_p.h)
 
 namespace Gio
 {
-class SettingsSchema;
 
   _WRAP_ENUM(SettingsBindFlags, GSettingsBindFlags)
 
@@ -47,14 +46,12 @@ protected:
   _WRAP_CTOR(Settings(const Glib::ustring& schema_id, const Glib::ustring& path), g_settings_new_with_path)
   //TODO: Requires SettingsBackend: _WRAP_CTOR(Settings(const Glib::ustring& schema_id, const Glib::RefPtr<SettingsBackend>& backend), g_settings_new_with_backend)
   //TODO: Requires SettingsBackend: _WRAP_CTOR(Settings(const Glib::ustring& schema_id, const Glib::RefPtr<SettingsBackend>& backend, const Glib::ustring& path), g_settings_new_with_backend_and_path)
-  //TODO: Requires SettingsBackend: _WRAP_CTOR(Settings(const Glib::RefPtr<SettingsSchema>& settings_schema, const Glib::RefPtr<SettingsBackend>& backend, const Glib::ustring& path), g_settings_new_full)
 
 public:
   _WRAP_CREATE(const Glib::ustring& schema_id)
   _WRAP_CREATE(const Glib::ustring& schema_id, const Glib::ustring& path)
   //TODO: Requires SettingsBackend: _WRAP_CREATE(const Glib::ustring& schema_id, const Glib::RefPtr<SettingsBackend>& backend)
   //TODO: Requires SettingsBackend: _WRAP_CREATE(const Glib::ustring& schema_id, const Glib::RefPtr<SettingsBackend>& backend, const Glib::ustring& path)
-  //TODO: Requires SettingsBackend: _WRAP_CREATE(const Glib::RefPtr<SettingsSchema>& settings_schema, const Glib::RefPtr<SettingsBackend>& backend, const Glib::ustring& path)
 
   //TODO: Rename these to get/set_*_value_variant() and add templated get/set_*_value() methods as elsewhere?
   _WRAP_METHOD(bool set_value(const Glib::ustring& key, const Glib::VariantBase& value),  g_settings_set_value)
@@ -139,6 +136,7 @@ public:
   _WRAP_METHOD(gint64 get_int64(const Glib::ustring& key) const, g_settings_get_int64)
   _WRAP_METHOD(void set_int64(const Glib::ustring& key, gint64 value), g_settings_set_int64)
   _WRAP_METHOD(guint get_uint(const Glib::ustring& key) const, g_settings_get_uint)
+  _WRAP_METHOD(void set_uiint(const Glib::ustring& key, guint value), g_settings_set_uint, deprecated "Use set_uint() instead.")
   _WRAP_METHOD(void set_uint(const Glib::ustring& key, guint value), g_settings_set_uint)
   _WRAP_METHOD(guint64 get_uint64(const Glib::ustring& key) const, g_settings_get_uint64)
   _WRAP_METHOD(void set_uint64(const Glib::ustring& key, guint64 value), g_settings_set_uint64)
@@ -155,8 +153,12 @@ public:
   _WRAP_METHOD(bool set_string_array(const Glib::ustring& key,  const Glib::StringArrayHandle& value), g_settings_set_strv)
 
   _WRAP_METHOD(int get_enum(const Glib::ustring& key) const, g_settings_get_enum)
+  _WRAP_METHOD(bool get_enum(const Glib::ustring& key, int value), g_settings_set_enum,
+    deprecated "This method is misnamed. Use set_enum() instead.")
   _WRAP_METHOD(bool set_enum(const Glib::ustring& key, int value), g_settings_set_enum)
   _WRAP_METHOD(guint get_flags(const Glib::ustring& key) const, g_settings_get_flags)
+  _WRAP_METHOD(bool get_flags(const Glib::ustring& key, guint value), g_settings_set_flags,
+    deprecated "This method is misnamed. Use set_flags() instead.")
   _WRAP_METHOD(bool set_flags(const Glib::ustring& key, guint value), g_settings_set_flags)
 
   // Ignore varargs functions.
@@ -173,13 +175,23 @@ public:
 
   _WRAP_METHOD(void reset(const Glib::ustring& key), g_settings_reset)
 
+_DEPRECATE_IFDEF_START
+//We must hand-code this because gmmproc is confused by the static keyword with the vector.
+//#m4 _CONVERSION(`const gchar*const*',`std::vector<Glib::ustring>',`Glib::ArrayHandler<Glib::ustring>::array_to_vector($3, Glib::OWNERSHIP_NONE)')
+  _WRAP_METHOD_DOCS_ONLY(g_settings_list_schemas)
+  static std::vector<Glib::ustring> list_schemas();
+  _IGNORE(g_settings_list_schemas)
+_DEPRECATE_IFDEF_END
+
 #m4 _CONVERSION(`gchar**',`std::vector<Glib::ustring>',`Glib::ArrayHandler<Glib::ustring>::array_to_vector($3, Glib::OWNERSHIP_DEEP)')
   _WRAP_METHOD(std::vector<Glib::ustring> list_children() const, g_settings_list_children)
-  _IGNORE(g_settings_list_keys)
+  _WRAP_METHOD(std::vector<Glib::ustring> list_keys() const, g_settings_list_keys, deprecated "Use SettingsSchema::list_kes().")
 
   _IGNORE(g_settings_get_range, g_settings_list_relocatable_schemas) // deprecated
 
-  _IGNORE(g_settings_range_check)
+  _WRAP_METHOD(bool range_check(const Glib::ustring& key, const Glib::VariantBase& value) const, g_settings_range_check,
+    deprecated "Use g_settings_schema_key_range_check() instead.")
+  //TODO: Wrap GSettingsSchema
 
 #m4 _CONVERSION(`Glib::ObjectBase*',`gpointer',(gpointer)$3->gobj())
   _WRAP_METHOD(void bind(const Glib::ustring& key, Glib::ObjectBase* object, const Glib::ustring& property, SettingsBindFlags flags=SETTINGS_BIND_DEFAULT), g_settings_bind)
@@ -196,15 +208,16 @@ public:
   _WRAP_PROPERTY("delay-apply", bool)
   _WRAP_PROPERTY("has-unapplied", bool)
   _WRAP_PROPERTY("path", std::string)
-  _IGNORE_PROPERTY("schema")
+  _WRAP_PROPERTY("schema", Glib::ustring, deprecated "Use the 'schema-id' property instead. In a future version, this property may instead refer to a SettingsSchema.")
   _WRAP_PROPERTY("schema-id", Glib::ustring)
 
-  _WRAP_PROPERTY("settings-schema", Glib::RefPtr<SettingsSchema>, newin "2,52")
+  //TODO: _WRAP_PROPERTY("settings-schema", Glib::RefPtr<SettingsSchema>)
 
   //TODO?: _WRAP_SIGNAL(bool change_event(const Glib::ArrayHandle<Glib::QueryQuark>& keys, int n_keys), "change-event")
 
+  //TODO: Remove two_signal_methods when we can break ABI.
 #m4 _CONVERSION(`const char*',`const Glib::ustring&',__GCHARP_TO_USTRING)
-  _WRAP_SIGNAL(void changed(const Glib::ustring& key), "changed", detail_name key)
+  _WRAP_SIGNAL(void changed(const Glib::ustring& key), "changed", detail_name key, two_signal_methods)
 
   _WRAP_SIGNAL(bool writable_change_event(GQuark key), "writable-change-event")
   _WRAP_SIGNAL(void writable_changed(const Glib::ustring& key), writable_changed)
index cf5f0da..e7894d6 100644 (file)
@@ -18,7 +18,6 @@
 _CONFIGINCLUDE(giommconfig.h)
 
 #include <glibmm/variant.h>
-#include <glibmm/varianttype.h>
 
 _DEFS(giomm,gio)
 _PINCLUDE(glibmm/private/object_p.h)
@@ -51,14 +50,14 @@ protected:
     g_settings_schema_key_from_flags)
 
 public:
+  //TODO: _WRAP_METHOD(const GVariantType *    g_settings_schema_key_get_value_type           (), g_settings_schema_key_get_value_type)
+  //_WRAP_METHOD(GVariant *              g_settings_schema_key_get_default_value        (), g_settings_schema_key_get_default_value)
+  //_WRAP_METHOD(GVariant *              g_settings_schema_key_get_range                (), g_settings_schema_key_get_range)
+  //TODO: _WRAP_METHOD(bool range_check(GVariant               *value), g_settings_schema_key_range_check)
+
   _WRAP_METHOD(Glib::ustring get_name() const, g_settings_schema_key_get_name)
   _WRAP_METHOD(Glib::ustring get_summary() const, g_settings_schema_key_get_summary)
   _WRAP_METHOD(Glib::ustring get_description() const, g_settings_schema_key_get_description)
-
-  _WRAP_METHOD(Glib::VariantType get_value_type() const, g_settings_schema_key_get_value_type)
-  _WRAP_METHOD(Glib::VariantBase get_default_value() const, g_settings_schema_key_get_default_value)
-  _WRAP_METHOD(Glib::VariantBase get_range() const, g_settings_schema_key_get_range)
-  _WRAP_METHOD(bool range_check(const Glib::VariantBase& value) const, g_settings_schema_key_range_check)
 };
 
 } // namespace Gio
index fe7e669..1c57541 100644 (file)
@@ -144,9 +144,6 @@ public:
 
   _WRAP_METHOD(void set_enabled(bool enabled = true), g_simple_action_set_enabled)
 
-  //TODO: Add templated version of this, renaming this to set_state_variant(), like Action::change_state()?
-  _WRAP_METHOD(void set_state(const Glib::VariantBase& value), g_simple_action_set_state)
-
   _WRAP_METHOD(void set_state_hint(const Glib::VariantBase& state_hint), g_simple_action_set_state_hint)
 
   _WRAP_PROPERTY("enabled", bool)
@@ -159,6 +156,13 @@ public:
 
   _WRAP_SIGNAL(void activate(const Glib::VariantBase& parameter), "activate", no_default_handler)
   _WRAP_SIGNAL(void change_state(const Glib::VariantBase& value), "change-state", no_default_handler)
+
+protected:
+
+  //TODO: Add templated version of this, renaming this to set_state_variant(), like Action::change_state()?
+  //This is protected because the C docs say "This should only be called by the implementor of the action."
+  // though that is not entirely clear. We can make this public if somebody needs it.
+  _WRAP_METHOD(void set_state(const Glib::VariantBase& value), g_simple_action_set_state)
 };
 
 } // namespace Gio
index 36dd91b..0c3fc8c 100644 (file)
@@ -49,7 +49,11 @@ public:
   _WRAP_METHOD_DOCS_ONLY(g_simple_action_group_new)
   _WRAP_CREATE()
 
-  _IGNORE(g_simple_action_group_lookup, g_simple_action_group_insert, g_simple_action_group_remove)
+  _WRAP_METHOD(Glib::RefPtr<Action> lookup(const Glib::ustring& action_name), g_simple_action_group_lookup, refreturn, deprecated "Use ActionMap::lookup_action() instead")
+  _WRAP_METHOD(Glib::RefPtr<const Action> lookup(const Glib::ustring& action_name) const, g_simple_action_group_lookup, refreturn, constversion, deprecated "Use ActionMap::lookup_action() instead")
+
+  _WRAP_METHOD(void insert(const Glib::RefPtr<Action>& action), g_simple_action_group_insert, deprecated "Use ActionMap::add_action() instead")
+  _WRAP_METHOD(void remove(const Glib::ustring& action_name), g_simple_action_group_remove, deprecated "Use ActionMap::remove_action() instead")
 
   _IGNORE(g_simple_action_group_add_entries) // deprecated
 };
index 5867943..16257f7 100644 (file)
@@ -1,3 +1,5 @@
+// -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+
 /* Copyright (C) 2010 Jonathon Jongsma
  *
  * This library is free software; you can redistribute it and/or
@@ -169,7 +171,7 @@ public:
 
 #m4 _CONVERSION(`GSocketConnectable*',`const Glib::RefPtr<SocketConnectable>&',`Glib::wrap($3)')
 #m4 _CONVERSION(`GIOStream*',`const Glib::RefPtr<IOStream>&',`Glib::wrap($3)')
-  _WRAP_SIGNAL(void event(SocketClientEvent event, const Glib::RefPtr<SocketConnectable>& connectable, const Glib::RefPtr<IOStream>& connection), event)
+  _WRAP_SIGNAL(void event(SocketClientEvent event, const Glib::RefPtr<SocketConnectable>& connectable, const Glib::RefPtr<IOStream>& connection), event, no_default_handler)
 };
 
 } // namespace Gio
index 319c052..80852f1 100644 (file)
@@ -64,7 +64,10 @@ public:
   _WRAP_METHOD(void set_rehandshake_mode(TlsRehandshakeMode mode), g_tls_connection_set_rehandshake_mode)
   _WRAP_METHOD(TlsRehandshakeMode get_rehandshake_mode() const, g_tls_connection_get_rehandshake_mode)
 
-  _IGNORE(g_tls_connection_set_use_system_certdb, g_tls_connection_get_use_system_certdb)
+  _WRAP_METHOD(void set_use_system_certdb(bool use_system_certdb = true), g_tls_connection_set_use_system_certdb,
+    deprecated "Use set_database() instead.")
+  _WRAP_METHOD(bool get_use_system_certdb() const, g_tls_connection_get_use_system_certdb,
+    deprecated "Use get_database() instead.")
 
   _WRAP_METHOD(Glib::RefPtr<TlsDatabase> get_database(), g_tls_connection_get_database)
   _WRAP_METHOD(Glib::RefPtr<const TlsDatabase> get_database() const, g_tls_connection_get_database, constversion)
@@ -91,7 +94,7 @@ public:
   _WRAP_PROPERTY("peer-certificate-errors", TlsCertificateFlags)
   _WRAP_PROPERTY("rehandshake-mode", TlsRehandshakeMode)
   _WRAP_PROPERTY("require-close-notify", bool)
-  _IGNORE_PROPERTY("use-system-certdb")
+  _WRAP_PROPERTY("use-system-certdb", bool, deprecated "Use property_database() instead.")
 
 #m4 _CONVERSION(`GTlsCertificate*',`const Glib::RefPtr<const TlsCertificate>&',`Glib::wrap($3, true)')
   _WRAP_SIGNAL(bool accept_certificate(const Glib::RefPtr<const TlsCertificate>& peer_cert, TlsCertificateFlags errors), "accept_certificate")
index cea8669..e3e4170 100644 (file)
@@ -82,7 +82,7 @@ public:
 
  _WRAP_METHOD(static bool abstract_names_supported(), g_unix_socket_address_abstract_names_supported)
 
-  _IGNORE_PROPERTY("abstract")
+  _WRAP_PROPERTY("abstract", bool, deprecated "Use property_address_type() instead, which distinguishes between zero-padded and non-zero-padded abstract addresses.")
   _WRAP_PROPERTY("address-type", UnixSocketAddressType)
   _WRAP_PROPERTY("path", std::string)
   _WRAP_PROPERTY("path-as-array", Glib::RefPtr<ByteArray>)
index b55fc7d..df32646 100644 (file)
@@ -55,7 +55,8 @@ public:
   _WRAP_METHOD(Glib::RefPtr<Volume> get_volume_for_uuid(const std::string& uuid), g_volume_monitor_get_volume_for_uuid, refreturn)
   _WRAP_METHOD(Glib::RefPtr<Mount> get_mount_for_uuid(const std::string& uuid), g_volume_monitor_get_mount_for_uuid, refreturn)
 
-  _IGNORE(g_volume_monitor_adopt_orphan_mount)
+  _WRAP_METHOD(static Glib::RefPtr<Volume> adopt_orphan_mount(const Glib::RefPtr<Mount>& mount), g_volume_monitor_adopt_orphan_mount,
+    deprecated "Instead of using this function, create shadow mounts with the URI of the mount you intend to adopt.")
 
 #m4 _CONVERSION(`GVolume*',`const Glib::RefPtr<Volume>&',`Glib::wrap($3, true)')
   _WRAP_SIGNAL(void volume_added(const Glib::RefPtr<Volume>& volume), volume_added)
@@ -73,8 +74,9 @@ public:
   _WRAP_SIGNAL(void drive_disconnected(const Glib::RefPtr<Drive>& drive), drive_disconnected)
   _WRAP_SIGNAL(void drive_changed(const Glib::RefPtr<Drive>& drive), drive_changed)
 
-  _WRAP_SIGNAL(void drive_eject_button(const Glib::RefPtr<Drive>& drive), drive_eject_button)
-  _WRAP_SIGNAL(void drive_stop_button(const Glib::RefPtr<Drive>& drive), drive_stop_button)
+  //TODO: Remove no_default_handler when we can break ABI:
+  _WRAP_SIGNAL(void drive_eject_button(const Glib::RefPtr<Drive>& drive), drive_eject_button, no_default_handler)
+  _WRAP_SIGNAL(void drive_stop_button(const Glib::RefPtr<Drive>& drive), drive_stop_button, no_default_handler)
 
   //TODO: Use ListHandle?
   //_WRAP_VFUNC(GList* get_volumes(), get_volumes)
index 153d65e..80b27b5 100644 (file)
  *
  * If your  source file is @c program.cc, you can compile it with:
  * @code
- * g++ program.cc -o program  `pkg-config --cflags --libs glibmm-2.52 giomm-2.52`
+ * g++ program.cc -o program  `pkg-config --cflags --libs glibmm-2.4 giomm-2.4`
  * @endcode
  *
  * Alternatively, if using autoconf, use the following in @c configure.ac:
  * @code
- * PKG_CHECK_MODULES([GLIBMM], [glibmm-2.52 giomm-2.52])
+ * PKG_CHECK_MODULES([GLIBMM], [glibmm-2.4 giomm-2.4])
  * @endcode
  * Then use the generated @c GLIBMM_CFLAGS and @c GLIBMM_LIBS variables in the
  * project Makefile.am files. For example:
 //#include <glibmm/i18n.h> //This must be included by the application, after system headers such as
 //<iostream>.
 
+// Include this first because we need it to be the first thing to include <glib.h>,
+// so we can do an undef trick to still use deprecated API in the header:
+#include <glibmm/thread.h>
+
+#include <glibmm/threads.h>
+
 #include <glibmm/arrayhandle.h>
 #include <glibmm/balancedtree.h>
 #include <glibmm/base64.h>
 #include <glibmm/slisthandle.h>
 #include <glibmm/spawn.h>
 #include <glibmm/stringutils.h>
+#include <glibmm/threadpool.h>
 #include <glibmm/timer.h>
 #include <glibmm/timeval.h>
 #include <glibmm/timezone.h>
 #include <glibmm/uriutils.h>
 #include <glibmm/ustring.h>
 #include <glibmm/value.h>
+#include <glibmm/valuearray.h>
 #include <glibmm/variant.h>
 #include <glibmm/variantdict.h>
 #include <glibmm/variantiter.h>
index 25e6c16..b08f62d 100644 (file)
@@ -16,6 +16,6 @@ Name: glibmm
 Description: C++ wrapper for GLib
 Version: @PACKAGE_VERSION@
 URL: http://www.gtkmm.org/
-Requires: gobject-2.0 sigc++-3.0
+Requires: gobject-2.0 sigc++-2.0
 Libs: -L${libdir} -lglibmm-@GLIBMM_API_VERSION@
 Cflags: -I${includedir}/@GLIBMM_MODULE_NAME@ -I${libdir}/@GLIBMM_MODULE_NAME@/include
index 29ab8cf..75b7d13 100644 (file)
@@ -85,9 +85,14 @@ Class::register_derived_type(GType base_type, GTypeModule* module)
 }
 
 GType
+Class::clone_custom_type(const char* custom_type_name) const
+{
+  return clone_custom_type(custom_type_name, interface_class_vector_type());
+}
+
+GType
 Class::clone_custom_type(
-  const char* custom_type_name, const interface_classes_type* interface_classes,
-  const class_init_funcs_type* class_init_funcs, GInstanceInitFunc instance_init_func) const
+  const char* custom_type_name, const interface_class_vector_type& interface_classes) const
 {
   std::string full_name("gtkmm__CustomObject_");
   Glib::append_canonical_typename(full_name, custom_type_name);
@@ -113,43 +118,30 @@ Class::clone_custom_type(
     // GTypeQuery::instance_size is guint but GTypeInfo::instance_size is guint16.
     const guint16 instance_size = (guint16)base_query.instance_size;
 
-    // Let the wrapper's class_init_function() be the first one to call.
-    auto all_class_init_funcs = new class_init_funcs_type(
-      1, std::tuple<GClassInitFunc, void*>(class_init_func_, nullptr));
-    if (class_init_funcs)
-      all_class_init_funcs->insert(all_class_init_funcs->end(),
-        class_init_funcs->begin(), class_init_funcs->end());
-
     const GTypeInfo derived_info = {
       class_size,
       nullptr, // base_init
       &Class::custom_class_base_finalize_function, // base_finalize
       &Class::custom_class_init_function,
       nullptr, // class_finalize
-      all_class_init_funcs, // class_data
+      this, // class_data
       instance_size,
       0, // n_preallocs
-      instance_init_func, // instance_init
+      nullptr, // instance_init
       nullptr, // value_table
     };
 
-    // custom_class_init_function() is called when the first object of the custom
-    // class is created, which is after clone_custom_type() has returned.
-    // Let custom_class_init_function() delete all_class_init_funcs.
-
     custom_type =
       g_type_register_static(base_type, full_name.c_str(), &derived_info, GTypeFlags(0));
 
     // Add derived versions of interfaces, if the C type implements any interfaces.
     // For instance, TreeModel_Class::add_interface().
-    if (interface_classes)
+    for (interface_class_vector_type::size_type i = 0; i < interface_classes.size(); i++)
     {
-      for (auto interface_class : *interface_classes)
+      const Interface_Class* interface_class = interface_classes[i];
+      if (interface_class)
       {
-        if (interface_class)
-        {
-          interface_class->add_interface(custom_type);
-        }
+        interface_class->add_interface(custom_type);
       }
     }
   }
@@ -185,36 +177,19 @@ Class::custom_class_base_finalize_function(void* g_class)
 void
 Class::custom_class_init_function(void* g_class, void* class_data)
 {
-  // clone_custom_type() sets the class data pointer to a pointer to a vector
-  // of pointers to functions to be called.
-  const class_init_funcs_type& class_init_funcs =
-    *static_cast<class_init_funcs_type*>(class_data);
+  // The class_data pointer is set to 'this' by clone_custom_type().
+  const Class* const self = static_cast<Class*>(class_data);
 
-  g_return_if_fail(!class_init_funcs.empty() && std::get<GClassInitFunc>(class_init_funcs[0]) != nullptr);
+  g_return_if_fail(self->class_init_func_ != nullptr);
 
   // Call the wrapper's class_init_function() to redirect
   // the vfunc and default signal handler callbacks.
-  auto init_func = std::get<GClassInitFunc>(class_init_funcs[0]);
-  (*init_func)(g_class, nullptr);
+  (*self->class_init_func_)(g_class, nullptr);
 
   GObjectClass* const gobject_class = static_cast<GObjectClass*>(g_class);
   gobject_class->get_property = &Glib::custom_get_property_callback;
   gobject_class->set_property = &Glib::custom_set_property_callback;
 
-  // Call extra class init functions, if any.
-  for (std::size_t i = 1; i < class_init_funcs.size(); ++i)
-  {
-    if (auto extra_init_func = std::get<GClassInitFunc>(class_init_funcs[i]))
-    {
-      auto extra_class_data = std::get<void*>(class_init_funcs[i]);
-      (*extra_init_func)(g_class, extra_class_data);
-    }
-  }
-
-  // Assume that this function is called exactly once for each type.
-  // Delete the class_init_funcs_type that was created in clone_custom_type().
-  delete static_cast<class_init_funcs_type*>(class_data);
-
   // Override the properties of implemented interfaces, if any.
   const GType object_type = G_TYPE_FROM_CLASS(g_class);
 
index e790715..bc5a06a 100644 (file)
@@ -1,6 +1,9 @@
+// -*- c++ -*-
 #ifndef _GLIBMM_CLASS_H
 #define _GLIBMM_CLASS_H
 
+/* $Id$ */
+
 /* Copyright 2001 Free Software Foundation
  * Copyright (C) 1998-2002 The gtkmm Development Team
  *
@@ -23,7 +26,6 @@
 #include <glibmmconfig.h> //Include this here so that the /private/*.h classes have access to GLIBMM_VFUNCS_ENABLED
 
 #include <vector> //For interface properties that custom types might override.
-#include <tuple>
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 
@@ -52,13 +54,20 @@ public:
 
   inline GType get_type() const;
 
-  /// The type that holds pointers to the interfaces of custom types.
-  using interface_classes_type = std::vector<const Interface_Class*>;
-  /** The type that holds pointers to extra class init functions of custom types.
-   * The std::tuple contains a function pointer and a pointer to class data.
-   * The class data pointer can be nullptr, if the function does not need it.
+  // TODO: Remove this method at the next ABI/API break.
+  /** Register a static custom GType, derived from the parent of this class's type.
+   * The parent type of the registered custom type is the same C class as the parent
+   * of the get_type() type. If a type with the specified name is already registered,
+   * nothing is done. register_derived_type() must have been called.
+   * @param custom_type_name The name of the registered type is
+   *        "gtkmm__CustomObject_" + canonic(custom_type_name), where canonic()
+   *        replaces special characters with '+'.
+   * @return The registered type.
    */
-  using class_init_funcs_type = std::vector<std::tuple<GClassInitFunc, void*>>;
+  GType clone_custom_type(const char* custom_type_name) const;
+
+  /// The type that holds pointers to the interfaces of custom types.
+  using interface_class_vector_type = std::vector<const Interface_Class*>;
 
   /** Register a static custom GType, derived from the parent of this class's type.
    * The parent type of the registered custom type is the same C class as the parent
@@ -67,16 +76,11 @@ public:
    * @param custom_type_name The name of the registered type is
    *        "gtkmm__CustomObject_" + canonic(custom_type_name), where canonic()
    *        replaces special characters with '+'.
-   * @param interface_classes Interfaces that the custom type implements (can be nullptr).
-   * @param class_init_funcs Extra class init functions (can be nullptr). These
-   *        functions, if any, are called after the class init function of this
-   *        class's type, e.g. Gtk::Widget.
-   * @param instance_init_func Instance init function (can be nullptr).
+   * @param interface_classes Interfaces that the custom type implements.
    * @return The registered type.
    */
   GType clone_custom_type(
-    const char* custom_type_name, const interface_classes_type* interface_classes,
-    const class_init_funcs_type* class_init_funcs, GInstanceInitFunc instance_init_func) const;
+    const char* custom_type_name, const interface_class_vector_type& interface_classes) const;
 
 protected:
   GType gtype_;
index 2e23526..d9067a3 100644 (file)
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#ifndef GLIBMM_CAN_USE_THREAD_LOCAL
+#include <glibmm/threads.h>
+#endif
+
 #include <glibmm/dispatcher.h>
 #include <glibmm/exceptionhandler.h>
 #include <glibmm/fileutils.h>
@@ -23,8 +27,7 @@
 #include <cerrno>
 #include <fcntl.h>
 #include <glib.h>
-#include <forward_list>
-#include <memory>
+#include <set>
 #include <utility> // For std::move()
 
 #ifdef G_OS_WIN32
 #define EINTR 0 /* TODO: should use the real define */
 #endif
 
-namespace Glib
-{
-class DispatchNotifier;
-}
-
 namespace
 {
 
 struct DispatchNotifyData
 {
-  Glib::Dispatcher::Impl* dispatcher_impl;
+  Glib::Dispatcher* dispatcher;
   Glib::DispatchNotifier* notifier;
 
-  DispatchNotifyData()
-  : dispatcher_impl(nullptr), notifier(nullptr)
-  {}
+  DispatchNotifyData() : dispatcher(nullptr), notifier(nullptr) {}
 
-  DispatchNotifyData(Glib::Dispatcher::Impl* d, Glib::DispatchNotifier* n)
-  : dispatcher_impl(d), notifier(n)
-  {}
+  DispatchNotifyData(Glib::Dispatcher* d, Glib::DispatchNotifier* n) : dispatcher(d), notifier(n) {}
 };
 
 static void
@@ -127,33 +121,11 @@ fd_close_and_invalidate(int& fd)
 }
 #endif /* !G_OS_WIN32 */
 
-void warn_dropped_dispatcher_message()
-{
-  g_warning("Dropped dispatcher message as the dispatcher no longer exists.");
-}
-
 } // anonymous namespace
 
 namespace Glib
 {
 
-// The most important reason for having the dispatcher implementation in a separate
-// class is that its deletion can be delayed until it's safe to delete it.
-// Deletion is safe when the pipe does not contain any message to the dispatcher
-// to delete. When the pipe is empty, it's surely safe.
-struct Dispatcher::Impl
-{
-public:
-  sigc::signal<void()> signal_;
-  DispatchNotifier*  notifier_;
-
-  explicit Impl(const Glib::RefPtr<MainContext>& context);
-
-  // noncopyable
-  Impl(const Impl&) = delete;
-  Impl& operator=(const Impl&) = delete;
-};
-
 class DispatchNotifier : public sigc::trackable
 {
 public:
@@ -163,10 +135,11 @@ public:
   DispatchNotifier(const DispatchNotifier&) = delete;
   DispatchNotifier& operator=(const DispatchNotifier&) = delete;
 
-  static DispatchNotifier* reference_instance(const Glib::RefPtr<MainContext>& context);
-  static void unreference_instance(DispatchNotifier* notifier, Dispatcher::Impl* dispatcher_impl);
+  static DispatchNotifier* reference_instance(
+    const Glib::RefPtr<MainContext>& context, const Dispatcher* dispatcher);
+  static void unreference_instance(DispatchNotifier* notifier, const Dispatcher* dispatcher);
 
-  void send_notification(Dispatcher::Impl* dispatcher_impl);
+  void send_notification(Dispatcher* dispatcher);
 
 protected:
   // Only used by reference_instance().  Should be private, but that triggers
@@ -174,10 +147,14 @@ protected:
   explicit DispatchNotifier(const Glib::RefPtr<MainContext>& context);
 
 private:
+#ifdef GLIBMM_CAN_USE_THREAD_LOCAL
   static thread_local DispatchNotifier* thread_specific_instance_;
+#else
+  static Glib::Threads::Private<DispatchNotifier> thread_specific_instance_;
+#endif
+
+  std::set<const Dispatcher*> deleted_dispatchers_;
 
-  using UniqueImplPtr = std::unique_ptr<Dispatcher::Impl>;
-  std::forward_list<UniqueImplPtr> orphaned_dispatcher_impl_;
   long ref_count_;
   Glib::RefPtr<MainContext> context_;
 #ifdef G_OS_WIN32
@@ -196,10 +173,16 @@ private:
 
 /**** Glib::DispatchNotifier ***********************************************/
 
+// static
+
+#ifdef GLIBMM_CAN_USE_THREAD_LOCAL
 thread_local DispatchNotifier* DispatchNotifier::thread_specific_instance_ = nullptr;
+#else
+Glib::Threads::Private<DispatchNotifier> DispatchNotifier::thread_specific_instance_;
+#endif
 
 DispatchNotifier::DispatchNotifier(const Glib::RefPtr<MainContext>& context)
-: orphaned_dispatcher_impl_(),
+: deleted_dispatchers_(),
   ref_count_(0),
   context_(context),
 #ifdef G_OS_WIN32
@@ -295,20 +278,40 @@ DispatchNotifier::create_pipe()
 }
 
 // static
-DispatchNotifier* DispatchNotifier::reference_instance(
-  const Glib::RefPtr<MainContext>& context)
+DispatchNotifier*
+DispatchNotifier::reference_instance(
+  const Glib::RefPtr<MainContext>& context, const Dispatcher* dispatcher)
 {
+#ifdef GLIBMM_CAN_USE_THREAD_LOCAL
   DispatchNotifier* instance = thread_specific_instance_;
+#else
+  DispatchNotifier* instance = thread_specific_instance_.get();
+#endif
 
   if (!instance)
   {
     instance = new DispatchNotifier(context);
+#ifdef GLIBMM_CAN_USE_THREAD_LOCAL
     thread_specific_instance_ = instance;
+#else
+    thread_specific_instance_.replace(instance);
+#endif
   }
   else
   {
     // Prevent massive mess-up.
     g_return_val_if_fail(instance->context_ == context, nullptr);
+
+    // In the possible but unlikely case that a new dispatcher gets the same
+    // address as a newly deleted one, if the pipe still contains messages to
+    // the deleted dispatcher, those messages will be delivered to the new one.
+    // Not ideal, but perhaps the best that can be done without breaking ABI.
+    // The alternative would be to remove the following erase(), and risk not
+    // delivering messages sent to the new dispatcher.
+    // TODO: When we can break ABI, a better solution without this drawback can
+    // be implemented. See https://bugzilla.gnome.org/show_bug.cgi?id=651942
+    // especially comment 16.
+    instance->deleted_dispatchers_.erase(dispatcher);
   }
 
   ++instance->ref_count_; // initially 0
@@ -317,49 +320,48 @@ DispatchNotifier* DispatchNotifier::reference_instance(
 }
 
 // static
-void DispatchNotifier::unreference_instance(
-  DispatchNotifier* notifier, Dispatcher::Impl* dispatcher_impl)
+void
+DispatchNotifier::unreference_instance(DispatchNotifier* notifier, const Dispatcher* dispatcher)
 {
+#ifdef GLIBMM_CAN_USE_THREAD_LOCAL
   DispatchNotifier* const instance = thread_specific_instance_;
+#else
+  DispatchNotifier* const instance = thread_specific_instance_.get();
+#endif
 
   // Yes, the notifier argument is only used to check for sanity.
   g_return_if_fail(instance == notifier);
 
   if (instance->pipe_is_empty())
-  {
-    // No messages in the pipe. Delete the Dispatcher::Impl immediately.
-    delete dispatcher_impl;
-    instance->orphaned_dispatcher_impl_.clear();
-  }
+    // No messages in the pipe. No need to keep track of deleted dispatchers.
+    instance->deleted_dispatchers_.clear();
   else
-  {
-    // There are messages in the pipe, possibly to the orphaned Dispatcher::Impl.
-    // Keep it around until it can safely be deleted.
-    // Delete all slots connected to the Dispatcher. Then the signal emission
-    // in pipe_io_handler() will do nothing.
-    dispatcher_impl->signal_.clear();
-    // Add a slot that will warn that a message has been dropped.
-    dispatcher_impl->signal_.connect(sigc::ptr_fun(warn_dropped_dispatcher_message));
-    instance->orphaned_dispatcher_impl_.push_front(UniqueImplPtr(dispatcher_impl));
-  }
+    // There are messages in the pipe, possibly to the deleted dispatcher.
+    // Keep its address, so pipe_io_handler() can avoid delivering messages to it.
+    instance->deleted_dispatchers_.insert(dispatcher);
 
   if (--instance->ref_count_ <= 0)
   {
     g_return_if_fail(instance->ref_count_ == 0); // could be < 0 if messed up
 
+#ifdef GLIBMM_CAN_USE_THREAD_LOCAL
     delete thread_specific_instance_;
     thread_specific_instance_ = nullptr;
+#else
+    thread_specific_instance_.replace(nullptr);
+#endif
   }
 }
 
-void DispatchNotifier::send_notification(Dispatcher::Impl* dispatcher_impl)
+void
+DispatchNotifier::send_notification(Dispatcher* dispatcher)
 {
 #ifdef G_OS_WIN32
   {
     const std::lock_guard<std::mutex> lock(mutex_);
 
     const bool was_empty = notify_queue_.empty();
-    notify_queue_.emplace_back(DispatchNotifyData(dispatcher_impl, this));
+    notify_queue_.emplace_back(DispatchNotifyData(dispatcher, this));
 
     if (was_empty)
     {
@@ -371,7 +373,7 @@ void DispatchNotifier::send_notification(Dispatcher::Impl* dispatcher_impl)
   }
 #else /* !G_OS_WIN32 */
 
-  DispatchNotifyData data(dispatcher_impl, this);
+  DispatchNotifyData data(dispatcher, this);
   gssize n_written;
 
   do
@@ -465,69 +467,75 @@ bool DispatchNotifier::pipe_io_handler(Glib::IOCondition)
 
   g_return_val_if_fail(data.notifier == this, true);
 
+  // Drop the received message, if it is addressed to a deleted dispatcher.
+  const bool drop_message =
+    (deleted_dispatchers_.find(data.dispatcher) != deleted_dispatchers_.end());
+
+  // If the pipe is empty, there can be no messages to deleted dispatchers.
+  // No reason to keep track of them any more.
+  if (!deleted_dispatchers_.empty() && pipe_is_empty())
+    deleted_dispatchers_.clear();
+
+  if (drop_message)
+  {
+    g_warning("Dropped dispatcher message as the dispatcher no longer exists");
+    return true;
+  }
+
   // Actually, we wouldn't need the try/catch block because the Glib::Source
   // C callback already does it for us.  However, we do it anyway because the
   // default return value is 'false', which is not what we want.
   try
   {
-    data.dispatcher_impl->signal_(); // emit
+    data.dispatcher->signal_(); // emit
   }
   catch (...)
   {
     Glib::exception_handlers_invoke();
   }
 
-  if (!orphaned_dispatcher_impl_.empty() && pipe_is_empty())
-    orphaned_dispatcher_impl_.clear();
-
   return true;
 }
 
-/**** Glib::Dispatcher and Glib::Dispatcher::Impl **************************/
+/**** Glib::Dispatcher *****************************************************/
 
-Dispatcher::Impl::Impl(const Glib::RefPtr<MainContext>& context)
-: signal_(),
-  notifier_(DispatchNotifier::reference_instance(context))
+Dispatcher::Dispatcher()
+: signal_(), notifier_(DispatchNotifier::reference_instance(MainContext::get_default(), this))
 {
 }
 
-Dispatcher::Dispatcher()
-: impl_(new Dispatcher::Impl(MainContext::get_default()))
-{}
-
-
 Dispatcher::Dispatcher(const Glib::RefPtr<MainContext>& context)
-: impl_(new Dispatcher::Impl(context))
+: signal_(), notifier_(DispatchNotifier::reference_instance(context, this))
 {
 }
 
 Dispatcher::~Dispatcher() noexcept
 {
-  DispatchNotifier::unreference_instance(impl_->notifier_, impl_);
+  DispatchNotifier::unreference_instance(notifier_, this);
 }
 
 void
 Dispatcher::emit()
 {
-  impl_->notifier_->send_notification(impl_);
+  notifier_->send_notification(this);
 }
 
 void
 Dispatcher::operator()()
 {
-  impl_->notifier_->send_notification(impl_);
+  notifier_->send_notification(this);
 }
 
 sigc::connection
-Dispatcher::connect(const sigc::slot<void()>& slot)
+Dispatcher::connect(const sigc::slot<void>& slot)
 {
-  return impl_->signal_.connect(slot);
+  return signal_.connect(slot);
 }
 
 sigc::connection
-Dispatcher::connect(sigc::slot<void()>&& slot)
+Dispatcher::connect(sigc::slot<void>&& slot)
 {
-  return impl_->signal_.connect(std::move(slot));
+  return signal_.connect(std::move(slot));
 }
 
 } // namespace Glib
index f66a523..e3b0d18 100644 (file)
 namespace Glib
 {
 
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+class DispatchNotifier;
+#endif
+
 /** Signal class for inter-thread communication.
  * @ingroup Threads
- * Glib::Dispatcher works similar to sigc::signal<void()>.  But unlike normal
+ * Glib::Dispatcher works similar to sigc::signal<void>.  But unlike normal
  * signals, the notification happens asynchronously through a pipe.  This is
  * a simple and efficient way of communicating between threads, and especially
  * useful in a thread model with a single GUI thread.
@@ -84,17 +88,18 @@ public:
   void emit();
   void operator()();
 
-  sigc::connection connect(const sigc::slot<void()>& slot);
+  sigc::connection connect(const sigc::slot<void>& slot);
   /** @newin{2,48}
    */
-  sigc::connection connect(sigc::slot<void()>&& slot);
-
-  #ifndef DOXYGEN_SHOULD_SKIP_THIS
-  struct Impl;
-  #endif
+  sigc::connection connect(sigc::slot<void>&& slot);
 
 private:
-  Impl* impl_; // hidden implementation
+  sigc::signal<void> signal_;
+  DispatchNotifier* notifier_;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  friend class Glib::DispatchNotifier;
+#endif
 };
 
 /*! A Glib::Dispatcher example.
index e80e009..95032a3 100644 (file)
@@ -19,6 +19,9 @@
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#ifndef GLIBMM_CAN_USE_THREAD_LOCAL
+#include <glibmm/threads.h>
+#endif
 #include <glibmmconfig.h>
 #include <glibmm/error.h>
 #include <glibmm/exceptionhandler.h>
@@ -33,7 +36,11 @@ using HandlerList = std::list<sigc::slot<void()>>;
 
 // Each thread has its own list of exception handlers
 // to avoid thread synchronization problems.
+#ifdef GLIBMM_CAN_USE_THREAD_LOCAL
 static thread_local HandlerList* thread_specific_handler_list = nullptr;
+#else
+static Glib::Threads::Private<HandlerList> thread_specific_handler_list;
+#endif
 
 static void
 glibmm_exception_warning(const GError* error)
@@ -83,14 +90,22 @@ namespace Glib
 {
 
 sigc::connection
-add_exception_handler(const sigc::slot<void()>& slot)
+add_exception_handler(const sigc::slot<void>& slot)
 {
+#ifdef GLIBMM_CAN_USE_THREAD_LOCAL
   HandlerList* handler_list = thread_specific_handler_list;
+#else
+  HandlerList* handler_list = thread_specific_handler_list.get();
+#endif
 
   if (!handler_list)
   {
     handler_list = new HandlerList();
+#ifdef GLIBMM_CAN_USE_THREAD_LOCAL
     thread_specific_handler_list = handler_list;
+#else
+    thread_specific_handler_list.set(handler_list);
+#endif
   }
 
   handler_list->emplace_back(slot);
@@ -115,7 +130,11 @@ exception_handlers_invoke() noexcept
   // handled.  If there are no more handlers in the list and the exception
   // is still unhandled, call glibmm_unexpected_exception().
 
+#ifdef GLIBMM_CAN_USE_THREAD_LOCAL
   if (HandlerList* const handler_list = thread_specific_handler_list)
+#else
+  if(HandlerList *const handler_list = thread_specific_handler_list.get())
+#endif
   {
     HandlerList::iterator pslot = handler_list->begin();
 
index acfd6f5..89c169b 100644 (file)
@@ -29,7 +29,7 @@ namespace Glib
 
 /** Specify a slot to be called when an exception is thrown by a signal handler.
  */
-sigc::connection add_exception_handler(const sigc::slot<void()>& slot);
+sigc::connection add_exception_handler(const sigc::slot<void>& slot);
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 // internal
diff --git a/glib/glibmm/extraclassinit.cc b/glib/glibmm/extraclassinit.cc
deleted file mode 100644 (file)
index 343fc6f..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (C) 2017 The glibmm 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/extraclassinit.h>
-
-namespace Glib
-{
-
-ExtraClassInit::ExtraClassInit(GClassInitFunc class_init_func, void* class_data,
-  GInstanceInitFunc instance_init_func)
-{
-  if (class_init_func)
-    add_custom_class_init_function(class_init_func, class_data);
-
-  if (instance_init_func)
-    set_custom_instance_init_function(instance_init_func);
-}
-
-} // namespace Glib
diff --git a/glib/glibmm/extraclassinit.h b/glib/glibmm/extraclassinit.h
deleted file mode 100644 (file)
index 9d2fc60..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#ifndef _GLIBMM_EXTRACLASSINIT_H
-#define _GLIBMM_EXTRACLASSINIT_H
-/* Copyright (C) 2017 The glibmm 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/objectbase.h>
-
-namespace Glib
-{
-
-/** A convenience class for named custom types.
- *
- * Use it if you need to add code to GType's class init function and/or
- * need an instance init function.
- * Example:
- * @code
- * #include <glibmm/extraclassinit.h>
- *
- * class MyExtraInit : public Glib::ExtraClassInit
- * {
- * public:
- *   MyExtraInit(const Glib::ustring& css_name)
- *   :
- *   Glib::ExtraClassInit(my_extra_class_init_function, &m_css_name, my_instance_init_function),
- *   m_css_name(css_name)
- *   { }
- *
- * private:
- *   static void my_extra_class_init_function(void* g_class, void* class_data)
- *   {
- *     const auto klass = static_cast<GtkWidgetClass*>(g_class);
- *     const auto css_name = static_cast<Glib::ustring*>(class_data);
- *     gtk_widget_class_set_css_name(klass, css_name->c_str());
- *   }
- *   static void my_instance_init_function(GTypeInstance* instance, void* g_class)
- *   {
- *     gtk_widget_set_has_window(GTK_WIDGET(instance), true);
- *   }
- *
- *   Glib::ustring m_css_name;
- * };
- *
- * class MyWidget : public Gtk::WidgetCustomDraw, public MyExtraInit, public Gtk::Widget
- * {
- * public:
- *   MyWidget()
- *   :
- *   // The GType name will be gtkmm__CustomObject_MyMidget
- *   Glib::ObjectBase("MyWidget"), // Unique class name
- *   Gtk::WidgetCustomDraw(),
- *   MyExtraInit("my-widget"),
- *   Gtk::Widget()
- *   {
- *     // ...
- *   }
- *   // ...
- * };
- * @endcode
- *
- * @note Classes derived from %ExtraClassInit (Gtk::WidgetCustomDraw and MyExtraInit
- * in the example) must be listed before Glib::Object or a class derived from
- * %Glib::Object (Gtk::Widget in the example) in the list of base classes.
- *
- * @newin{2,52}
- */
-class ExtraClassInit : virtual public ObjectBase
-{
-protected:
-  /** Constructor.
-   *
-   * @param class_init_func Pointer to an extra class init function.
-   *        nullptr, if no extra class init function is needed.
-   * @param class_data Class data pointer, passed to the class init function.
-   *        Can be nullptr, if the class init function does not need it.
-   * @param instance_init_func Pointer to an instance init function.
-   *        nullptr, if no instance init function is needed.
-   */
-  explicit ExtraClassInit(GClassInitFunc class_init_func, void* class_data = nullptr,
-    GInstanceInitFunc instance_init_func = nullptr);
-};
-
-} // namespace Glib
-
-#endif /* _GLIBMM_EXTRACLASSINIT_H */
index e04a0b7..dc6615f 100644 (file)
@@ -14,7 +14,6 @@ glibmm_files_extra_cc =                       \
        error.cc                        \
        exception.cc                    \
        exceptionhandler.cc             \
-       extraclassinit.cc               \
        init.cc                         \
        interface.cc                    \
        main.cc                         \
@@ -31,6 +30,7 @@ glibmm_files_extra_cc =                       \
        signalproxy_connectionnode.cc   \
        streamiochannel.cc              \
        stringutils.cc                  \
+       threadpool.cc                   \
        timer.cc                        \
        timeval.cc                      \
        ustring.cc                      \
@@ -51,7 +51,6 @@ glibmm_files_extra_h =                        \
        error.h                         \
        exception.h                     \
        exceptionhandler.h              \
-       extraclassinit.h                \
        helperlist.h                    \
        i18n-lib.h                      \
        i18n.h                          \
@@ -75,6 +74,7 @@ glibmm_files_extra_h =                        \
        slisthandle.h                   \
        streamiochannel.h               \
        stringutils.h                   \
+       threadpool.h                    \
        timer.h                         \
        timeval.h                       \
        ustring.h                       \
index f42cdf5..cc3b84c 100644 (file)
 
 #include <glibmm/init.h>
 #include <glibmm/error.h>
-#include <locale>
-#include <clocale>
-#include <stdexcept>
-
-namespace
-{
-  bool init_to_users_preferred_locale = true;
-
-} // anonymous namespace
 
 namespace Glib
 {
-void set_init_to_users_preferred_locale(bool state)
-{
-  init_to_users_preferred_locale = state;
-}
-
-bool get_init_to_users_preferred_locale()
-{
-  return init_to_users_preferred_locale;
-}
 
-void init()
+void
+init()
 {
-  static bool is_initialized = false;
-
-  if (is_initialized)
-    return;
-
-  if (init_to_users_preferred_locale)
-  {
-    try
-    {
-      // Set the global locale for C++ functions and the locale for C functions
-      // to the user-preferred locale.
-      std::locale::global(std::locale(""));
-    }
-    catch (const std::runtime_error& ex)
-    {
-      g_warning("Can't set the global locale to the user's preferred locale.\n"
-        "   %s\n   The environment variable LANG may be wrong.\n", ex.what());
-    }
-  }
-  else
-  {
-    try
-    {
-      // Make the C++ locale equal to the C locale.
-      std::locale::global(std::locale(std::setlocale(LC_ALL, nullptr)));
-    }
-    catch (const std::runtime_error& ex)
-    {
-      g_warning("Can't make the global C++ locale equal to the C locale.\n"
-        "   %s\n   C locale = %s\n", ex.what(), std::setlocale(LC_ALL, nullptr));
-    }
-  }
-
   // Also calls Glib::wrap_register_init() and Glib::wrap_init().
   Glib::Error::register_init();
-
-  is_initialized = true;
 }
 
 } // namespace Glib
index a736093..844945a 100644 (file)
@@ -1,6 +1,9 @@
+// -*- c++ -*-
 #ifndef _GLIBMM_INIT_H
 #define _GLIBMM_INIT_H
 
+/* $Id$ */
+
 /* Copyright (C) 2002 The gtkmm Development Team
  *
  * This library is free software; you can redistribute it and/or
@@ -22,50 +25,12 @@ namespace Glib
 {
 
 /** Initialize glibmm.
- *
- * You may call this more than once. Calls after the first one have no effect.
- * Sets the global locale as specified by set_init_to_users_preferred_locale().
- * You do not need to call %Glib::init() if you are using Gtk::Application,
- * because it calls %Glib::init() for you.
- *
- * @see set_init_to_users_preferred_locale()
+ * You may call this more than once.
+ * You do not need to call this if you are using Glib::MainLoop or Gtk::Main,
+ * because they call it for you.
  */
 void init();
 
-/** Instruct Glib::init() which global locale to set.
- *
- * To have the intended effect, this function must be called before init() is called.
- * Not calling it has the same effect as calling it with @a state = <tt>true</tt>.
- *
- * Note the confusing difference between C locale and "C" locale.
- * The C locale is the locale used by C code, set by std::setlocale(LC_ALL,&nbsp;locale_name).
- * The "C" locale is the classic locale, set by std::setlocale(LC_ALL,&nbsp;"C")
- * or std::locale::global(std::locale::classic()). It's the default global locale
- * in a C or C++ program.
- *
- * In a mixed C and C++ program, like a program using glibmm, having the C global
- * locale differ from std::locale::global() is error prone. Glib::init() tries
- * to avoid that.
- *
- * @param state If <tt>true</tt>, init() will set the C and C++ global locale
- *              to the user's preferred locale (std::locale::global(std::locale(""))).
- *              The user's preferred locale is set in the program's environment,
- *              usually with the LANG environment variable.<br>
- *              If <tt>false</tt>, init() will set the C++ global locale to the C global locale
- *              (std::locale::global(std::locale(std::setlocale(LC_ALL,&nbsp;nullptr)))).
- *
- * @newin{2,52}
- */
-void set_init_to_users_preferred_locale(bool state = true);
-
-/** Get the state, set with set_init_to_users_preferred_locale().
- * @returns The state, set with set_init_to_users_preferred_locale(); <tt>true</tt>
- *          if set_init_to_users_preferred_locale() has not been called.
- *
- * @newin{2,52}
- */
-bool get_init_to_users_preferred_locale();
-
 } // namespace Glib
 
 #endif /* _GLIBMM_INIT_H */
index 31a5278..0ce998b 100644 (file)
@@ -96,9 +96,10 @@ Interface::Interface(const Interface_Class& interface_class)
     }
     else // gobject_ == nullptr
     {
-      // The GObject is not instantiated yet. Add to the stored custom interface
-      // classes, and add the interface to the GType in the Glib::Object constructor.
-      add_custom_interface_class(&interface_class);
+      // The GObject is not instantiated yet. Add to the custom_interface_classes
+      // and add the interface in the Glib::Object constructor.
+      std::lock_guard<std::mutex> lock(extra_object_base_data_mutex);
+      extra_object_base_data[this].custom_interface_classes.emplace_back(&interface_class);
     }
   }
 }
index 1f19f46..93ba40e 100644 (file)
 
 #include <glibmmconfig.h> // May define GLIBMM_DISABLE_DEPRECATED
 
+#ifndef GLIBMM_DISABLE_DEPRECATED
+// Include glibmm/thread.h first because we need it to be first to include <glib.h>,
+// so we can do an undef trick to still use deprecated API in the header:
+#include <glibmm/thread.h>
+#include <glibmm/threads.h>
+#endif // GLIBMM_DISABLE_DEPRECATED
+
 #include <glibmm/main.h>
 #include <glibmm/exceptionhandler.h>
 #include <glibmm/wrap.h>
 #include <glibmm/iochannel.h>
 #include <algorithm>
+#include <map> // Needed until the next ABI break.
 
 namespace
 {
+#ifdef GLIBMM_DISABLE_DEPRECATED
 void
 time64_to_time_val(gint64 time64, Glib::TimeVal& time_val)
 {
@@ -34,14 +43,34 @@ time64_to_time_val(gint64 time64, Glib::TimeVal& time_val)
     static_cast<long>(time64 - static_cast<gint64>(seconds) * G_GINT64_CONSTANT(1000000));
   time_val = Glib::TimeVal(seconds, microseconds);
 }
+#endif // GLIBMM_DISABLE_DEPRECATED
+
+// TODO: At the next ABI break, replace ExtraSourceData by new data members in Source.
+// Then the mutex is not necessary, but to keep the code thread-safe, use the
+// g_atomic_*() functions on these data elements.
+// These are new data members that can't be added to Glib::Source now,
+// because it would break ABI.
+struct ExtraSourceData
+{
+  ExtraSourceData() : ref_count(1), keep_wrapper(2) {}
+  int ref_count;
+  // When both Source::unreference() and SourceCallbackData::destroy_notify_callback()
+  // have decreased keep_wrapper, it's time to delete the C++ wrapper.
+  int keep_wrapper;
+};
+
+std::map<const Glib::Source*, ExtraSourceData> extra_source_data;
+// Source instances may be used in different threads.
+// Accesses to extra_source_data must be thread-safe.
+std::mutex extra_source_data_mutex;
 
-class SourceConnectionNode : public sigc::notifiable
+class SourceConnectionNode
 {
 public:
   explicit inline SourceConnectionNode(const sigc::slot_base& slot);
 
-  static void notify(sigc::notifiable* data);
-  static void destroy_notify_callback(sigc::notifiable* data);
+  static void* notify(void* data);
+  static void destroy_notify_callback(void* data);
 
   inline void install(GSource* source);
   inline sigc::slot_base* get_slot();
@@ -57,8 +86,8 @@ inline SourceConnectionNode::SourceConnectionNode(const sigc::slot_base& slot)
   slot_.set_parent(this, &SourceConnectionNode::notify);
 }
 
-void
-SourceConnectionNode::notify(sigc::notifiable* data)
+void*
+SourceConnectionNode::notify(void* data)
 {
   SourceConnectionNode* const self = static_cast<SourceConnectionNode*>(data);
 
@@ -73,11 +102,13 @@ SourceConnectionNode::notify(sigc::notifiable* data)
     // Destroying the object triggers execution of destroy_notify_handler(),
     // either immediately or later, so we leave that to do the deletion.
   }
+
+  return nullptr;
 }
 
 // static
 void
-SourceConnectionNode::destroy_notify_callback(sigc::notifiable* data)
+SourceConnectionNode::destroy_notify_callback(void* data)
 {
   SourceConnectionNode* const self = static_cast<SourceConnectionNode*>(data);
 
@@ -143,8 +174,17 @@ SourceCallbackData::destroy_notify_callback(void* data)
   if (self->node)
     SourceConnectionNode::destroy_notify_callback(self->node);
 
-  // destroy_notify_callback2() does nothing if self->wrapper == nullptr.
-  Glib::Source::destroy_notify_callback2(self->wrapper);
+  if (self->wrapper)
+  {
+    std::unique_lock<std::mutex> lock(extra_source_data_mutex);
+    if (--extra_source_data[self->wrapper].keep_wrapper == 0)
+    {
+      // No other reference exists to the wrapper. Delete it!
+      extra_source_data.erase(self->wrapper);
+      lock.unlock();
+      Glib::Source::destroy_notify_callback(self->wrapper);
+    }
+  }
 
   delete self;
 }
@@ -192,7 +232,7 @@ glibmm_source_callback(void* data)
   try
   {
     // Recreate the specific slot from the generic slot node.
-    return (*static_cast<sigc::slot<bool()>*>(conn_data->get_slot()))();
+    return (*static_cast<sigc::slot<bool>*>(conn_data->get_slot()))();
   }
   catch (...)
   {
@@ -213,7 +253,7 @@ glibmm_source_callback_once(void* data)
   try
   {
     // Recreate the specific slot from the generic slot node.
-    (*static_cast<sigc::slot<void()>*>(conn_data->get_slot()))();
+    (*static_cast<sigc::slot<void>*>(conn_data->get_slot()))();
   }
   catch (...)
   {
@@ -222,13 +262,6 @@ glibmm_source_callback_once(void* data)
   return 0; // Destroy the event source after one call
 }
 
-static void
-glibmm_source_destroy_notify_callback(void* data)
-{
-  SourceConnectionNode* const conn_data = static_cast<SourceConnectionNode*>(data);
-  SourceConnectionNode::destroy_notify_callback(conn_data);
-}
-
 static gboolean
 glibmm_iosource_callback(GIOChannel*, GIOCondition condition, void* data)
 {
@@ -238,7 +271,7 @@ glibmm_iosource_callback(GIOChannel*, GIOCondition condition, void* data)
   try
   {
     // Recreate the specific slot from the generic slot node.
-    return (*static_cast<sigc::slot<bool(Glib::IOCondition)>*>(callback_data->node->get_slot()))(
+    return (*static_cast<sigc::slot<bool, Glib::IOCondition>*>(callback_data->node->get_slot()))(
       (Glib::IOCondition)condition);
   }
   catch (...)
@@ -260,7 +293,7 @@ glibmm_child_watch_callback(GPid pid, gint child_status, void* data)
   try
   {
     // Recreate the specific slot from the generic slot node.
-    (*static_cast<sigc::slot<void(GPid, int)>*>(conn_data->get_slot()))(pid, child_status);
+    (*static_cast<sigc::slot<void, GPid, int>*>(conn_data->get_slot()))(pid, child_status);
   }
   catch (...)
   {
@@ -271,7 +304,7 @@ glibmm_child_watch_callback(GPid pid, gint child_status, void* data)
 
 static void
 glibmm_signal_connect_once(
-  const sigc::slot<void()>& slot, int priority, GSource* source, GMainContext* context)
+  const sigc::slot<void>& slot, int priority, GSource* source, GMainContext* context)
 {
   SourceConnectionNode* const conn_node = new SourceConnectionNode(slot);
 
@@ -279,7 +312,7 @@ glibmm_signal_connect_once(
     g_source_set_priority(source, priority);
 
   g_source_set_callback(source, &glibmm_source_callback_once, conn_node,
-    &glibmm_source_destroy_notify_callback);
+    &SourceConnectionNode::destroy_notify_callback);
 
   conn_node->install(source);
   g_source_attach(source, context);
@@ -294,7 +327,7 @@ glibmm_main_context_invoke_callback(void* data)
   try
   {
     // Recreate the specific slot from the generic slot node.
-    return (*static_cast<sigc::slot<bool()>*>(slot))();
+    return (*static_cast<sigc::slot<bool>*>(slot))();
   }
   catch (...)
   {
@@ -346,7 +379,7 @@ inline SignalTimeout::SignalTimeout(GMainContext* context) : context_(context)
 
 /* Note that this is our equivalent of g_timeout_add(). */
 sigc::connection
-SignalTimeout::connect(const sigc::slot<bool()>& slot, unsigned int interval, int priority)
+SignalTimeout::connect(const sigc::slot<bool>& slot, unsigned int interval, int priority)
 {
   SourceConnectionNode* const conn_node = new SourceConnectionNode(slot);
   const sigc::connection connection(*conn_node->get_slot());
@@ -357,8 +390,7 @@ SignalTimeout::connect(const sigc::slot<bool()>& slot, unsigned int interval, in
     g_source_set_priority(source, priority);
 
   g_source_set_callback(
-    source, &glibmm_source_callback, conn_node,
-    &glibmm_source_destroy_notify_callback);
+    source, &glibmm_source_callback, conn_node, &SourceConnectionNode::destroy_notify_callback);
 
   conn_node->install(source);
   g_source_attach(source, context_);
@@ -368,7 +400,7 @@ SignalTimeout::connect(const sigc::slot<bool()>& slot, unsigned int interval, in
 }
 
 void
-SignalTimeout::connect_once(const sigc::slot<void()>& slot, unsigned int interval, int priority)
+SignalTimeout::connect_once(const sigc::slot<void>& slot, unsigned int interval, int priority)
 {
   GSource* const source = g_timeout_source_new(interval);
   glibmm_signal_connect_once(slot, priority, source, context_);
@@ -376,7 +408,7 @@ SignalTimeout::connect_once(const sigc::slot<void()>& slot, unsigned int interva
 
 /* Note that this is our equivalent of g_timeout_add_seconds(). */
 sigc::connection
-SignalTimeout::connect_seconds(const sigc::slot<bool()>& slot, unsigned int interval, int priority)
+SignalTimeout::connect_seconds(const sigc::slot<bool>& slot, unsigned int interval, int priority)
 {
   SourceConnectionNode* const conn_node = new SourceConnectionNode(slot);
   const sigc::connection connection(*conn_node->get_slot());
@@ -387,8 +419,7 @@ SignalTimeout::connect_seconds(const sigc::slot<bool()>& slot, unsigned int inte
     g_source_set_priority(source, priority);
 
   g_source_set_callback(
-    source, &glibmm_source_callback, conn_node,
-    &glibmm_source_destroy_notify_callback);
+    source, &glibmm_source_callback, conn_node, &SourceConnectionNode::destroy_notify_callback);
 
   conn_node->install(source);
   g_source_attach(source, context_);
@@ -399,7 +430,7 @@ SignalTimeout::connect_seconds(const sigc::slot<bool()>& slot, unsigned int inte
 
 void
 SignalTimeout::connect_seconds_once(
-  const sigc::slot<void()>& slot, unsigned int interval, int priority)
+  const sigc::slot<void>& slot, unsigned int interval, int priority)
 {
   GSource* const source = g_timeout_source_new_seconds(interval);
   glibmm_signal_connect_once(slot, priority, source, context_);
@@ -418,7 +449,7 @@ inline SignalIdle::SignalIdle(GMainContext* context) : context_(context)
 }
 
 sigc::connection
-SignalIdle::connect(const sigc::slot<bool()>& slot, int priority)
+SignalIdle::connect(const sigc::slot<bool>& slot, int priority)
 {
   SourceConnectionNode* const conn_node = new SourceConnectionNode(slot);
   const sigc::connection connection(*conn_node->get_slot());
@@ -429,8 +460,7 @@ SignalIdle::connect(const sigc::slot<bool()>& slot, int priority)
     g_source_set_priority(source, priority);
 
   g_source_set_callback(
-    source, &glibmm_source_callback, conn_node,
-    &glibmm_source_destroy_notify_callback);
+    source, &glibmm_source_callback, conn_node, &SourceConnectionNode::destroy_notify_callback);
 
   conn_node->install(source);
   g_source_attach(source, context_);
@@ -440,7 +470,7 @@ SignalIdle::connect(const sigc::slot<bool()>& slot, int priority)
 }
 
 void
-SignalIdle::connect_once(const sigc::slot<void()>& slot, int priority)
+SignalIdle::connect_once(const sigc::slot<void>& slot, int priority)
 {
   GSource* const source = g_idle_source_new();
   glibmm_signal_connect_once(slot, priority, source, context_);
@@ -460,7 +490,7 @@ inline SignalIO::SignalIO(GMainContext* context) : context_(context)
 
 sigc::connection
 SignalIO::connect(
-  const sigc::slot<bool(IOCondition)>& slot, PollFD::fd_t fd, IOCondition condition, int priority)
+  const sigc::slot<bool, IOCondition>& slot, PollFD::fd_t fd, IOCondition condition, int priority)
 {
   const auto source = IOSource::create(fd, condition);
 
@@ -475,7 +505,7 @@ SignalIO::connect(
 }
 
 sigc::connection
-SignalIO::connect(const sigc::slot<bool(IOCondition)>& slot, const Glib::RefPtr<IOChannel>& channel,
+SignalIO::connect(const sigc::slot<bool, IOCondition>& slot, const Glib::RefPtr<IOChannel>& channel,
   IOCondition condition, int priority)
 {
   const auto source = IOSource::create(channel, condition);
@@ -503,7 +533,7 @@ inline SignalChildWatch::SignalChildWatch(GMainContext* context) : context_(cont
 }
 
 sigc::connection
-SignalChildWatch::connect(const sigc::slot<void(GPid, int)>& slot, GPid pid, int priority)
+SignalChildWatch::connect(const sigc::slot<void, GPid, int>& slot, GPid pid, int priority)
 {
   SourceConnectionNode* const conn_node = new SourceConnectionNode(slot);
   const sigc::connection connection(*conn_node->get_slot());
@@ -513,9 +543,8 @@ SignalChildWatch::connect(const sigc::slot<void(GPid, int)>& slot, GPid pid, int
   if (priority != G_PRIORITY_DEFAULT)
     g_source_set_priority(source, priority);
 
-  g_source_set_callback(source, (GSourceFunc)&glibmm_child_watch_callback,
-    conn_node,
-    &glibmm_source_destroy_notify_callback);
+  g_source_set_callback(source, (GSourceFunc)&glibmm_child_watch_callback, conn_node,
+    &SourceConnectionNode::destroy_notify_callback);
 
   conn_node->install(source);
   g_source_attach(source, context_);
@@ -570,6 +599,20 @@ MainContext::acquire()
   return g_main_context_acquire(gobj());
 }
 
+#ifndef GLIBMM_DISABLE_DEPRECATED
+bool
+MainContext::wait(Glib::Cond& cond, Glib::Mutex& mutex)
+{
+  return g_main_context_wait(gobj(), cond.gobj(), mutex.gobj());
+}
+
+bool
+MainContext::wait(Glib::Threads::Cond& cond, Glib::Threads::Mutex& mutex)
+{
+  return g_main_context_wait(gobj(), cond.gobj(), mutex.gobj());
+}
+#endif // GLIBMM_DISABLE_DEPRECATED
+
 void
 MainContext::release()
 {
@@ -648,10 +691,10 @@ MainContext::remove_poll(PollFD& fd)
 }
 
 void
-MainContext::invoke(const sigc::slot<bool()>& slot, int priority)
+MainContext::invoke(const sigc::slot<bool>& slot, int priority)
 {
   // Make a copy of slot on the heap.
-  sigc::slot_base* const slot_copy = new sigc::slot<bool()>(slot);
+  sigc::slot_base* const slot_copy = new sigc::slot<bool>(slot);
 
   g_main_context_invoke_full(gobj(), priority, glibmm_main_context_invoke_callback, slot_copy,
     glibmm_main_context_invoke_destroy_notify_callback);
@@ -883,17 +926,30 @@ Source::gobj_copy() const
 void
 Source::reference() const
 {
-  ++ref_count_;
+  std::lock_guard<std::mutex> lock(extra_source_data_mutex);
+  ++extra_source_data[this].ref_count;
 }
 
 void
 Source::unreference() const
 {
-  if (--ref_count_ == 0)
+  std::unique_lock<std::mutex> lock(extra_source_data_mutex);
+  if (--extra_source_data[this].ref_count == 0)
   {
     GSource* const tmp_gobject = gobject_;
 
-    destroy_notify_callback2(const_cast<Source*>(this));
+    if (--extra_source_data[this].keep_wrapper == 0)
+    {
+      // The last reference from a RefPtr<Source> has been deleted, and
+      // SourceCallbackData::destroy_notify_callback() has been called while
+      // extra_source_data[this].keep_wrapper was > 1.
+      // Delete the wrapper!
+      extra_source_data.erase(this);
+      lock.unlock();
+      destroy_notify_callback(const_cast<Source*>(this));
+    }
+    else
+      lock.unlock();
 
     // Drop the one and only GSource reference held by the C++ wrapper.
     // If the GSource instance is attached to a main context, the GMainContext
@@ -963,6 +1019,16 @@ Source::remove_poll(Glib::PollFD& poll_fd)
   g_source_remove_poll(gobject_, poll_fd.gobj());
 }
 
+#ifndef GLIBMM_DISABLE_DEPRECATED
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+void
+Source::get_current_time(Glib::TimeVal& current_time)
+{
+  g_source_get_current_time(gobject_, &current_time);
+}
+G_GNUC_END_IGNORE_DEPRECATIONS
+#endif // GLIBMM_DISABLE_DEPRECATED
+
 gint64
 Source::get_time() const
 {
@@ -1034,19 +1100,17 @@ Source::dispatch_vfunc(GSource*, GSourceFunc callback, void* user_data)
 
 // static
 void
-Source::destroy_notify_callback2(void* data)
+Source::destroy_notify_callback(void* data)
 {
   if (data)
   {
     Source* const self = static_cast<Source*>(data);
-    if (--self->keep_wrapper_ == 0)
-    {
-      // gobject_ is already invalid at this point.
-      self->gobject_ = nullptr;
 
-      // No exception checking: if the dtor throws, you're out of luck anyway.
-      delete self;
-    }
+    // gobject_ is already invalid at this point.
+    self->gobject_ = nullptr;
+
+    // No exception checking: if the dtor throws, you're out of luck anyway.
+    delete self;
   }
 }
 
@@ -1062,8 +1126,7 @@ Source::attach_signal_source(const sigc::slot_base& slot, int priority, GSource*
     g_source_set_priority(source, priority);
 
   g_source_set_callback(
-    source, callback_func, conn_node,
-    &glibmm_source_destroy_notify_callback);
+    source, callback_func, conn_node, &SourceConnectionNode::destroy_notify_callback);
 
   conn_node->install(source);
   g_source_attach(source, context);
@@ -1098,7 +1161,7 @@ TimeoutSource::create(unsigned int interval)
 }
 
 sigc::connection
-TimeoutSource::connect(const sigc::slot<bool()>& slot)
+TimeoutSource::connect(const sigc::slot<bool>& slot)
 {
   return connect_generic(slot);
 }
@@ -1117,7 +1180,11 @@ bool
 TimeoutSource::prepare(int& timeout)
 {
   Glib::TimeVal current_time;
+#ifndef GLIBMM_DISABLE_DEPRECATED
+  get_current_time(current_time);
+#else
   time64_to_time_val(get_time(), current_time);
+#endif // GLIBMM_DISABLE_DEPRECATED
 
   Glib::TimeVal remaining = expiration_;
   remaining.subtract(current_time);
@@ -1154,7 +1221,11 @@ bool
 TimeoutSource::check()
 {
   Glib::TimeVal current_time;
+#ifndef GLIBMM_DISABLE_DEPRECATED
+  get_current_time(current_time);
+#else
   time64_to_time_val(get_time(), current_time);
+#endif // GLIBMM_DISABLE_DEPRECATED
 
   return (expiration_ <= current_time);
 }
@@ -1162,11 +1233,15 @@ TimeoutSource::check()
 bool
 TimeoutSource::dispatch(sigc::slot_base* slot)
 {
-  const bool again = (*static_cast<sigc::slot<bool()>*>(slot))();
+  const bool again = (*static_cast<sigc::slot<bool>*>(slot))();
 
   if (again)
   {
+#ifndef GLIBMM_DISABLE_DEPRECATED
+    get_current_time(expiration_);
+#else
     time64_to_time_val(get_time(), expiration_);
+#endif // GLIBMM_DISABLE_DEPRECATED
     expiration_.add_milliseconds(std::min<unsigned long>(G_MAXLONG, interval_));
   }
 
@@ -1183,7 +1258,7 @@ IdleSource::create()
 }
 
 sigc::connection
-IdleSource::connect(const sigc::slot<bool()>& slot)
+IdleSource::connect(const sigc::slot<bool>& slot)
 {
   return connect_generic(slot);
 }
@@ -1213,7 +1288,7 @@ IdleSource::check()
 bool
 IdleSource::dispatch(sigc::slot_base* slot)
 {
-  return (*static_cast<sigc::slot<bool()>*>(slot))();
+  return (*static_cast<sigc::slot<bool>*>(slot))();
 }
 
 /**** Glib::IOSource *******************************************************/
@@ -1232,7 +1307,7 @@ IOSource::create(const Glib::RefPtr<IOChannel>& channel, IOCondition condition)
 }
 
 sigc::connection
-IOSource::connect(const sigc::slot<bool(IOCondition)>& slot)
+IOSource::connect(const sigc::slot<bool, IOCondition>& slot)
 {
   return connect_generic(slot);
 }
@@ -1272,7 +1347,7 @@ IOSource::check()
 bool
 IOSource::dispatch(sigc::slot_base* slot)
 {
-  return (*static_cast<sigc::slot<bool(IOCondition)>*>(slot))(poll_fd_.get_revents());
+  return (*static_cast<sigc::slot<bool, IOCondition>*>(slot))(poll_fd_.get_revents());
 }
 
 } // namespace Glib
index 63b1ef1..c6dc839 100644 (file)
 #include <sigc++/sigc++.h>
 #include <vector>
 #include <cstddef>
-#include <atomic>
 
 namespace Glib
 {
 
+#ifndef GLIBMM_DISABLE_DEPRECATED
+class Cond;
+class Mutex;
+
+namespace Threads
+{
+class Cond;
+class Mutex;
+}
+#endif // GLIBMM_DISABLE_DEPRECATED
+
 /** @defgroup MainLoop The Main Event Loop
  * Manages all available sources of events.
  * @{
@@ -61,6 +71,16 @@ private:
   GPollFD gobject_;
 };
 
+// Concerning SignalTimeout::connect_once(), SignalTimeout::connect_seconds_once()
+// and SignalIdle::connect_once():
+// See https://bugzilla.gnome.org/show_bug.cgi?id=396963 and
+// http://bugzilla.gnome.org/show_bug.cgi?id=512348 about the sigc::trackable issue.
+// It's recommended to replace sigc::slot<void>& by std::function<void()>& in
+// Threads::Thread::create() and ThreadPool::push() at the next ABI break.
+// Such a replacement would be a mixed blessing in SignalTimeout and SignalIdle.
+// In a single-threaded program auto-disconnection of trackable slots is safe
+// and can be useful.
+
 class SignalTimeout
 {
 public:
@@ -104,7 +124,7 @@ public:
    * @return A connection handle, which can be used to disconnect the handler.
    */
   sigc::connection connect(
-    const sigc::slot<bool()>& slot, unsigned int interval, int priority = PRIORITY_DEFAULT);
+    const sigc::slot<bool>& slot, unsigned int interval, int priority = PRIORITY_DEFAULT);
 
   /** Connects a timeout handler that runs only once.
    * This method takes a function pointer to a function with a void return
@@ -126,7 +146,7 @@ public:
    * @param priority The priority of the new event source.
    */
   void connect_once(
-    const sigc::slot<void()>& slot, unsigned int interval, int priority = PRIORITY_DEFAULT);
+    const sigc::slot<void>& slot, unsigned int interval, int priority = PRIORITY_DEFAULT);
 
   /** Connects a timeout handler with whole second granularity.
    *
@@ -164,7 +184,7 @@ public:
    * @newin{2,14}
    */
   sigc::connection connect_seconds(
-    const sigc::slot<bool()>& slot, unsigned int interval, int priority = PRIORITY_DEFAULT);
+    const sigc::slot<bool>& slot, unsigned int interval, int priority = PRIORITY_DEFAULT);
 
   /** Connects a timeout handler that runs only once with whole second
    *  granularity.
@@ -188,7 +208,7 @@ public:
    * @param priority The priority of the new event source.
    */
   void connect_seconds_once(
-    const sigc::slot<void()>& slot, unsigned int interval, int priority = PRIORITY_DEFAULT);
+    const sigc::slot<void>& slot, unsigned int interval, int priority = PRIORITY_DEFAULT);
 
 private:
   GMainContext* context_;
@@ -226,7 +246,7 @@ public:
    * @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()>& slot, int priority = PRIORITY_DEFAULT_IDLE);
+  sigc::connection connect(const sigc::slot<bool>& slot, int priority = PRIORITY_DEFAULT_IDLE);
 
   /** Connects an idle handler that runs only once.
    * This method takes a function pointer to a function with a void return
@@ -246,7 +266,7 @@ public:
    * @endcode
    * @param priority The priority of the new event source.
    */
-  void connect_once(const sigc::slot<void()>& slot, int priority = PRIORITY_DEFAULT_IDLE);
+  void connect_once(const sigc::slot<void>& slot, int priority = PRIORITY_DEFAULT_IDLE);
 
 private:
   GMainContext* context_;
@@ -287,7 +307,7 @@ public:
    * @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(IOCondition)>& slot, PollFD::fd_t fd, IOCondition condition,
+  sigc::connection connect(const sigc::slot<bool, IOCondition>& slot, PollFD::fd_t fd, IOCondition condition,
     int priority = PRIORITY_DEFAULT);
 
   /** Connects an I/O handler that watches an I/O channel.
@@ -316,7 +336,7 @@ public:
    * @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(IOCondition)>& slot,
+  sigc::connection connect(const sigc::slot<bool, IOCondition>& slot,
     const Glib::RefPtr<IOChannel>& channel, IOCondition condition, int priority = PRIORITY_DEFAULT);
 
 private:
@@ -348,7 +368,7 @@ public:
    * @return A connection handle, which can be used to disconnect the handler.
    */
   sigc::connection connect(
-    const sigc::slot<void(GPid, int)>& slot, GPid pid, int priority = PRIORITY_DEFAULT);
+    const sigc::slot<void, GPid, int>& slot, GPid pid, int priority = PRIORITY_DEFAULT);
 
 private:
   GMainContext* context_;
@@ -435,6 +455,36 @@ public:
    */
   bool acquire();
 
+#ifndef GLIBMM_DISABLE_DEPRECATED
+  /** Tries to become the owner of the specified context, as with acquire(). But if another thread
+   * is the owner,
+   * atomically drop mutex and wait on cond until that owner releases ownership or until cond is
+   * signaled, then try
+   * again (once) to become the owner.
+   * @param cond A condition variable.
+   * @param mutex A mutex, currently held.
+   * @return true if the operation succeeded, and this thread is now the owner of context.
+   *
+   * @deprecated Use wait(Glib::Threads::Cond& cond, Glib::Threads::Mutex& mutex) instead.
+   */
+  bool wait(Glib::Cond& cond, Glib::Mutex& mutex);
+
+  // Deprecated mostly because it uses deprecated Glib::Threads:: for parameters.
+  /** Tries to become the owner of the specified context, as with acquire(). But if another thread
+   * is the owner,
+   * atomically drop mutex and wait on cond until that owner releases ownership or until cond is
+   * signaled, then try
+   * again (once) to become the owner.
+   * @param cond A condition variable.
+   * @param mutex A mutex, currently held.
+   * @return true if the operation succeeded, and this thread is now the owner of context.
+   *
+   * @deprecated Please use the underlying g_main_context_wait() function if you really need this
+   * functionality.
+   */
+  bool wait(Glib::Threads::Cond& cond, Glib::Threads::Mutex& mutex);
+#endif // GLIBMM_DISABLE_DEPRECATED
+
   /** Releases ownership of a context previously acquired by this thread with acquire(). If the
    * context was acquired
    * multiple times, the only release ownership when release() is called as many times as it was
@@ -535,7 +585,7 @@ public:
    *
    * @newin{2,38}
    */
-  void invoke(const sigc::slot<bool()>& slot, int priority = PRIORITY_DEFAULT);
+  void invoke(const sigc::slot<bool>& slot, int priority = PRIORITY_DEFAULT);
 
   /** Timeout signal, attached to this MainContext.
    * @return A signal proxy; you want to use SignalTimeout::connect().
@@ -773,13 +823,6 @@ protected:
 private:
   GSource* gobject_;
 
-  mutable std::atomic_int ref_count_ {1};
-  // The C++ wrapper (the Source instance) is deleted, when both Source::unreference()
-  // and SourceCallbackData::destroy_notify_callback() have decreased keep_wrapper_
-  // by calling destroy_notify_callback2().
-  // https://bugzilla.gnome.org/show_bug.cgi?id=561885
-  std::atomic_int keep_wrapper_ {2};
-
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
   static inline Source* get_wrapper(GSource* source);
 
@@ -790,8 +833,7 @@ private:
   static gboolean dispatch_vfunc(GSource* source, GSourceFunc callback, void* user_data);
 
 public:
-  // Really destroys the object during the second call. See keep_wrapper_.
-  static void destroy_notify_callback2(void* data);
+  static void destroy_notify_callback(void* data);
   // 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);
@@ -808,7 +850,7 @@ public:
   using CppObjectType = Glib::TimeoutSource;
 
   static Glib::RefPtr<TimeoutSource> create(unsigned int interval);
-  sigc::connection connect(const sigc::slot<bool()>& slot);
+  sigc::connection connect(const sigc::slot<bool>& slot);
 
 protected:
   explicit TimeoutSource(unsigned int interval);
@@ -831,7 +873,7 @@ public:
   using CppObjectType = Glib::IdleSource;
 
   static Glib::RefPtr<IdleSource> create();
-  sigc::connection connect(const sigc::slot<bool()>& slot);
+  sigc::connection connect(const sigc::slot<bool>& slot);
 
 protected:
   IdleSource();
@@ -850,7 +892,7 @@ public:
   static Glib::RefPtr<IOSource> create(PollFD::fd_t fd, IOCondition condition);
   static Glib::RefPtr<IOSource> create(
     const Glib::RefPtr<IOChannel>& channel, IOCondition condition);
-  sigc::connection connect(const sigc::slot<bool(IOCondition)>& slot);
+  sigc::connection connect(const sigc::slot<bool, IOCondition>& slot);
 
 protected:
   IOSource(PollFD::fd_t fd, IOCondition condition);
index 4dd8d4e..e7f6f88 100644 (file)
@@ -194,13 +194,21 @@ Object::Object()
 
   if (custom_type_name_ && !is_anonymous_custom_())
   {
-    object_class_.init();
+    Class::interface_class_vector_type custom_interface_classes;
 
+    {
+      std::lock_guard<std::mutex> lock(extra_object_base_data_mutex);
+      const extra_object_base_data_type::iterator iter = extra_object_base_data.find(this);
+      if (iter != extra_object_base_data.end())
+      {
+        custom_interface_classes = iter->second.custom_interface_classes;
+        extra_object_base_data.erase(iter);
+      }
+    }
+
+    object_class_.init();
     // This creates a type that is derived (indirectly) from GObject.
-    object_type = object_class_.clone_custom_type(custom_type_name_,
-      get_custom_interface_classes(), get_custom_class_init_functions(),
-      get_custom_instance_init_function());
-    custom_class_init_finished();
+    object_type = object_class_.clone_custom_type(custom_type_name_, custom_interface_classes);
   }
 
   void* const new_object = g_object_newv(object_type, 0, nullptr);
@@ -219,11 +227,20 @@ Object::Object(const Glib::ConstructParams& construct_params)
 
   if (custom_type_name_ && !is_anonymous_custom_())
   {
+    Class::interface_class_vector_type custom_interface_classes;
+
+    {
+      std::lock_guard<std::mutex> lock(extra_object_base_data_mutex);
+      const extra_object_base_data_type::iterator iter = extra_object_base_data.find(this);
+      if (iter != extra_object_base_data.end())
+      {
+        custom_interface_classes = iter->second.custom_interface_classes;
+        extra_object_base_data.erase(iter);
+      }
+    }
+
     object_type =
-      construct_params.glibmm_class.clone_custom_type(custom_type_name_,
-      get_custom_interface_classes(), get_custom_class_init_functions(),
-      get_custom_instance_init_function());
-    custom_class_init_finished();
+      construct_params.glibmm_class.clone_custom_type(custom_type_name_, custom_interface_classes);
   }
 
   // Create a new GObject with the specified array of construct properties.
index 7e36414..c524a16 100644 (file)
@@ -40,16 +40,9 @@ namespace Glib
 
 /**** Glib::ObjectBase *****************************************************/
 
-// Used only during the construction of named custom types.
-struct ObjectBase::PrivImpl
-{
-  // Pointers to the interfaces of custom types.
-  Class::interface_classes_type custom_interface_classes;
-  // Pointers to extra class init functions.
-  Class::class_init_funcs_type custom_class_init_functions;
-  // Pointer to the instance init function.
-  GInstanceInitFunc custom_instance_init_function = nullptr;
-};
+// static data members
+ObjectBase::extra_object_base_data_type ObjectBase::extra_object_base_data;
+std::mutex ObjectBase::extra_object_base_data_mutex;
 
 ObjectBase::ObjectBase()
 : gobject_(nullptr),
@@ -59,14 +52,12 @@ ObjectBase::ObjectBase()
 }
 
 ObjectBase::ObjectBase(const char* custom_type_name)
-: gobject_(nullptr), custom_type_name_(custom_type_name),
-  cpp_destruction_in_progress_(false)
+: gobject_(nullptr), custom_type_name_(custom_type_name), cpp_destruction_in_progress_(false)
 {
 }
 
 ObjectBase::ObjectBase(const std::type_info& custom_type_info)
-: gobject_(nullptr), custom_type_name_(custom_type_info.name()),
-  cpp_destruction_in_progress_(false)
+: gobject_(nullptr), custom_type_name_(custom_type_info.name()), cpp_destruction_in_progress_(false)
 {
 }
 
@@ -163,6 +154,14 @@ ObjectBase::~ObjectBase() noexcept
   // we have to call g_object_unref() on our own.
   //
 
+  // Just a precaution. Unless a derived class's ctor has thrown an exception,
+  // 'this' should have been erased from extra_object_base_data by
+  // Glib::Object's constructor.
+  {
+    std::lock_guard<std::mutex> lock(extra_object_base_data_mutex);
+    extra_object_base_data.erase(this);
+  }
+
   if (GObject* const gobject = gobject_)
   {
 #ifdef GLIBMM_DEBUG_REFCOUNTING
@@ -352,9 +351,22 @@ ObjectBase::get_property_value(const Glib::ustring& property_name, Glib::ValueBa
   g_object_get_property(const_cast<GObject*>(gobj()), property_name.c_str(), value.gobj());
 }
 
-sigc::connection
+void
 ObjectBase::connect_property_changed(
-  const Glib::ustring& property_name, const sigc::slot<void()>& slot)
+  const Glib::ustring& property_name, const sigc::slot<void>& slot)
+{
+  connect_property_changed_with_return(property_name, slot);
+}
+
+void
+ObjectBase::connect_property_changed(const Glib::ustring& property_name, sigc::slot<void>&& slot)
+{
+  connect_property_changed_with_return(property_name, std::move(slot));
+}
+
+sigc::connection
+ObjectBase::connect_property_changed_with_return(
+  const Glib::ustring& property_name, const sigc::slot<void>& slot)
 {
   // Create a proxy to hold our connection info
   // This will be deleted by destroy_notify_handler.
@@ -366,8 +378,8 @@ ObjectBase::connect_property_changed(
 }
 
 sigc::connection
-ObjectBase::connect_property_changed(
-  const Glib::ustring& property_name, sigc::slot<void()>&& slot)
+ObjectBase::connect_property_changed_with_return(
+  const Glib::ustring& property_name, sigc::slot<void>&& slot)
 {
   // Create a proxy to hold our connection info
   // This will be deleted by destroy_notify_handler.
@@ -390,49 +402,6 @@ ObjectBase::thaw_notify()
   g_object_thaw_notify(gobj());
 }
 
-void ObjectBase::add_custom_interface_class(const Interface_Class* iface_class)
-{
-  if (!priv_pimpl_)
-    priv_pimpl_ = std::make_unique<PrivImpl>();
-  priv_pimpl_->custom_interface_classes.emplace_back(iface_class);
-}
-
-void ObjectBase::add_custom_class_init_function(GClassInitFunc class_init_func, void* class_data)
-{
-  if (!priv_pimpl_)
-    priv_pimpl_ = std::make_unique<PrivImpl>();
-  priv_pimpl_->custom_class_init_functions.emplace_back(
-    std::make_tuple(class_init_func, class_data));
-}
-
-void ObjectBase::set_custom_instance_init_function(GInstanceInitFunc instance_init_func)
-{
-  if (!priv_pimpl_)
-    priv_pimpl_ = std::make_unique<PrivImpl>();
-  priv_pimpl_->custom_instance_init_function = instance_init_func;
-}
-
-const Class::interface_classes_type* ObjectBase::get_custom_interface_classes() const
-{
-  return priv_pimpl_ ? &priv_pimpl_->custom_interface_classes : nullptr;
-}
-
-const Class::class_init_funcs_type* ObjectBase::get_custom_class_init_functions() const
-{
-  return priv_pimpl_ ? &priv_pimpl_->custom_class_init_functions : nullptr;
-}
-
-GInstanceInitFunc ObjectBase::get_custom_instance_init_function() const
-{
-  return priv_pimpl_ ? priv_pimpl_->custom_instance_init_function : nullptr;
-}
-
-void ObjectBase::custom_class_init_finished()
-{
-  priv_pimpl_.reset();
-}
-
-/**** Global function *****************************************************/
 bool
 _gobject_cppinstance_already_deleted(GObject* gobject)
 {
index 3faed9d..cf6a4a0 100644 (file)
@@ -28,7 +28,9 @@
 #include <glibmm/debug.h>
 #include <sigc++/trackable.h>
 #include <typeinfo>
-#include <memory>
+#include <map> // Needed until the next ABI break.
+#include <memory> // Not used by ObjectBase any more, but user code may rely on it being here.
+#include <mutex>
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 extern "C" {
@@ -118,19 +120,34 @@ public:
   template <class PropertyType>
   void get_property(const Glib::ustring& property_name, PropertyType& value) const;
 
-  /// You probably want to use a specific property_*() accessor method instead.
-  template <class PropertyType>
-  PropertyType get_property(const Glib::ustring& property_name) const;
+  // TODO: At the next ABI break, delete connect_property_changed_with_return()
+  // and let connect_property_changed() return sigc::connection.
+  /** You can use the signal_changed() signal of the property proxy instead.
+   *
+   * See also connect_property_changed_with_return().
+   */
+  void connect_property_changed(const Glib::ustring& property_name, const sigc::slot<void>& slot);
 
   /** You can use the signal_changed() signal of the property proxy instead.
+   *
+   * @newin{2,48}
+   */
+  void connect_property_changed(const Glib::ustring& property_name, sigc::slot<void>&& slot);
+
+  /** You can use the signal_changed() signal of the property proxy instead.
+   *
+   * This method was added because connect_property_changed() does not return a sigc::connection,
+   * and we could not break the ABI by changing that function.
    */
-  sigc::connection connect_property_changed(const Glib::ustring& property_name, const sigc::slot<void()>& slot);
+  sigc::connection connect_property_changed_with_return(
+    const Glib::ustring& property_name, const sigc::slot<void>& slot);
 
   /** You can use the signal_changed() signal of the property proxy instead.
    *
    * @newin{2,48}
    */
-  sigc::connection connect_property_changed(const Glib::ustring& property_name, sigc::slot<void()>&& slot);
+  sigc::connection connect_property_changed_with_return(
+    const Glib::ustring& property_name, sigc::slot<void>&& slot);
 
   /** Increases the freeze count on object. If the freeze count is non-zero, the
    * emission of "notify" signals on object is stopped. The signals are queued
@@ -203,15 +220,20 @@ protected:
 
   bool is_anonymous_custom_() const;
 
-  // The following 7 methods are used by Glib::ExtraClassInit, Glib::Interface
-  // and Glib::Object during construction of a named custom type.
-  void add_custom_interface_class(const Interface_Class* iface_class);
-  void add_custom_class_init_function(GClassInitFunc class_init_func, void* class_data = nullptr);
-  void set_custom_instance_init_function(GInstanceInitFunc instance_init_func);
-  const Class::interface_classes_type* get_custom_interface_classes() const;
-  const Class::class_init_funcs_type* get_custom_class_init_functions() const;
-  GInstanceInitFunc get_custom_instance_init_function() const;
-  void custom_class_init_finished();
+  // TODO: At the next ABI break, replace extra_object_base_data by a non-static
+  // data member.
+  // This is a new data member that can't be added as instance data to
+  // ObjectBase now, because it would break ABI.
+  struct ExtraObjectBaseData
+  {
+    Class::interface_class_vector_type custom_interface_classes;
+  };
+
+  using extra_object_base_data_type = std::map<const ObjectBase*, ExtraObjectBaseData>;
+  static extra_object_base_data_type extra_object_base_data;
+  // ObjectBase instances may be used in different threads.
+  // Accesses to extra_object_base_data must be thread-safe.
+  static std::mutex extra_object_base_data_mutex;
 
 public:
   //  is_derived_() must be public, so that overridden vfuncs and signal handlers can call it
@@ -239,15 +261,12 @@ protected:
 
 private:
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
-  // Private part of implementation.
-  // Used only during construction of named custom types.
-  struct PrivImpl;
-  std::unique_ptr<PrivImpl> priv_pimpl_;
-
   virtual void set_manage(); // calls g_error()
+#endif // DOXYGEN_SHOULD_SKIP_THIS
 
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
   friend class Glib::GSigConnectionNode; // for GSigConnectionNode::notify()
-#endif // DOXYGEN_SHOULD_SKIP_THIS
+#endif
 };
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
@@ -275,16 +294,6 @@ ObjectBase::get_property(const Glib::ustring& property_name, PropertyType& value
   value = property_value.get();
 }
 
-template <class PropertyType>
-inline PropertyType
-ObjectBase::get_property(const Glib::ustring& property_name) const
-{
-  PropertyType value;
-  get_property(property_name, value);
-
-  return value;
-}
-
 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
 
 bool _gobject_cppinstance_already_deleted(GObject* gobject);
index 66ebf70..5b7a400 100644 (file)
@@ -58,7 +58,7 @@ void PropertyProxyConnectionNode::callback(GObject*, GParamSpec* pspec, gpointer
   if (pspec && data)
   {
     if (sigc::slot_base* const slot = SignalProxyBase::data_to_slot(data))
-      (*static_cast<sigc::slot<void()>*>(slot))();
+      (*static_cast<sigc::slot<void>*>(slot))();
   }
 }
 
index c5e6a53..fdfb237 100644 (file)
@@ -39,7 +39,7 @@ public:
   SignalProxyProperty(Glib::ObjectBase* obj, const gchar* property_name);
   ~SignalProxyProperty() noexcept;
 
-  using SlotType = sigc::slot<void()>;
+  using SlotType = sigc::slot<void>;
   sigc::connection connect(const SlotType& slot);
   /** @newin{2,48}
    */
index ed3df91..892b6a6 100644 (file)
@@ -167,6 +167,12 @@ public:
    */
   inline explicit operator bool() const noexcept;
 
+#ifndef GLIBMM_DISABLE_DEPRECATED
+  /// @deprecated Use reset() instead because this leads to confusion with clear() methods on the
+  /// underlying class. For instance, people use .clear() when they mean ->clear().
+  inline void clear() noexcept;
+#endif // GLIBMM_DISABLE_DEPRECATED
+
   /** Set underlying instance to nullptr, decrementing reference count of existing instance
    * appropriately.
    * @newin{2,16}
@@ -396,6 +402,15 @@ inline RefPtr<T_CppObject>::operator bool() const noexcept
   return (pCppObject_ != nullptr);
 }
 
+#ifndef GLIBMM_DISABLE_DEPRECATED
+template <class T_CppObject>
+inline void
+RefPtr<T_CppObject>::clear() noexcept
+{
+  reset();
+}
+#endif // GLIBMM_DISABLE_DEPRECATED
+
 template <class T_CppObject>
 inline void
 RefPtr<T_CppObject>::reset() noexcept
index 9da33cc..a7e5d9c 100644 (file)
@@ -43,7 +43,19 @@ SignalProxyNormal::~SignalProxyNormal() noexcept
 }
 
 sigc::slot_base&
-SignalProxyNormal::connect_impl_(bool notify, const sigc::slot_base& slot, bool after)
+SignalProxyNormal::connect_(const sigc::slot_base& slot, bool after)
+{
+  return connect_impl_(info_->callback, slot, after);
+}
+
+sigc::slot_base&
+SignalProxyNormal::connect_notify_(const sigc::slot_base& slot, bool after)
+{
+  return connect_impl_(info_->notify_callback, slot, after);
+}
+
+sigc::slot_base&
+SignalProxyNormal::connect_impl_(GCallback callback, const sigc::slot_base& slot, bool after)
 {
   // create a proxy to hold our connection info
   auto pConnectionNode = new SignalProxyConnectionNode(slot, obj_->gobj());
@@ -51,9 +63,8 @@ SignalProxyNormal::connect_impl_(bool notify, const sigc::slot_base& slot, bool
   // connect it to glib
   // pConnectionNode will be passed in the data argument to the callback.
   pConnectionNode->connection_id_ = g_signal_connect_data(obj_->gobj(), info_->signal_name,
-    notify ? info_->notify_callback : info_->callback, pConnectionNode,
-    &SignalProxyConnectionNode::destroy_notify_handler,
-    static_cast<GConnectFlags>(after ? G_CONNECT_AFTER : 0));
+    callback, pConnectionNode, &SignalProxyConnectionNode::destroy_notify_handler,
+    static_cast<GConnectFlags>((after) ? G_CONNECT_AFTER : 0));
 
   return pConnectionNode->slot_;
 }
@@ -90,7 +101,7 @@ SignalProxyNormal::slot0_void_callback(GObject* self, void* data)
     try
     {
       if (sigc::slot_base* const slot = data_to_slot(data))
-        (*static_cast<sigc::slot<void()>*>(slot))();
+        (*static_cast<sigc::slot<void>*>(slot))();
     }
     catch (...)
     {
@@ -99,9 +110,9 @@ SignalProxyNormal::slot0_void_callback(GObject* self, void* data)
   }
 }
 
-// SignalProxyDetailedBase implementation:
+// SignalProxyDetailed implementation:
 
-SignalProxyDetailedBase::SignalProxyDetailedBase(
+SignalProxyDetailed::SignalProxyDetailed(
   Glib::ObjectBase* obj, const SignalProxyInfo* info, const Glib::ustring& detail_name)
 : SignalProxyBase(obj),
   info_(info),
@@ -110,12 +121,12 @@ SignalProxyDetailedBase::SignalProxyDetailedBase(
 {
 }
 
-SignalProxyDetailedBase::~SignalProxyDetailedBase() noexcept
+SignalProxyDetailed::~SignalProxyDetailed() noexcept
 {
 }
 
 sigc::slot_base&
-SignalProxyDetailedBase::connect_impl_(bool notify, const sigc::slot_base& slot, bool after)
+SignalProxyDetailed::connect_impl_(bool notify, const sigc::slot_base& slot, bool after)
 {
   // create a proxy to hold our connection info
   auto pConnectionNode = new SignalProxyConnectionNode(slot, obj_->gobj());
@@ -131,7 +142,7 @@ SignalProxyDetailedBase::connect_impl_(bool notify, const sigc::slot_base& slot,
 }
 
 sigc::slot_base&
-SignalProxyDetailedBase::connect_impl_(bool notify, sigc::slot_base&& slot, bool after)
+SignalProxyDetailed::connect_impl_(bool notify, sigc::slot_base&& slot, bool after)
 {
   // create a proxy to hold our connection info
   auto pConnectionNode = new SignalProxyConnectionNode(std::move(slot), obj_->gobj());
@@ -147,7 +158,7 @@ SignalProxyDetailedBase::connect_impl_(bool notify, sigc::slot_base&& slot, bool
 }
 
 void
-SignalProxyDetailedBase::emission_stop()
+SignalProxyDetailed::emission_stop()
 {
   g_signal_stop_emission_by_name(obj_->gobj(), detailed_name_.c_str());
 }
index 063bd91..458e6b1 100644 (file)
@@ -47,7 +47,7 @@ struct SignalProxyInfo
 
 #endif // DOXYGEN_SHOULD_SKIP_THIS
 
-// This base class is used by SignalProxyNormal, SignalProxyDetailedBase and SignalProxyProperty.
+// This base class is used by SignalProxyNormal, SignalProxyDetailed and SignalProxyProperty.
 class SignalProxyBase
 {
 public:
@@ -67,7 +67,7 @@ protected:
   ObjectBase* obj_;
 
 private:
-  SignalProxyBase& operator=(const SignalProxyBase&) = delete;
+  SignalProxyBase& operator=(const SignalProxyBase&); // not implemented
 };
 
 // Shared portion of a Signal without detail
@@ -79,7 +79,7 @@ private:
  * the template derivatives, which serve as gatekeepers for the
  * types allowed on a particular signal.
  *
- * For signals with a detailed name (signal_name::detail_name) see SignalProxyDetailedBase.
+ * For signals with a detailed name (signal_name::detail_name) see SignalProxyDetailed.
  */
 class SignalProxyNormal : public SignalProxyBase
 {
@@ -103,20 +103,28 @@ protected:
    */
   SignalProxyNormal(Glib::ObjectBase* obj, const SignalProxyInfo* info);
 
-  /** Connects a signal handler to a signal.
-   * This is called by connect() and connect_notify() in derived SignalProxy classes.
+  /** Connects a generic signal handler to a signal.
+   * This is called by connect() in derived SignalProxy classes.
    *
-   * @param notify Whether this method is called by connect_notify() or by connect().
    * @param slot The signal handler, usually created with sigc::mem_fun() or sigc::ptr_fun().
    * @param after Whether this signal handler should be called before or after the default signal
    * handler.
+   */
+  sigc::slot_base& connect_(const sigc::slot_base& slot, bool after);
+
+  /** Connects a signal handler without a return value to a signal.
+   * This is called by connect_notify() in derived SignalProxy classes.
    *
-   * @newin{2,52}
+   * @param slot The signal handler, which should have a @c void return type,
+   *        usually created with sigc::mem_fun() or sigc::ptr_fun().
+   * @param after Whether this signal handler should be called before or after the default signal
+   * handler.
    */
-  sigc::slot_base& connect_impl_(bool notify, const sigc::slot_base& slot, bool after);
+  sigc::slot_base& connect_notify_(const sigc::slot_base& slot, bool after);
 
   /** Connects a signal handler to a signal.
-   * @see connect_impl_(bool notify, const sigc::slot_base& slot, bool after).
+   * @see connect_(const sigc::slot_base& slot, bool after) and
+   * connect_notify_(const sigc::slot_base& slot, bool after).
    *
    * @newin{2,48}
    */
@@ -125,27 +133,28 @@ protected:
 private:
   const SignalProxyInfo* info_;
 
+  // TODO: We could maybe replace both connect_() and connect_notify_() with this in future, because
+  // they don't do anything extra.
+  /** This is called by connect_() and connect_notify_().
+   */
+  sigc::slot_base& connect_impl_(GCallback callback, const sigc::slot_base& slot, bool after);
+
   // no copy assignment
-  SignalProxyNormal& operator=(const SignalProxyNormal&) = delete;
+  SignalProxyNormal& operator=(const SignalProxyNormal&);
 };
 
 /**** Glib::SignalProxy ***************************************************/
 
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-template <class R, class... T>
-class SignalProxy;
-#endif // DOXYGEN_SHOULD_SKIP_THIS
-
 /** Proxy for signals with any number of arguments.
  * Use the connect() or connect_notify() method, with sigc::mem_fun() or sigc::ptr_fun()
  * to connect signal handlers to signals.
  */
 template <class R, class... T>
-class SignalProxy<R(T...)> : public SignalProxyNormal
+class SignalProxy : public SignalProxyNormal
 {
 public:
-  using SlotType = sigc::slot<R(T...)>;
-  using VoidSlotType = sigc::slot<void(T...)>;
+  using SlotType = sigc::slot<R, T...>;
+  using VoidSlotType = sigc::slot<void, T...>;
 
   SignalProxy(ObjectBase* obj, const SignalProxyInfo* info) : SignalProxyNormal(obj, info) {}
 
@@ -159,7 +168,7 @@ public:
    */
   sigc::connection connect(const SlotType& slot, bool after = true)
   {
-    return sigc::connection(connect_impl_(false, slot, after));
+    return sigc::connection(connect_(slot, after));
   }
 
   /** Connects a signal handler to a signal.
@@ -185,8 +194,9 @@ public:
    * connect_notify() binds <tt>return T()</tt> to the connected signal handler.
    * For instance, if the return type is @c bool, the following two calls are equivalent.
    * @code
-   * connect_notify(sigc::mem_fun(*this, &TheClass::on_something));
-   * connect(sigc::bind_return<bool>(sigc::mem_fun(*this, &TheClass::on_something), false), false);
+   * connect_notify( sigc::mem_fun(*this, &TheClass::on_something) );
+   * connect( sigc::bind_return<bool>(sigc::mem_fun(*this, &TheClass::on_something), false), false
+   * );
    * @endcode
    *
    * @param slot The signal handler, which should have a @c void return type,
@@ -196,7 +206,7 @@ public:
    */
   sigc::connection connect_notify(const VoidSlotType& slot, bool after = false)
   {
-    return sigc::connection(connect_impl_(true, slot, after));
+    return sigc::connection(connect_notify_(slot, after));
   }
 
   /** Connects a signal handler without a return value to a signal.
@@ -210,6 +220,29 @@ public:
   }
 };
 
+/* Templates below has been added to avoid API break, and should not be
+ * used in a newly created code. SignalProxy class should be used instead
+ * of SignalProxy# class.
+ */
+template <typename R>
+using SignalProxy0 = SignalProxy<R>;
+template <typename R, typename T1>
+using SignalProxy1 = SignalProxy<R, T1>;
+template <typename R, typename T1, typename T2>
+using SignalProxy2 = SignalProxy<R, T1, T2>;
+template <typename R, typename T1, typename T2, typename T3>
+using SignalProxy3 = SignalProxy<R, T1, T2, T3>;
+template <typename R, typename T1, typename T2, typename T3, typename T4>
+using SignalProxy4 = SignalProxy<R, T1, T2, T3, T4>;
+template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
+using SignalProxy5 = SignalProxy<R, T1, T2, T3, T4, T5>;
+template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+using SignalProxy6 = SignalProxy<R, T1, T2, T3, T4, T5, T6>;
+
+// TODO: When we can break ABI, consider renaming
+// SignalProxyDetailed => SignalProxyDetailedBase
+// SignalProxyDetailedAnyType => SignalProxyDetailed
+
 // Shared portion of a Signal with detail
 /** The SignalProxy provides an API similar to sigc::signal that can be used to
  * connect sigc::slots to glib signals.
@@ -219,10 +252,10 @@ public:
  * the template derivatives, which serve as gatekeepers for the
  * types allowed on a particular signal.
  */
-class SignalProxyDetailedBase : public SignalProxyBase
+class SignalProxyDetailed : public SignalProxyBase
 {
 public:
-  ~SignalProxyDetailedBase() noexcept;
+  ~SignalProxyDetailed() noexcept;
 
   /// Stops the current signal emission (not in libsigc++)
   void emission_stop();
@@ -234,11 +267,11 @@ protected:
    *             and the C callbacks that should be called by glib.
    * @param detail_name The detail name, if any.
    */
-  SignalProxyDetailedBase(
+  SignalProxyDetailed(
     Glib::ObjectBase* obj, const SignalProxyInfo* info, const Glib::ustring& detail_name);
 
   /** Connects a signal handler to a signal.
-   * This is called by connect() and connect_notify() in derived SignalProxyDetailed classes.
+   * This is called by connect() and connect_notify() in derived SignalProxyDetailedAnyType classes.
    *
    * @param notify Whether this method is called by connect_notify() or by connect().
    * @param slot The signal handler, usually created with sigc::mem_fun() or sigc::ptr_fun().
@@ -259,28 +292,23 @@ private:
   const Glib::ustring detailed_name_; // signal_name[::detail_name]
 
   // no copy assignment
-  SignalProxyDetailedBase& operator=(const SignalProxyDetailedBase&) = delete;
+  SignalProxyDetailed& operator=(const SignalProxyDetailed&);
 };
 
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-template <class R, class... T>
-class SignalProxyDetailed;
-#endif // DOXYGEN_SHOULD_SKIP_THIS
-
 /** Proxy for signals with any number of arguments and possibly a detailed name.
  * Use the connect() or connect_notify() method, with sigc::mem_fun() or sigc::ptr_fun()
  * to connect signal handlers to signals.
  */
 template <class R, class... T>
-class SignalProxyDetailed<R(T...)> : public SignalProxyDetailedBase
+class SignalProxyDetailedAnyType : public SignalProxyDetailed
 {
 public:
-  using SlotType = sigc::slot<R(T...)>;
-  using VoidSlotType = sigc::slot<void(T...)>;
+  using SlotType = sigc::slot<R, T...>;
+  using VoidSlotType = sigc::slot<void, T...>;
 
-  SignalProxyDetailed(
+  SignalProxyDetailedAnyType(
     ObjectBase* obj, const SignalProxyInfo* info, const Glib::ustring& detail_name)
-  : SignalProxyDetailedBase(obj, info, detail_name)
+  : SignalProxyDetailed(obj, info, detail_name)
   {
   }
 
@@ -320,8 +348,9 @@ public:
    * connect_notify() binds <tt>return T()</tt> to the connected signal handler.
    * For instance, if the return type is @c bool, the following two calls are equivalent.
    * @code
-   * connect_notify(sigc::mem_fun(*this, &TheClass::on_something));
-   * connect(sigc::bind_return<bool>(sigc::mem_fun(*this, &TheClass::on_something), false), false);
+   * connect_notify( sigc::mem_fun(*this, &TheClass::on_something) );
+   * connect( sigc::bind_return<bool>(sigc::mem_fun(*this, &TheClass::on_something), false), false
+   * );
    * @endcode
    *
    * @param slot The signal handler, which should have a @c void return type,
@@ -345,6 +374,25 @@ public:
   }
 };
 
+/* Templates below has been added to avoid API break, and should not be
+ * used in a newly created code. SignalProxyDetailedAnyType class should be
+ * used instead of SignalProxyDetailed# class.
+ */
+template <typename R>
+using SignalProxyDetailed0 = SignalProxyDetailedAnyType<R>;
+template <typename R, typename T1>
+using SignalProxyDetailed1 = SignalProxyDetailedAnyType<R, T1>;
+template <typename R, typename T1, typename T2>
+using SignalProxyDetailed2 = SignalProxyDetailedAnyType<R, T1, T2>;
+template <typename R, typename T1, typename T2, typename T3>
+using SignalProxyDetailed3 = SignalProxyDetailedAnyType<R, T1, T2, T3>;
+template <typename R, typename T1, typename T2, typename T3, typename T4>
+using SignalProxyDetailed4 = SignalProxyDetailedAnyType<R, T1, T2, T3, T4>;
+template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5>
+using SignalProxyDetailed5 = SignalProxyDetailedAnyType<R, T1, T2, T3, T4, T5>;
+template <typename R, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+using SignalProxyDetailed6 = SignalProxyDetailedAnyType<R, T1, T2, T3, T4, T5, T6>;
+
 } // namespace Glib
 
 #endif /* _GLIBMM_SIGNALPROXY_H */
index 8603e76..d4d0855 100644 (file)
@@ -41,8 +41,8 @@ SignalProxyConnectionNode::SignalProxyConnectionNode(sigc::slot_base&& slot, GOb
 // notify is a message coming up from the slot to be passed back to Gtk+
 // disconnect is a message coming up from the Gtk+ to be passed down to SigC++
 // static
-void
-SignalProxyConnectionNode::notify(sigc::notifiable* data)
+void*
+SignalProxyConnectionNode::notify(void* data)
 {
   // notification from libsigc++.
   SignalProxyConnectionNode* conn = static_cast<SignalProxyConnectionNode*>(data);
@@ -73,6 +73,8 @@ SignalProxyConnectionNode::notify(sigc::notifiable* data)
       g_signal_handler_disconnect(o, connection_id);
     }
   }
+
+  return nullptr; // apparently unused in libsigc++
 }
 
 // static
index 3099269..88e98ee 100644 (file)
@@ -37,7 +37,7 @@ namespace Glib
   * It lives between the layer of Gtk+ and libsigc++.
   * It is very much an internal class.
   */
-class SignalProxyConnectionNode : public sigc::notifiable
+class SignalProxyConnectionNode
 {
 public:
   /** @param slot The signal handler for the glib signal.
@@ -56,7 +56,7 @@ public:
    * This callback is registered in the slot.
    * @param data The SignalProxyConnectionNode object (@p this).
    */
-  static void notify(sigc::notifiable* data);
+  static void* notify(void* data);
 
   /** Callback that is executed when the glib closure is destroyed.
    * @param data The SignalProxyConnectionNode object (@p this).
diff --git a/glib/glibmm/threadpool.cc b/glib/glibmm/threadpool.cc
new file mode 100644 (file)
index 0000000..75a6a7b
--- /dev/null
@@ -0,0 +1,255 @@
+/* Copyright (C) 2002 The gtkmm 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, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmmconfig.h>
+#ifndef GLIBMM_DISABLE_DEPRECATED
+
+#include <glibmm/threadpool.h>
+#include <glibmm/exceptionhandler.h>
+#include <glibmm/threads.h>
+#include <glib.h>
+#include <list>
+
+namespace Glib
+{
+
+// internal
+class ThreadPool::SlotList
+{
+public:
+  SlotList();
+  ~SlotList() noexcept;
+
+  // noncopyable
+  SlotList(const ThreadPool::SlotList&) = delete;
+  ThreadPool::SlotList& operator=(const ThreadPool::SlotList&) = delete;
+
+  sigc::slot<void>* push(const sigc::slot<void>& slot);
+  sigc::slot<void> pop(sigc::slot<void>* slot_ptr);
+
+  void lock_and_unlock();
+
+private:
+  Glib::Threads::Mutex mutex_;
+  std::list<sigc::slot<void>> list_;
+};
+
+ThreadPool::SlotList::SlotList()
+{
+}
+
+ThreadPool::SlotList::~SlotList() noexcept
+{
+}
+
+sigc::slot<void>*
+ThreadPool::SlotList::push(const sigc::slot<void>& slot)
+{
+  Threads::Mutex::Lock lock(mutex_);
+
+  list_.emplace_back(slot);
+  return &list_.back();
+}
+
+sigc::slot<void>
+ThreadPool::SlotList::pop(sigc::slot<void>* slot_ptr)
+{
+  sigc::slot<void> slot;
+
+  {
+    Threads::Mutex::Lock lock(mutex_);
+
+    std::list<sigc::slot<void>>::iterator pslot = list_.begin();
+    while (pslot != list_.end() && slot_ptr != &*pslot)
+      ++pslot;
+
+    if (pslot != list_.end())
+    {
+      slot = *pslot;
+      list_.erase(pslot);
+    }
+  }
+
+  return slot;
+}
+
+void
+ThreadPool::SlotList::lock_and_unlock()
+{
+  mutex_.lock();
+  mutex_.unlock();
+}
+
+} // namespace Glib
+
+namespace
+{
+
+static void
+call_thread_entry_slot(void* data, void* user_data)
+{
+  try
+  {
+    Glib::ThreadPool::SlotList* const slot_list =
+      static_cast<Glib::ThreadPool::SlotList*>(user_data);
+
+    sigc::slot<void> slot(slot_list->pop(static_cast<sigc::slot<void>*>(data)));
+
+    slot();
+  }
+  catch (Glib::Threads::Thread::Exit&)
+  {
+    // Just exit from the thread.  The Thread::Exit exception
+    // is our sane C++ replacement of g_thread_exit().
+  }
+  catch (...)
+  {
+    Glib::exception_handlers_invoke();
+  }
+}
+
+} // anonymous namespace
+
+namespace Glib
+{
+
+ThreadPool::ThreadPool(int max_threads, bool exclusive)
+: gobject_(nullptr), slot_list_(new SlotList())
+{
+  GError* error = nullptr;
+
+  gobject_ = g_thread_pool_new(&call_thread_entry_slot, slot_list_, max_threads, exclusive, &error);
+
+  if (error)
+  {
+    delete slot_list_;
+    slot_list_ = nullptr;
+    Glib::Error::throw_exception(error);
+  }
+}
+
+ThreadPool::~ThreadPool() noexcept
+{
+  if (gobject_)
+    g_thread_pool_free(gobject_, 1, 1);
+
+  if (slot_list_)
+  {
+    slot_list_->lock_and_unlock();
+    delete slot_list_;
+  }
+}
+
+void
+ThreadPool::push(const sigc::slot<void>& slot)
+{
+  sigc::slot<void>* const slot_ptr = slot_list_->push(slot);
+
+  GError* error = nullptr;
+  g_thread_pool_push(gobject_, slot_ptr, &error);
+
+  if (error)
+  {
+    slot_list_->pop(slot_ptr);
+    Glib::Error::throw_exception(error);
+  }
+}
+
+void
+ThreadPool::set_max_threads(int max_threads)
+{
+  GError* error = nullptr;
+  g_thread_pool_set_max_threads(gobject_, max_threads, &error);
+
+  if (error)
+    Glib::Error::throw_exception(error);
+}
+
+int
+ThreadPool::get_max_threads() const
+{
+  return g_thread_pool_get_max_threads(gobject_);
+}
+
+unsigned int
+ThreadPool::get_num_threads() const
+{
+  return g_thread_pool_get_num_threads(gobject_);
+}
+
+unsigned int
+ThreadPool::unprocessed() const
+{
+  return g_thread_pool_unprocessed(gobject_);
+}
+
+bool
+ThreadPool::get_exclusive() const
+{
+  g_return_val_if_fail(gobject_ != nullptr, false);
+
+  return gobject_->exclusive;
+}
+
+void
+ThreadPool::shutdown(bool immediately)
+{
+  if (gobject_)
+  {
+    g_thread_pool_free(gobject_, immediately, 1);
+    gobject_ = nullptr;
+  }
+
+  if (slot_list_)
+  {
+    slot_list_->lock_and_unlock();
+    delete slot_list_;
+    slot_list_ = nullptr;
+  }
+}
+
+// static
+void
+ThreadPool::set_max_unused_threads(int max_threads)
+{
+  g_thread_pool_set_max_unused_threads(max_threads);
+}
+
+// static
+int
+ThreadPool::get_max_unused_threads()
+{
+  return g_thread_pool_get_max_unused_threads();
+}
+
+// static
+unsigned int
+ThreadPool::get_num_unused_threads()
+{
+  return g_thread_pool_get_num_unused_threads();
+}
+
+// static
+void
+ThreadPool::stop_unused_threads()
+{
+  g_thread_pool_stop_unused_threads();
+}
+
+} // namespace Glib
+
+#endif // GLIBMM_DISABLE_DEPRECATED
diff --git a/glib/glibmm/threadpool.h b/glib/glibmm/threadpool.h
new file mode 100644 (file)
index 0000000..f75f34d
--- /dev/null
@@ -0,0 +1,200 @@
+#ifndef _GLIBMM_THREADPOOL_H
+#define _GLIBMM_THREADPOOL_H
+
+/* Copyright (C) 2002 The gtkmm 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, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmmconfig.h>
+
+#ifndef GLIBMM_DISABLE_DEPRECATED
+
+#include <sigc++/sigc++.h>
+
+extern "C" {
+using GThreadPool = struct _GThreadPool;
+}
+
+namespace Glib
+{
+
+/** @defgroup ThreadPools Thread Pools
+ * Pools of threads to execute work concurrently.
+ *
+ * @deprecated This is deprecated in favor of the standard C++ concurrency API in C++11 and C++14.
+ *
+ * @{
+ */
+
+// TODO: Is std::async() an appropriate replacement to mention for this deprecated API?
+
+/** A pool of threads to execute work concurrently.
+ *
+ * @deprecated This is deprecated in favor of the standard C++ concurrency API in C++11 and C++14.
+ */
+class ThreadPool
+{
+public:
+  /** Constructs a new thread pool.
+   * Whenever you call ThreadPool::push(), either a new thread is created or an
+   * unused one is reused. At most @a max_threads threads are running
+   * concurrently for this thread pool. @a max_threads&nbsp;=&nbsp;-1 allows
+   * unlimited threads to be created for this thread pool.
+   *
+   * The parameter @a exclusive determines, whether the thread pool owns all
+   * threads exclusive or whether the threads are shared globally. If @a
+   * exclusive is <tt>true</tt>, @a max_threads threads are started immediately
+   * and they will run exclusively for this thread pool until it is destroyed
+   * by ~ThreadPool(). If @a exclusive is <tt>false</tt>, threads are created
+   * when needed and shared between all non-exclusive thread pools.  This
+   * implies that @a max_threads may not be -1 for exclusive thread pools.
+   *
+   * @param max_threads The maximal number of threads to execute concurrently
+   * in the new thread pool, -1 means no limit.
+   * @param exclusive Should this thread pool be exclusive?
+   * @throw Glib::ThreadError An error can only occur when @a exclusive is
+   * set to <tt>true</tt> and not all @a max_threads threads could be created.
+   */
+  explicit ThreadPool(int max_threads = -1, bool exclusive = false);
+  virtual ~ThreadPool() noexcept;
+
+  // See http://bugzilla.gnome.org/show_bug.cgi?id=512348 about the sigc::trackable issue.
+  // TODO: At the next ABI break, consider changing const sigc::slot<void>& slot
+  // to const std::function<void()>& func, if it can be assumed that all supported
+  // compilers understand the C++11 template class std::function<>.
+  /** Inserts @a slot into the list of tasks to be executed by the pool.
+   * When the number of currently running threads is lower than the maximal
+   * allowed number of threads, a new thread is started (or reused).  Otherwise
+   * @a slot stays in the queue until a thread in this pool finishes its
+   * previous task and processes @a slot.
+   *
+   * Because sigc::trackable is not thread-safe, if the slot represents a
+   * non-static class method and is created by sigc::mem_fun(), the class concerned
+   * should not derive from sigc::trackable. You can use, say, boost::bind() or,
+   * in C++11, std::bind() or a C++11 lambda expression instead of sigc::mem_fun().
+   *
+   * @param slot A new task for the thread pool.
+   * @throw Glib::ThreadError An error can only occur when a new thread
+   * couldn't be created. In that case @a slot is simply appended to the
+   * queue of work to do.
+   */
+  void push(const sigc::slot<void>& slot);
+
+  /** Sets the maximal allowed number of threads for the pool.
+   * A value of -1 means that the maximal number of threads is unlimited.
+   * Setting @a max_threads to 0 means stopping all work for pool. It is
+   * effectively frozen until @a max_threads is set to a non-zero value again.
+   *
+   * A thread is never terminated while it is still running. Instead the
+   * maximal number of threads only has effect for the allocation of new
+   * threads in ThreadPool::push().  A new thread is allocated whenever the
+   * number of currently running threads in the pool is smaller than the
+   * maximal number.
+   *
+   * @param max_threads A new maximal number of threads for the pool.
+   * @throw Glib::ThreadError An error can only occur when a new thread
+   * couldn't be created.
+   */
+  void set_max_threads(int max_threads);
+
+  /** Returns the maximal number of threads for the pool.
+   * @return The maximal number of threads.
+   */
+  int get_max_threads() const;
+
+  /** Returns the number of threads currently running in the pool.
+   * @return The number of threads currently running.
+   */
+  unsigned int get_num_threads() const;
+
+  /** Returns the number of tasks still unprocessed in the pool.
+   * @return The number of unprocessed tasks.
+   */
+  unsigned int unprocessed() const;
+
+  /** Returns whether all threads are exclusive to this pool.
+   * @return Whether all threads are exclusive to this pool.
+   */
+  bool get_exclusive() const;
+
+  /** Frees all resources allocated for the pool.
+   * If @a immediately is <tt>true</tt>, no new task is processed.  Otherwise the
+   * pool is not freed before the last task is processed.  Note however, that no
+   * thread of this pool is interrupted while processing a task. Instead at least
+   * all still running threads can finish their tasks before the pool is freed.
+   *
+   * This method does not return before all tasks to be processed (dependent on
+   * @a immediately, whether all or only the currently running) are ready.
+   * After calling shutdown() the pool must not be used anymore.
+   *
+   * @param immediately Should the pool shut down immediately?
+   */
+  void shutdown(bool immediately = false);
+
+  /** Sets the maximal number of unused threads to @a max_threads.
+   * If @a max_threads is -1, no limit is imposed on the number of unused threads.
+   * @param max_threads Maximal number of unused threads.
+   */
+  static void set_max_unused_threads(int max_threads);
+
+  /** Returns the maximal allowed number of unused threads.
+   * @return The maximal number of unused threads.
+   */
+  static int get_max_unused_threads();
+
+  /** Returns the number of currently unused threads.
+   * @return The number of currently unused threads.
+   */
+  static unsigned int get_num_unused_threads();
+
+  /** Stops all currently unused threads.
+   * This does not change the maximal number of unused threads.  This function can
+   * be used to regularly stop all unused threads e.g. from Glib::signal_timeout().
+   */
+  static void stop_unused_threads();
+
+  GThreadPool* gobj() { return gobject_; }
+  const GThreadPool* gobj() const { return gobject_; }
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  class SlotList;
+#endif
+
+private:
+  GThreadPool* gobject_;
+  SlotList* slot_list_;
+
+  ThreadPool(const ThreadPool&);
+  ThreadPool& operator=(const ThreadPool&);
+};
+
+/** @} group ThreadPools */
+
+/***************************************************************************/
+/*  inline implementation                                                  */
+/***************************************************************************/
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/**** Glib::Private ********************************************************/
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} // namespace Glib
+
+#endif // GLIBMM_DISABLE_DEPRECATED
+
+#endif /* _GLIBMM_THREADPOOL_H */
index ba6289d..fe45c1a 100644 (file)
@@ -184,9 +184,7 @@ gunichar get_unichar_from_std_iterator(std::string::const_iterator pos) G_GNUC_P
  * If you're using std::ostringstream to build strings for display in the
  * user interface, you must convert the result back to UTF-8 as shown below:
  * @code
- * std::locale::global(std::locale("")); // Set the global locale to the user's preferred locale.
- *                                       // Usually unnecessary here, because Glib::init()
- *                                       // does it for you.
+ * std::locale::global(std::locale("")); // set the global locale to the user's preferred locale
  * std::ostringstream output;
  * output << percentage << " % done";
  * label->set_text(Glib::locale_to_utf8(output.str()));
index 5e17183..096b9fe 100644 (file)
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
 
+#ifndef GLIBMM_DISABLE_DEPRECATED
+/* Occasionally, a struct variable has to be initialized after its definition,
+ * i.e. when using structs as class member data.  For convenience, the macro
+ * GLIBMM_INITIALIZE_STRUCT(Var, Type) is provided.  It even avoids creating
+ * a temporary if the compiler is GCC.
+ *
+ * @deprecated Use e.g. std::memset() instead.
+ * It's not used any more in the code generated by _CLASS_BOXEDTYPE_STATIC.
+ * It generates compiler warnings if __STRICT_ANSI__ is defined.
+ */
+#if ((__GNUC__ >= 3) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) && !defined(__STRICT_ANSI__)
+
+#define GLIBMM_INITIALIZE_STRUCT(Var, Type) __builtin_memset(&(Var), 0, sizeof(Type))
+
+#else
+
+// TODO: This causes warnings like this:
+//"missing initializer for member"
+#define GLIBMM_INITIALIZE_STRUCT(Var, Type) \
+  G_STMT_START                              \
+  {                                         \
+    Type const temp_initializer__ = {       \
+      0,                                    \
+    };                                      \
+    (Var) = temp_initializer__;             \
+  }                                         \
+  G_STMT_END
+
+#endif
+#endif // GLIBMM_DISABLE_DEPRECATED
+
 namespace Glib
 {
 
 // These are used by gmmproc-generated type conversions:
 
+#ifndef GLIBMM_DISABLE_DEPRECATED
+/** Helper to deal with memory allocated
+ * by GLib functions in an exception-safe manner.
+ *
+ * @deprecated Use make_unique_ptr_gfree() instead.
+ */
+template <typename T>
+class ScopedPtr
+{
+private:
+  T* ptr_;
+  ScopedPtr(const ScopedPtr<T>&);
+  ScopedPtr<T>& operator=(const ScopedPtr<T>&);
+
+public:
+  ScopedPtr() : ptr_(nullptr) {}
+  explicit ScopedPtr(T* ptr) : ptr_(ptr) {}
+  ~ScopedPtr() noexcept { g_free(ptr_); }
+  T* get() const { return ptr_; }
+  T** addr() { return &ptr_; }
+};
+#endif // GLIBMM_DISABLE_DEPRECATED
+
 /** Helper to deal with memory allocated
  * by GLib functions in an exception-safe manner.
  *
@@ -42,6 +96,17 @@ make_unique_ptr_gfree(T* p)
   return std::unique_ptr<T[], decltype(&g_free)>(p, &g_free);
 }
 
+// TODO: Deprecate this? We don't use it ourselves.
+/** Removes the const nature of a ptr
+ *
+ */
+template <class T>
+inline T*
+unconst(const T* t)
+{
+  return const_cast<T*>(t);
+}
+
 // Convert const gchar* to ustring, while treating NULL as empty string.
 inline Glib::ustring
 convert_const_gchar_ptr_to_ustring(const char* str)
index a7628fc..4707320 100644 (file)
@@ -57,8 +57,8 @@ class BalancedTree
 {
   _CLASS_GENERIC(BalancedTree, GTree)
 public:
-  using TraverseFunc = sigc::slot<bool(const K&, const V&)>;
-  using CompareFunc = sigc::slot<int(const K&, const K&)>;
+  using TraverseFunc = sigc::slot<bool, const K&, const V&>;
+  using CompareFunc = sigc::slot<int, const K&, const K&>;
 
 protected:
   BalancedTree() :
@@ -67,7 +67,7 @@ protected:
     gobject_ = g_tree_new_full(on_compare_tree, &key_compare_slot, on_destroy_key, on_destroy_value);
   }
 
-  explicit BalancedTree(const CompareFunc &key_compare_slot_) :
+  BalancedTree(const CompareFunc &key_compare_slot_) :
     key_compare_slot(key_compare_slot_)
   {
     gobject_ = g_tree_new_full(on_compare_tree, &key_compare_slot, on_destroy_key, on_destroy_value);
@@ -235,8 +235,8 @@ public:
    */
   V* search(const CompareFunc &search_func, const K& key)
   {
-    sigc::slot<int(const K&, const CompareFunc&, const K&)> real_slot = sigc::ptr_fun(on_compare_key);
-    sigc::slot<int(const K&)> bound_slot = sigc::bind(real_slot, search_func, key);
+    sigc::slot<int, const K&, const CompareFunc&, const K&> real_slot = sigc::ptr_fun(on_compare_key);
+    sigc::slot<int, const K&> bound_slot = sigc::bind(real_slot, search_func, key);
     gpointer value = g_tree_search(gobj(), c_callback_search, reinterpret_cast<gconstpointer>(&bound_slot));
 
     return reinterpret_cast<V*>(value);
@@ -278,7 +278,7 @@ private:
   /// Wrapper for invoking GCompareFunc.
   static gint c_callback_search(gconstpointer a, gconstpointer b)
   {
-    const auto slot = reinterpret_cast<const sigc::slot<int(const K&)> *>(b);
+    const sigc::slot<int, const K&>* slot = reinterpret_cast<const sigc::slot<int, const K&> *>(b);
     return (*slot)(*reinterpret_cast<const K*>(a));
   }
 
index db2baa1..b30cba1 100644 (file)
@@ -106,7 +106,7 @@ public:
    *
    * @return <tt>true</tt> if the transformation was successful, and <tt>false</tt> otherwise.
    */
-  using SlotTransform = sigc::slot<bool(const GValue*, GValue*)>;
+  using SlotTransform = sigc::slot<bool, const GValue*, GValue*>;
 
   /** Creates a binding between @a source_property and @a target_property,
    * allowing you to set the transformation functions to be used by the binding.
@@ -183,7 +183,7 @@ public:
    *         stored in a Glib::Value<T_target> object.
    * @tparam T_functor_to Type of functor that translates from the source to the target.
    *         Must be convertible to<br>
-   *         sigc::slot<bool(const T_source&, T_target&)>.
+   *         sigc::slot<bool, const T_source&, T_target&>.
    *
    * @see bind_property_value()
    *
@@ -196,7 +196,7 @@ public:
     BindingFlags flags,
     const T_functor_to& transform_to)
   {
-    sigc::slot<bool(const T_source&, T_target&)> slot_transform_to = transform_to;
+    sigc::slot<bool, const T_source&, T_target&> slot_transform_to = transform_to;
 
     return bind_property_value(source_property, target_property, flags,
       slot_transform_to.empty() ? SlotTransform() : TransformProp<T_source, T_target>(slot_transform_to));
@@ -219,7 +219,7 @@ public:
    *         stored in a Glib::Value<T_target> object.
    * @tparam T_functor_to Type of functor that translates from the source to the target.
    *         Must be convertible to<br>
-   *         sigc::slot<bool(const T_source&, T_target&)>.
+   *         sigc::slot<bool, const T_source&, T_target&>.
    *
    * @see bind_property_value()
    *
@@ -232,7 +232,7 @@ public:
     BindingFlags flags,
     const T_functor_to& transform_to)
   {
-    sigc::slot<bool(const T_source&, T_target&)> slot_transform_to = transform_to;
+    sigc::slot<bool, const T_source&, T_target&> slot_transform_to = transform_to;
 
     return bind_property_value(source_property, target_property, flags,
       slot_transform_to.empty() ? SlotTransform() : TransformProp<T_source, T_target>(slot_transform_to));
@@ -255,7 +255,7 @@ public:
    *         stored in a Glib::Value<T_target> object.
    * @tparam T_functor_to Type of functor that translates from the source to the target.
    *         Must be convertible to<br>
-   *         sigc::slot<bool(const T_source&, T_target&)>.
+   *         sigc::slot<bool, const T_source&, T_target&>.
    *
    * @see bind_property_value()
    *
@@ -268,7 +268,7 @@ public:
     BindingFlags flags,
     const T_functor_to& transform_to)
   {
-    sigc::slot<bool(const T_source&, T_target&)> slot_transform_to = transform_to;
+    sigc::slot<bool, const T_source&, T_target&> slot_transform_to = transform_to;
 
     return bind_property_value(source_property, target_property, flags,
       slot_transform_to.empty() ? SlotTransform() : TransformProp<T_source, T_target>(slot_transform_to));
@@ -291,7 +291,7 @@ public:
    *         stored in a Glib::Value<T_target> object.
    * @tparam T_functor_to Type of functor that translates from the source to the target.
    *         Must be convertible to<br>
-   *         sigc::slot<bool(const T_source&, T_target&)>.
+   *         sigc::slot<bool, const T_source&, T_target&>.
    *
    * @see bind_property_value()
    *
@@ -304,7 +304,7 @@ public:
     BindingFlags flags,
     const T_functor_to& transform_to)
   {
-    sigc::slot<bool(const T_source&, T_target&)> slot_transform_to = transform_to;
+    sigc::slot<bool, const T_source&, T_target&> slot_transform_to = transform_to;
 
     return bind_property_value(source_property, target_property, flags,
       slot_transform_to.empty() ? SlotTransform() : TransformProp<T_source, T_target>(slot_transform_to));
@@ -329,10 +329,10 @@ public:
    *         stored in a Glib::Value<T_target> object.
    * @tparam T_functor_to Type of functor that translates from the source to the target.
    *         Must be convertible to<br>
-   *         sigc::slot<bool(const T_source&, T_target&)>.
+   *         sigc::slot<bool, const T_source&, T_target&>.
    * @tparam T_functor_from Type of functor that translates from the target to the source.
    *         Must be convertible to<br>
-   *         sigc::slot<bool(const T_target&, T_source&)>.
+   *         sigc::slot<bool, const T_target&, T_source&>.
    *
    * @see bind_property_value()
    *
@@ -346,8 +346,8 @@ public:
     const T_functor_to& transform_to,
     const T_functor_from& transform_from)
   {
-    sigc::slot<bool(const T_source&, T_target&)> slot_transform_to = transform_to;
-    sigc::slot<bool(const T_target&, T_source&)> slot_transform_from = transform_from;
+    sigc::slot<bool, const T_source&, T_target&> slot_transform_to = transform_to;
+    sigc::slot<bool, const T_target&, T_source&> slot_transform_from = transform_from;
 
     return bind_property_value(source_property, target_property, flags,
       slot_transform_to.empty() ? SlotTransform() : TransformProp<T_source, T_target>(slot_transform_to),
@@ -391,12 +391,13 @@ private:
   // The functor TransformProp can be implicitly converted to a SlotTransform
   // and used in a call to bind_property_value().
   template <typename T_from, typename T_to>
-  class TransformProp
+  class TransformProp : public sigc::functor_base
   {
   public:
-    using SlotTypedTransform = sigc::slot<bool(const T_from&, T_to&)>;
+    using result_type = bool;
+    using SlotTypedTransform = sigc::slot<bool, const T_from&, T_to&>;
 
-    explicit TransformProp(const SlotTypedTransform& slot) : typed_transform(slot) {}
+    TransformProp(const SlotTypedTransform& slot) : typed_transform(slot) {}
 
     bool operator()(const GValue* from_value, GValue* to_value)
     {
index 1e657b5..3005197 100644 (file)
@@ -58,7 +58,7 @@ public:
    * int compare(const guint8* first, const guint8* second);
    * </code>
    */
-  using SlotCompare = sigc::slot<int(const guint8*, const guint8*)>;
+  using SlotCompare = sigc::slot<int, const guint8*, const guint8*>;
 
   _WRAP_METHOD(static Glib::RefPtr<ByteArray> create(), g_byte_array_new)
 
index b3a5555..26770dd 100644 (file)
@@ -61,7 +61,9 @@ public:
 
   _WRAP_METHOD(void reset(), g_checksum_reset)
 
-  _WRAP_METHOD(void update(const guchar* data, gssize length), g_checksum_update)
+  //TODO: length should really be gssize, not gsize, when we can break ABI:
+#m4 _CONVERSION(`gsize',`gssize',`(gssize)($3)')
+  _WRAP_METHOD(void update(const guchar* data, gsize length), g_checksum_update)
 
   /** Feeds data into an existing Checksum.
    * The checksum must still be open, that is get_string() or get_digest() must not have been called on the checksum.
@@ -97,3 +99,4 @@ public:
 };
 
 } //namespace Glib
+
index ad23886..4f15dda 100644 (file)
@@ -76,6 +76,24 @@ Date::set_parse(const Glib::ustring& str)
   g_date_set_parse(&gobject_, str.c_str());
 }
 
+_DEPRECATE_IFDEF_START
+
+// Avoid a build problem in the case that std::time_t is equivalent to gint32 (GTime is also gint32)
+// That would make the set_time() method overload impossible.
+#ifdef GLIBMM_HAVE_C_STD_TIME_T_IS_NOT_INT32
+void
+Date::set_time(GTime time)
+{
+  // This method, and the C function g_date_set_time() that it wraps, are deprecated.
+  //(::time_t is used here instead of std::time_t, since the C function is declared
+  // with ::time_t. It's not important. The C++ standard requires that ::time_t
+  // and std::time_t shall be identical when both are defined.)
+  g_date_set_time_t(&gobject_, static_cast<time_t>(time));
+}
+#endif // GLIBMM_HAVE_C_STD_TIME_T_IS_NOT_INT32
+
+_DEPRECATE_IFDEF_END
+
 void
 Date::set_time(std::time_t timet)
 {
index e5c0ca6..228272a 100644 (file)
@@ -109,6 +109,24 @@ public:
    */
   void set_parse (const Glib::ustring& str);
 
+
+  _DEPRECATE_IFDEF_START
+
+  //Avoid a build problem in the case that std::time_t is equivalent to gint32 (GTime is also gint32)
+  //That would make the set_time() method overload impossible.
+  #ifdef GLIBMM_HAVE_C_STD_TIME_T_IS_NOT_INT32
+  /** Sets the value of a date from a GTime value.
+   *
+   * @param time GTime value to set.
+   *
+   * @deprecated Please use set_time(std::time_t) or set_time(const GTimeVal&).
+   */
+  void set_time(GTime time);
+  #endif //GLIBMM_HAVE_C_STD_TIME_T_IS_NOT_INT32
+
+  _DEPRECATE_IFDEF_END
+
+
   /** Sets the value of a date from a <type>std::time_t</type> value.
    *
    * @param timet std::time_t value to set
index 78bb944..6b52c61 100644 (file)
@@ -36,9 +36,12 @@ glibmm_files_any_hg =                \
        regex.hg                \
        shell.hg                \
        spawn.hg                \
+       thread.hg               \
+       threads.hg              \
        timezone.hg             \
        unicode.hg              \
        uriutils.hg             \
+       valuearray.hg \
        variant.hg              \
        variantdict.hg          \
        variantiter.hg          \
index 41c2de2..c43ccb0 100644 (file)
@@ -142,7 +142,8 @@ public:
 #m4 _CONVERSION(`const Glib::ArrayHandle<std::string>&', `const gchar**', `const_cast<const gchar**>($3.data())')
 #m4 _CONVERSION(`Glib::ArrayHandle<std::string>&', `gchar**', `const_cast<gchar**>($3.data())')
 
-  _IGNORE(g_key_file_load_from_dirs)
+  _WRAP_METHOD(bool load_from_dirs(const std::string& file, const Glib::ArrayHandle<std::string>& search_dirs, Glib::ArrayHandle<std::string>& full_path, KeyFileFlags flags = Glib::KEY_FILE_NONE),
+    g_key_file_load_from_dirs, errthrow, deprecated "Use the load_from_dirs() method that takes a std::string& full_path.")
 
   _WRAP_METHOD_DOCS_ONLY(g_key_file_load_from_dirs)
   bool load_from_dirs(const std::string& file, const Glib::ArrayHandle<std::string>& search_dirs, std::string& full_path, KeyFileFlags flags = Glib::KEY_FILE_NONE);
index 4d2f331..a6754c3 100644 (file)
@@ -117,6 +117,14 @@ get_current_dir()
   return convert_return_gchar_ptr_to_stdstring(g_get_current_dir());
 }
 
+#ifndef GLIBMM_DISABLE_DEPRECATED
+std::string
+get_user_special_dir(GUserDirectory directory)
+{
+  return convert_const_gchar_ptr_to_stdstring(g_get_user_special_dir(directory));
+}
+#endif // GLIBMM_DISABLE_DEPRECATED
+
 std::string
 get_user_special_dir(UserDirectory directory)
 {
index 63040c0..f4833f5 100644 (file)
@@ -165,6 +165,28 @@ std::string get_tmp_dir();
  */
 std::string get_current_dir();
 
+#ifndef GLIBMM_DISABLE_DEPRECATED
+/** Returns the full path of a special directory using its logical id.
+ *
+ * On Unix this is done using the XDG special user directories.
+ * For compatibility with existing practise, G_USER_DIRECTORY_DESKTOP
+ * falls back to `$HOME/Desktop` when XDG special user directories have
+ * not been set up.
+ *
+ * Depending on the platform, the user might be able to change the path
+ * of the special directory without requiring the session to restart; GLib
+ * will not reflect any change once the special directories are loaded.
+ *
+ * @param directory The logical id of special directory.
+ * @return The path to the specified special directory, or an empty string
+ *         if the logical id was not found.
+ *
+ * @newin{2,14}
+ * @deprecated Use get_user_special_dir(Glib::UserDirectory directory) instead.
+ */
+std::string get_user_special_dir(GUserDirectory directory);
+#endif // GLIBMM_DISABLE_DEPRECATED
+
 /** Returns the full path of a special directory using its logical id.
  *
  * On Unix this is done using the XDG special user directories.
index bcec2dd..75b63c0 100644 (file)
@@ -69,8 +69,8 @@ class NodeTree
 {
   _CLASS_GENERIC(NodeTree, GNode)
 public:
-  using TraverseFunc = sigc::slot<bool(NodeTree<T>&)>;
-  using ForeachFunc = sigc::slot<void(NodeTree<T>&)>;
+  using TraverseFunc = sigc::slot<bool, NodeTree<T>&>;
+  using ForeachFunc = sigc::slot<void, NodeTree<T>&>;
 
 private:
   static NodeTree<T>* wrap(GNode* node)
@@ -337,10 +337,10 @@ public:
    */
   NodeTree<T>* find_child(const T& the_data, TraverseFlags flags = TRAVERSE_ALL)
   {
-    sigc::slot<void(GNode*, const T&, GNode**)> real_slot = sigc::ptr_fun(on_compare_child);
+    sigc::slot<void, GNode*, const T&, GNode**> real_slot = sigc::ptr_fun(on_compare_child);
 
     GNode* child = nullptr;
-    using type_foreach_gnode_slot = sigc::slot<void(GNode*)>;
+    using type_foreach_gnode_slot = sigc::slot<void, GNode*>;
     type_foreach_gnode_slot bound_slot = sigc::bind(real_slot, the_data, &child);
 
     g_node_children_foreach(gobj(), (GTraverseFlags)flags, c_callback_foreach_compare_child, reinterpret_cast<gpointer>(&bound_slot));
@@ -371,10 +371,10 @@ public:
   NodeTree<T>* find(const T& the_data, TraverseType order = TRAVERSE_IN_ORDER, TraverseFlags flags = TRAVERSE_ALL)
   {
     //We use a sigc::slot for the C callback, so we can bind some extra data.
-    sigc::slot<gboolean(GNode*, const T&, GNode**)> real_slot = sigc::ptr_fun(on_compare_node);
+    sigc::slot<gboolean, GNode*, const T&, GNode**> real_slot = sigc::ptr_fun(on_compare_node);
     GNode* child = nullptr;
 
-    using type_traverse_gnode_slot = sigc::slot<gboolean(GNode*)>;
+    using type_traverse_gnode_slot = sigc::slot<gboolean, GNode*>;
     type_traverse_gnode_slot bound_slot = sigc::bind(real_slot, the_data, &child);
 
     g_node_traverse(const_cast<GNode*>(gobj()), (GTraverseType)order, (GTraverseFlags)flags, -1, c_callback_traverse_compare_node, reinterpret_cast<gpointer>(&bound_slot));
@@ -732,7 +732,7 @@ private:
     }
   }
 
-  /// Wrapper for invoking a sigc::slot<void(GNode*)> (Internal use).
+  /// Wrapper for invoking a sigc::slot<void,GNode*> (Internal use).
   static void c_callback_foreach_compare_child(GNode* node, gpointer data)
   {
     const ForeachFunc* slot = reinterpret_cast<const ForeachFunc*>(data);
@@ -750,7 +750,7 @@ private:
     return FALSE;
   }
 
-  /// Wrapper for invoking a sigc::slot<gboolean(GNode*)> (Internal use).
+  /// Wrapper for invoking a sigc::slot<gboolean,GNode*> (Internal use).
   static gboolean c_callback_traverse_compare_node(GNode* node, gpointer data)
   {
     const TraverseFunc* slot = reinterpret_cast<const TraverseFunc*>(data);
index 0f86e6e..04fe81d 100644 (file)
@@ -200,7 +200,7 @@ public:
    * This function is used to translate user-visible strings, for --help output.
    * The function takes an untranslated string and returns a translated string
    */
-  using SlotTranslate = sigc::slot<Glib::ustring(const Glib::ustring&)>;
+  using SlotTranslate = sigc::slot<Glib::ustring, const Glib::ustring&>;
 
   /**
    * Sets the function which is used to translate user-visible
index 6db4e9e..e89f27c 100644 (file)
@@ -49,17 +49,17 @@ class OptionGroup
 public:
   /** For example Glib::ustring on_translate(const Glib::ustring& original);.
    */
-  using SlotTranslate = sigc::slot<Glib::ustring(const Glib::ustring&)>;
+  using SlotTranslate = sigc::slot<Glib::ustring, const Glib::ustring&>;
 
   /** For example bool on_option_arg_string(const Glib::ustring& option_name,
    *  const Glib::ustring& value, bool has_value);.
    */
-  using SlotOptionArgString = sigc::slot<bool(const Glib::ustring&, const Glib::ustring&, bool)>;
+  using SlotOptionArgString = sigc::slot<bool, const Glib::ustring&, const Glib::ustring&, bool>;
 
   /** For example bool on_option_arg_filename(const Glib::ustring& option_name,
    *  const std::string& value, bool has_value);.
    */
-  using SlotOptionArgFilename = sigc::slot<bool(const Glib::ustring&, const std::string&, bool)>;
+  using SlotOptionArgFilename = sigc::slot<bool, const Glib::ustring&, const std::string&, bool>;
 
   OptionGroup(const Glib::ustring& name, const Glib::ustring& description, const Glib::ustring& help_description = Glib::ustring());
 
index bd34ad5..0949048 100644 (file)
@@ -42,7 +42,7 @@ _WRAP_GERROR(SpawnError, GSpawnError, G_SPAWN_ERROR, NO_GTYPE, s#^2BIG$#TOOBIG#)
 /** For instance,<br>
  *   void on_child_setup();
  */
-using SlotSpawnChildSetup = sigc::slot<void()>;
+using SlotSpawnChildSetup = sigc::slot<void>;
 
 /** Executes a child program asynchronously (your program will not
  * block waiting for the child to exit). The child program is
diff --git a/glib/src/thread.ccg b/glib/src/thread.ccg
new file mode 100644 (file)
index 0000000..3d6d795
--- /dev/null
@@ -0,0 +1,427 @@
+/* Copyright (C) 2002 The gtkmm 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, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/exceptionhandler.h>
+#include <glib.h>
+
+namespace
+{
+
+extern "C" {
+
+static void*
+call_thread_entry_slot(void* data)
+{
+  const auto slot = reinterpret_cast<sigc::slot_base*>(data);
+
+  try
+  {
+    // Recreate the specific slot, and drop the reference obtained by create().
+    (*static_cast<sigc::slot<void>*>(slot))();
+  }
+  catch (Glib::Thread::Exit&)
+  {
+    // Just exit from the thread.  The Thread::Exit exception
+    // is our sane C++ replacement of g_thread_exit().
+  }
+  catch (...)
+  {
+    Glib::exception_handlers_invoke();
+  }
+
+  delete slot;
+  return nullptr;
+}
+
+} // extern "C"
+
+} // anonymous namespace
+
+namespace Glib
+{
+
+// This was always meant as an internal method. It is no longer called,
+// and no longer needs to be called. We are keeping it just to avoid
+// breaking ABI, though hopefully nobody is using it anyway.
+// TODO: Remove this when we can break ABI.
+void
+thread_init_impl()
+{
+  // Make sure the exception map is initialized before creating any thread.
+  Glib::Error::register_init();
+}
+
+/**** Glib::Thread *********************************************************/
+
+// static
+Thread*
+Thread::create(const sigc::slot<void>& slot, bool /* joinable */)
+{
+  // Make a copy of slot on the heap
+  const auto slot_copy = new sigc::slot<void>(slot);
+
+  GError* error = nullptr;
+
+  const auto thread = g_thread_try_new(nullptr, &call_thread_entry_slot, slot_copy, &error);
+
+  if (error)
+  {
+    delete slot_copy;
+    // Glib::Error::throw_exception() will probably wrap G_THREAD_ERROR in a
+    // Glib::Threads::ThreadError instance, but we want a Glib::ThreadError.
+    if (error->domain == G_THREAD_ERROR)
+      throw Glib::ThreadError(error);
+    else
+      Glib::Error::throw_exception(error);
+  }
+
+  return reinterpret_cast<Thread*>(thread);
+}
+
+// static
+Thread*
+Thread::create(const sigc::slot<void>& slot, unsigned long stack_size, bool joinable, bool bound,
+  ThreadPriority priority)
+{
+  // Make a copy of slot on the heap
+  const auto slot_copy = new sigc::slot<void>(slot);
+
+  GError* error = nullptr;
+
+  const auto thread = g_thread_create_full(&call_thread_entry_slot, slot_copy, stack_size, joinable,
+    bound, (GThreadPriority)priority, &error);
+
+  if (error)
+  {
+    delete slot_copy;
+    // Glib::Error::throw_exception() will probably wrap G_THREAD_ERROR in a
+    // Glib::Threads::ThreadError instance, but we want a Glib::ThreadError.
+    if (error->domain == G_THREAD_ERROR)
+      throw Glib::ThreadError(error);
+    else
+      Glib::Error::throw_exception(error);
+  }
+
+  return reinterpret_cast<Thread*>(thread);
+}
+
+// static
+Thread*
+Thread::self()
+{
+  return reinterpret_cast<Thread*>(g_thread_self());
+}
+
+void
+Thread::join()
+{
+  g_thread_join(&gobject_);
+}
+
+bool
+Thread::joinable() const
+{
+  return true; // An appropriate result now that this is deprecated because all threads are now
+               // joinable.
+}
+
+void
+Thread::set_priority(ThreadPriority priority)
+{
+  g_thread_set_priority(&gobject_, (GThreadPriority)priority);
+}
+
+ThreadPriority
+Thread::get_priority() const
+{
+  return THREAD_PRIORITY_NORMAL; // An appropriate result now that this is deprecated because the
+                                 // priority concept has been removed.
+}
+
+void
+thread_init(GThreadFunctions* /* vtable */)
+{
+  // g_thread_init() is deprecated and now does nothing,
+  // so we do not even call it. That avoids a need to link to gthread-2.0,
+  // which contains the empty g_thread_init() implementation.
+  // g_thread_init(vtable);
+
+  Glib::thread_init_impl();
+}
+
+bool
+thread_supported()
+{
+  // MSVC++ needs the != 0 to avoid an int -> bool cast warning.
+  return (g_thread_supported() != 0);
+}
+
+// static
+void
+Thread::yield()
+{
+  g_thread_yield();
+}
+
+Thread*
+wrap(GThread* gobject)
+{
+  return reinterpret_cast<Thread*>(gobject);
+}
+
+/**** Glib::StaticMutex ****************************************************/
+
+void
+StaticMutex::lock()
+{
+  g_static_mutex_lock(&gobject_);
+}
+
+bool
+StaticMutex::trylock()
+{
+  return g_static_mutex_trylock(&gobject_);
+}
+
+void
+StaticMutex::unlock()
+{
+  g_static_mutex_unlock(&gobject_);
+}
+
+StaticMutex::operator Mutex&()
+{
+  // If GStaticMutex is implemented as struct (e.g. on Linux), its first struct
+  // member (runtime_mutex) is a GMutex pointer.  If the gthread implementation
+  // is native (i.e. the vtable pointer passed to g_thread_init() was 0), then
+  // the runtime_mutex pointer is unused, and the rest of the GStaticMutex
+  // struct resembles the mutex data.
+  //
+  // On Win32, GStaticMutex is just a typedef to struct _GMutex*.  Either way,
+  // the first sizeof(GMutex*) bytes of GStaticMutex always resemble a GMutex
+  // pointer.  The gthread implementation relies on that, and we'll also do so.
+
+  GMutex*& runtime_mutex = reinterpret_cast<GMutex*&>(gobject_);
+
+  // Fortunately, it cannot hurt if we set this to the GMutex pointer returned
+  // by g_static_mutex_get_mutex().  Either we just overwrite it with the same
+  // value, or it was unused anyway.  Doing that allows casting the pointer
+  // location to a Glib::Mutex reference (its only data member is a GMutex*).
+
+  runtime_mutex = g_static_mutex_get_mutex(&gobject_);
+
+  return reinterpret_cast<Mutex&>(runtime_mutex);
+}
+
+/**** Glib::Mutex **********************************************************/
+
+Mutex::Mutex()
+: gobject_(g_mutex_new()) // TODO: Use a statically-allocated GMutext instead, with g_mutex_init().
+{
+}
+
+Mutex::~Mutex()
+{
+  g_mutex_free(gobject_);
+}
+
+void
+Mutex::lock()
+{
+  g_mutex_lock(gobject_);
+}
+
+bool
+Mutex::trylock()
+{
+  return g_mutex_trylock(gobject_);
+}
+
+void
+Mutex::unlock()
+{
+  g_mutex_unlock(gobject_);
+}
+
+/**** Glib::StaticRecMutex *************************************************/
+
+void
+StaticRecMutex::lock()
+{
+  g_static_rec_mutex_lock(&gobject_);
+}
+
+bool
+StaticRecMutex::trylock()
+{
+  return g_static_rec_mutex_trylock(&gobject_);
+}
+
+void
+StaticRecMutex::unlock()
+{
+  g_static_rec_mutex_unlock(&gobject_);
+}
+
+void
+StaticRecMutex::lock_full(unsigned int depth)
+{
+  g_static_rec_mutex_lock_full(&gobject_, depth);
+}
+
+unsigned int
+StaticRecMutex::unlock_full()
+{
+  return g_static_rec_mutex_unlock_full(&gobject_);
+}
+
+StaticRecMutex::operator RecMutex&()
+{
+  return static_cast<RecMutex&>(*this);
+}
+
+/**** Glib::RecMutex *******************************************************/
+
+RecMutex::RecMutex()
+{
+  g_static_rec_mutex_init(&gobject_);
+}
+
+RecMutex::~RecMutex()
+{
+  g_static_rec_mutex_free(&gobject_);
+}
+
+/**** Glib::StaticRWLock ***************************************************/
+
+void
+StaticRWLock::reader_lock()
+{
+  g_static_rw_lock_reader_lock(&gobject_);
+}
+
+bool
+StaticRWLock::reader_trylock()
+{
+  return g_static_rw_lock_reader_trylock(&gobject_);
+}
+
+void
+StaticRWLock::reader_unlock()
+{
+  g_static_rw_lock_reader_unlock(&gobject_);
+}
+
+void
+StaticRWLock::writer_lock()
+{
+  g_static_rw_lock_writer_lock(&gobject_);
+}
+
+bool
+StaticRWLock::writer_trylock()
+{
+  return g_static_rw_lock_writer_trylock(&gobject_);
+}
+
+void
+StaticRWLock::writer_unlock()
+{
+  g_static_rw_lock_writer_unlock(&gobject_);
+}
+
+StaticRWLock::operator RWLock&()
+{
+  return static_cast<RWLock&>(*this);
+}
+
+/**** Glib::RWLock *********************************************************/
+
+RWLock::RWLock()
+{
+  g_static_rw_lock_init(&gobject_);
+
+  // GLib doesn't have GRWLock, only GStaticRWLock.  Force initialization
+  // of the mutex and the condition variables now, to mimic the behaviour
+  // of a (hypothetical) GRWLock.
+
+  if (g_static_mutex_get_mutex(&gobject_.mutex))
+  {
+    gobject_.read_cond = g_cond_new();
+    gobject_.write_cond = g_cond_new();
+  }
+}
+
+RWLock::~RWLock()
+{
+  g_static_rw_lock_free(&gobject_);
+}
+
+/**** Glib::Cond ***********************************************************/
+
+Cond::Cond() : gobject_(g_cond_new())
+{
+}
+
+Cond::~Cond()
+{
+  g_cond_free(gobject_);
+}
+
+void
+Cond::signal()
+{
+  g_cond_signal(gobject_);
+}
+
+void
+Cond::broadcast()
+{
+  g_cond_broadcast(gobject_);
+}
+
+void
+Cond::wait(Mutex& mutex)
+{
+  g_cond_wait(gobject_, mutex.gobj());
+}
+
+bool
+Cond::timed_wait(Mutex& mutex, const Glib::TimeVal& abs_time)
+{
+  return g_cond_timed_wait(gobject_, mutex.gobj(), const_cast<Glib::TimeVal*>(&abs_time));
+}
+
+void*
+StaticPrivate_get_helper(GStaticPrivate* private_key)
+{
+  return g_static_private_get(private_key);
+}
+
+void
+StaticPrivate_set_helper(GStaticPrivate* private_key, gpointer data, GDestroyNotify notify)
+{
+  return g_static_private_set(private_key, data, notify);
+}
+
+GPrivate*
+GPrivate_new_helper(GDestroyNotify notify)
+{
+  return g_private_new(notify);
+}
+
+} // namespace Glib
diff --git a/glib/src/thread.hg b/glib/src/thread.hg
new file mode 100644 (file)
index 0000000..57b940f
--- /dev/null
@@ -0,0 +1,1085 @@
+/* Copyright (C) 2002 The gtkmm 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, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_DEFS(glibmm,glib)
+_CONFIGINCLUDE(glibmmconfig.h)
+
+_IS_DEPRECATED // This whole file is deprecated.
+
+#m4 _PUSH(SECTION_CC_PRE_INCLUDES)
+//Stop the compiler warnings about using the deprecated API;
+#define GLIB_DISABLE_DEPRECATION_WARNINGS 1
+#m4 _POP()
+
+// We use GThreadFunctions in the (deprecated) API, so we must temporarily undef G_DISABLE_DEPRECATED.
+// Temporarily undef G_DISABLE_DEPRECATED, redefining it later if appropriate.
+#if defined(G_DISABLE_DEPRECATED) && !defined(GLIBMM_G_DISABLE_DEPRECATED_UNDEFED)
+//Stop the deprecation ifdef guards around the API declarations:
+#undef G_DISABLE_DEPRECATED
+#define GLIBMM_G_DISABLE_DEPRECATED_UNDEFED 1
+#endif
+
+#include <glib.h>
+
+// Redefine G_DISABLE_DEPRECATED if it was defined before we temporarily undefed it:
+#if defined(GLIBMM_G_DISABLE_DEPRECATED_UNDEFED)
+#define G_DISABLE_DEPRECATED 1
+#undef GLIBMM_G_DISABLE_DEPRECATED_UNDEFED
+#endif
+
+
+#include <glibmm/error.h>
+#include <glibmm/timeval.h>
+#include <sigc++/sigc++.h>
+
+#include <cstddef>
+
+/* Shadow THREAD_PRIORITY_NORMAL macro (from winbase.h).
+ */
+#if defined(THREAD_PRIORITY_NORMAL) && !defined(GLIBMM_MACRO_SHADOW_THREAD_PRIORITY_NORMAL)
+enum { GLIBMM_MACRO_DEFINITION_THREAD_PRIORITY_NORMAL = THREAD_PRIORITY_NORMAL };
+#undef THREAD_PRIORITY_NORMAL
+enum { THREAD_PRIORITY_NORMAL = GLIBMM_MACRO_DEFINITION_THREAD_PRIORITY_NORMAL };
+#define THREAD_PRIORITY_NORMAL THREAD_PRIORITY_NORMAL
+#define GLIBMM_MACRO_SHADOW_THREAD_PRIORITY_NORMAL 1
+#endif
+
+
+/** Initializer macro for Glib::StaticRecMutex.
+ * @relates Glib::StaticRecMutex
+ * @hideinitializer
+ *
+ * @deprecated Glib::StaticRecMutex is deprecated in favour of Glib::Threads::RecMutex, which can be used statically.
+ */
+#define GLIBMM_STATIC_REC_MUTEX_INIT { G_STATIC_REC_MUTEX_INIT }
+
+/** Initializer macro for Glib::StaticRWLock.
+ * @relates Glib::StaticRWLock
+ * @hideinitializer
+ *
+ * @deprecated Glib::StaticRWLock is deprecated in favour of Glib::Threads::RWLock, which can be used statically.
+ */
+#define GLIBMM_STATIC_RW_LOCK_INIT { G_STATIC_RW_LOCK_INIT }
+
+/** Initializer macro for Glib::StaticPrivate.
+ * @relates Glib::StaticPrivate
+ * @hideinitializer
+ *
+ * @deprecated Glib::StaticPrivate is deprecated in favour of Glib::Threads::Private, which can be used statically.
+ */
+#define GLIBMM_STATIC_PRIVATE_INIT { G_STATIC_PRIVATE_INIT }
+
+namespace Glib
+{
+
+/** @deprecated Thread priorities no longer have any effect.
+ */
+_WRAP_ENUM(ThreadPriority, GThreadPriority, NO_GTYPE)
+
+/*! @var ThreadPriority THREAD_PRIORITY_LOW
+ * A priority lower than normal.
+ */
+/*! @var ThreadPriority THREAD_PRIORITY_NORMAL
+ * The default priority.
+ */
+/*! @var ThreadPriority THREAD_PRIORITY_HIGH
+ * A priority higher than normal.
+ */
+/*! @var ThreadPriority THREAD_PRIORITY_URGENT
+ * The highest priority.
+ */
+
+/** Initializes the GLib thread system.
+ * @deprecated Calling thread_init() is no longer necessary and no longer has any effect.
+ */
+void thread_init(GThreadFunctions* vtable = nullptr);
+
+/** Returns whether the thread system is initialized.
+ * @return @c true, if the thread system is initialized.
+ * @deprecated This is no longer useful, because the thread system is always initialized.
+ */
+bool thread_supported();
+
+/**
+ * @deprecated Use Glib::Threads::NotLock instead.
+ */
+enum NotLock { NOT_LOCK };
+
+/**
+ * @deprecated Use Glib::Threads::TryLock instead.
+ */
+enum TryLock { TRY_LOCK };
+
+class Mutex;
+class RecMutex;
+class RWLock;
+
+struct StaticRecMutex;
+struct StaticRWLock;
+
+
+/** Exception class for thread-related errors.
+ * @deprecated Use Glib::Threads::ThreadError instead.
+ */
+_WRAP_GERROR(ThreadError, GThreadError, G_THREAD_ERROR, NO_GTYPE)
+
+
+/** Represents a running thread.
+ * An instance of this class can only be obtained with create(), self(),
+ * or wrap(GThread*).  It's not possible to delete a Thread object.  If the
+ * thread is @em not joinable, its resources will be freed automatically
+ * when it exits.  Otherwise, if the thread @em is joinable, you must call
+ * join() to avoid a memory leak.
+ *
+ * @note g_thread_exit() is not wrapped, because that function exits a thread
+ * without any cleanup.  That's especially dangerous in C++ code, since the
+ * destructors of automatic objects won't be invoked.  Instead, you can throw
+ * a Thread::Exit exception, which will be caught by the internal thread
+ * entry function.
+ *
+ * @note You might have noticed that the thread entry slot doesn't have the
+ * usual void* return value.  If you want to return any data from your thread
+ * you can pass an additional output argument to the thread's entry slot.
+ *
+ * @deprecated Use Glib::Threads::Thread instead.
+ */
+class Thread
+{
+public:
+
+  Thread(const Thread&) = delete;
+  Thread& operator=(const Thread&) = delete;
+
+  class Exit;
+
+  //See http://bugzilla.gnome.org/show_bug.cgi?id=512348 about the sigc::trackable issue.
+  /** Creates a new thread with the priority <tt>THREAD_PRIORITY_NORMAL</tt>.
+   * If @a joinable is @c true, you can wait for this thread's termination by
+   * calling join().  Otherwise the thread will just disappear, when ready.
+   *
+   * The new thread executes the function or method @a slot points to.  You can
+   * pass additional arguments using sigc::bind().  If the thread was created
+   * successfully, it is returned, otherwise a ThreadError exception is thrown.
+   *
+   * Because sigc::trackable is not thread safe, if the slot represents a
+   * non-static class method (that is, it is created by sigc::mem_fun()), the
+   * class concerned should not derive from sigc::trackable.
+   *
+   * @param slot A slot to execute in the new thread.
+   * @param joinable This parameter is now ignored because Threads are now always joinable.
+   * @return The new Thread* on success.
+   * @throw Glib::ThreadError
+   */
+  static Thread* create(const sigc::slot<void>& slot, bool joinable = true);
+
+  /** Returns the Thread* corresponding to the calling thread.
+   * @return The current thread.
+   */
+  static Thread* self();
+
+  /** Waits until the thread finishes.
+   * Waits until the thread finishes, i.e. the slot, as given to create(),
+   * returns or g_thread_exit() is called by the thread.  (Calling
+   * g_thread_exit() in a C++ program should be avoided.)  All resources of
+   * the thread including the Glib::Thread object are released.  The thread
+   * must have been created with <tt>joinable&nbsp;=&nbsp;true</tt>.
+   */
+  void join();
+
+  //See http://bugzilla.gnome.org/show_bug.cgi?id=512348 about the sigc::trackable issue.
+  /** Creates a new thread with the priority @a priority. The stack gets the
+   * size @a stack_size or the default value for the current platform, if
+   * @a stack_size is <tt>0</tt>.
+   *
+   * If @a joinable is @c true, you can wait for this thread's termination by
+   * calling join().  Otherwise the thread will just disappear, when ready.
+   * If @a bound is @c true, this thread will be scheduled in the system scope,
+   * otherwise the implementation is free to do scheduling in the process
+   * scope.  The first variant is more expensive resource-wise, but generally
+   * faster.  On some systems (e.g. Linux) all threads are bound.
+   *
+   * The new thread executes the function or method @a slot points to.  You can
+   * pass additional arguments using sigc::bind().  If the thread was created
+   * successfully, it is returned.
+   *
+   * Because sigc::trackable is not thread safe, if the slot represents a
+   * non-static class method (that is, it is created by sigc::mem_fun()), the
+   * class concerned should not derive from sigc::trackable.
+   *
+   * @note It is not guaranteed, that threads with different priorities really
+   * behave accordingly.  On some systems (e.g. Linux) only root can increase
+   * priorities.  On other systems (e.g. Solaris) there doesn't seem to be
+   * different scheduling for different priorities.  All in all try to avoid
+   * being dependent on priorities.  Use <tt>Glib::THREAD_PRIORITY_NORMAL</tt>
+   * here as a default.
+   *
+   * @note Only use the extended
+   * create(const sigc::slot<void>&, unsigned long, bool, bool, ThreadPriority)
+   * function, when you really can't use the simple
+   * create(const sigc::slot<void>&, bool)
+   * instead.  The latter overload does not take @a stack_size, @a bound and
+   * @a priority as arguments, as they should only be used for cases, where
+   * it is inevitable.
+   *
+   * @param slot A slot to execute in the new thread.
+   * @param stack_size A stack size for the new thread, or <tt>0</tt>.
+   * @param joinable Should this thread be joinable?
+   * @param bound Should this thread be bound to a system thread?
+   * @param priority A priority for the thread.
+   * @return The new Thread* on success.
+   * @throw Glib::ThreadError
+   *
+   * @deprecated Use the simpler create() method instead, because all Threads
+   * are now joinable, and bounds and priority parameters now have no effect.
+   */
+  static Thread* create(const sigc::slot<void>& slot, unsigned long stack_size,
+                        bool joinable, bool bound, ThreadPriority priority);
+
+  /** Returns whether the thread is joinable.
+   * @return Whether the thread is joinable.
+   *
+   * @deprecated All threads are now joinable.
+   */
+  bool joinable() const;
+
+  /** Changes the priority of the thread to @a priority.
+   * @note It is not guaranteed, that threads with different priorities really
+   * behave accordingly.  On some systems (e.g. Linux) only @c root can
+   * increase priorities.  On other systems (e.g. Solaris) there doesn't seem
+   * to be different scheduling for different priorities.  All in all try to
+   * avoid being dependent on priorities.
+   * @param priority A new priority for the thread.
+   *
+   * @deprecated Thread priorities no longer have any effect.
+   */
+  void set_priority(ThreadPriority priority);
+
+  /** Returns the priority of the thread.
+   * @return The thread's priority.
+   *
+   * @deprecated Thread priorities no longer have any effect.
+   */
+  ThreadPriority get_priority() const;
+
+  /** Gives way to other threads waiting to be scheduled.
+   * This function is often used as a method to make busy wait less evil.  But
+   * in most cases, you will encounter, there are better methods to do that.
+   * So in general you shouldn't use this function.
+   */
+  static void yield();
+
+  GThread*       gobj()       { return &gobject_; }
+  const GThread* gobj() const { return &gobject_; }
+
+private:
+  GThread gobject_;
+
+  // Glib::Thread can neither be constructed nor deleted.
+  Thread();
+  void operator delete(void*, std::size_t);
+};
+
+/** %Exception class used to exit from a thread.
+ * @code
+ * throw Glib::Thread::Exit();
+ * @endcode
+ * Write this if you want to exit from a thread created by Thread::create().
+ * Of course you must make sure not to catch Thread::Exit by accident, i.e.
+ * when using <tt>catch(...)</tt> somewhere in your code.
+ *
+ * @deprecated Use Glib::Threads::Thread::Exit instead.
+ */
+class Thread::Exit
+{};
+
+
+//TODO: Make sure that Glib::wrap() uses Glib::Threads::wrap() instead.
+
+/** @relates Glib::Thread
+ *
+ * @deprecated Use Glib::Threads::wrap(GThread*) instead.
+ */
+Thread* wrap(GThread* gobject);
+
+struct StaticMutex;
+
+/** Like Glib::Mutex, but can be defined at compile time.
+ * Use @c GLIBMM_STATIC_MUTEX_INIT to initialize a StaticMutex:
+ * @code
+ * Glib::StaticMutex mutex = GLIBMM_STATIC_MUTEX_INIT;
+ * @endcode
+ *
+ * A StaticMutex can be used without calling Glib::thread_init(), it will
+ * silently do nothing then.  That will also work when using the implicit
+ * conversion to Mutex&, thus you can safely use Mutex::Lock with a
+ * StaticMutex.
+ *
+ * @deprecated Use Glib::Threads::Mutex instead, which can be used statically.
+ */
+struct StaticMutex
+{
+  void lock();
+  bool trylock();
+  void unlock();
+
+  operator Mutex&();
+
+  GStaticMutex* gobj() { return &gobject_; }
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  // Must be public to allow initialization at compile time.
+  GStaticMutex gobject_;
+#endif
+};
+
+/** Initializer macro for Glib::StaticMutex.
+ * @relates Glib::StaticMutex
+ * @hideinitializer
+ *
+ * @deprecated  Glib::StaticMutex is deprecated in favour of Glib::Threads::Mutex, which can be used statically.
+ */
+#define GLIBMM_STATIC_MUTEX_INIT { G_STATIC_MUTEX_INIT }
+
+/** Represents a mutex (mutual exclusion).
+ * It can be used to protect data against shared access.  Try to use
+ * Mutex::Lock instead of calling lock() and unlock() directly&nbsp;--
+ * it will make your life much easier.
+ *
+ * @note Glib::Mutex is not recursive, i.e. a thread will deadlock, if it
+ * already has locked the mutex while calling lock().  Use Glib::RecMutex
+ * instead, if you need recursive mutexes.
+ *
+ * @deprecated Use Glib::Threads::Mutex instead.
+ */
+class Mutex
+{
+public:
+  class Lock;
+
+  Mutex();
+
+  Mutex(const Mutex&) = delete;
+  Mutex& operator=(const Mutex&) = delete;
+
+  ~Mutex();
+
+  /** Locks the mutex.
+   * If mutex is already locked by another thread, the current thread will
+   * block until mutex is unlocked by the other thread.
+   * @see Mutex::Lock
+   */
+  void lock();
+
+  /** Tries to lock the mutex.
+   * If the mutex is already locked by another thread, it immediately returns
+   * @c false.  Otherwise it locks the mutex and returns @c true.
+   * @return Whether the mutex could be locked.
+   * @see Mutex::Lock
+   */
+  bool trylock();
+
+  /** Unlocks the mutex.
+   * If another thread is blocked in a lock() call for this mutex, it will be
+   * woken and can lock the mutex itself.
+   * @see Mutex::Lock
+   */
+  void unlock();
+
+  GMutex* gobj() { return gobject_; }
+
+private:
+  GMutex* gobject_;
+};
+
+/** Utility class for exception-safe mutex locking.
+ * @par Usage example:
+ * @code
+ * {
+ *   Glib::Mutex::Lock lock (mutex); // calls mutex.lock()
+ *   do_something();
+ * } // the destructor calls mutex.unlock()
+ * @endcode
+ * As you can see, the compiler takes care of the unlocking.  This is not
+ * only exception safe but also much less error-prone.  You could even
+ * <tt>return</tt> while still holding the lock and it will be released
+ * properly.
+ *
+ * @deprecated Use Glib::Threads::Mutex::Lock instead.
+ */
+class Mutex::Lock
+{
+public:
+  explicit inline Lock(Mutex& mutex);
+  inline Lock(Mutex& mutex, NotLock);
+  inline Lock(Mutex& mutex, TryLock);
+  inline ~Lock();
+
+  inline void acquire();
+  inline bool try_acquire();
+  inline void release();
+  inline bool locked() const;
+
+private:
+  Mutex&  mutex_;
+  bool    locked_;
+
+
+};
+
+
+/** Like Glib::RecMutex, but can be defined at compile time.
+ * Use @c GLIBMM_STATIC_REC_MUTEX_INIT to initialize a StaticRecMutex:
+ * @code
+ * Glib::StaticRecMutex mutex = GLIBMM_STATIC_REC_MUTEX_INIT;
+ * @endcode
+ * A StaticRecMutex can be used without calling Glib::thread_init(), it will
+ * silently do nothing then.  That will also work when using the implicit
+ * conversion to RecMutex&, thus you can safely use RecMutex::Lock with a
+ * StaticRecMutex.
+ *
+ * @deprecated Use Glib::Threads::RecMutex instead, which can be used statically.
+ */
+struct StaticRecMutex
+{
+  void lock();
+  bool trylock();
+  void unlock();
+
+  void lock_full(unsigned int depth);
+  unsigned int unlock_full();
+
+  operator RecMutex&();
+
+  GStaticRecMutex* gobj() { return &gobject_; }
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  // Must be public to allow initialization at compile time.
+  GStaticRecMutex gobject_;
+#endif
+};
+
+/**
+ *
+ * @deprecated Use Glib::Threads::RecMutex instead.
+ */
+class RecMutex : public StaticRecMutex
+{
+public:
+  class Lock;
+
+  RecMutex();
+  ~RecMutex();
+
+private:
+  // noncopyable
+  RecMutex(const RecMutex&);
+  RecMutex& operator=(const RecMutex&);
+};
+
+/** Utility class for exception-safe locking of recursive mutexes.
+ *
+ * @deprecated Use Glib::Threads::RecMutex instead.
+ */
+class RecMutex::Lock
+{
+public:
+  explicit inline Lock(RecMutex& mutex);
+  inline Lock(RecMutex& mutex, NotLock);
+  inline Lock(RecMutex& mutex, TryLock);
+
+  Lock(const RecMutex::Lock&) = delete;
+  RecMutex::Lock& operator=(const RecMutex::Lock&) = delete;
+
+  inline ~Lock();
+
+  inline void acquire();
+  inline bool try_acquire();
+  inline void release();
+  inline bool locked() const;
+
+private:
+  RecMutex& mutex_;
+  bool      locked_;
+};
+
+
+/** Like Glib::RWLock, but can be defined at compile time.
+ * Use @c GLIBMM_STATIC_RW_LOCK_INIT to initialize a StaticRWLock:
+ * @code
+ * Glib::StaticRWLock rw_lock = GLIBMM_STATIC_RW_LOCK_INIT;
+ * @endcode
+ * A StaticRWLock can be used without calling Glib::thread_init(), it will
+ * silently do nothing then.  That will also work when using the implicit
+ * conversion to RWLock&, thus you can safely use RWLock::ReaderLock and
+ * RWLock::WriterLock with a StaticRWLock.
+ *
+ * @deprecated Use Glib::Threads::RWLock instead, which can be used statically.
+ */
+struct StaticRWLock
+{
+  void reader_lock();
+  bool reader_trylock();
+  void reader_unlock();
+
+  void writer_lock();
+  bool writer_trylock();
+  void writer_unlock();
+
+  operator RWLock&();
+
+  GStaticRWLock* gobj() { return &gobject_; }
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  // Must be public to allow initialization at compile time.
+  GStaticRWLock gobject_;
+#endif
+};
+
+/**
+ *
+ * @deprecated Use Glib::Threads::RWLock instead.
+ */
+class RWLock : public StaticRWLock
+{
+public:
+  class ReaderLock;
+  class WriterLock;
+
+  RWLock();
+
+  RWLock(const RWLock&) = delete;
+  RWLock& operator=(const RWLock&) = delete;
+
+  ~RWLock();
+};
+
+/** Utility class for exception-safe locking of read/write locks.
+ *
+ * @deprecated Use Glib::Threads::RWLock::ReaderLock instead.
+ */
+class RWLock::ReaderLock
+{
+public:
+  explicit inline ReaderLock(RWLock& rwlock);
+  inline ReaderLock(RWLock& rwlock, NotLock);
+  inline ReaderLock(RWLock& rwlock, TryLock);
+
+  ReaderLock(const RWLock::ReaderLock&) = delete;
+  RWLock::ReaderLock& operator=(const RWLock::ReaderLock&) = delete;
+
+  inline ~ReaderLock();
+
+  inline void acquire();
+  inline bool try_acquire();
+  inline void release();
+  inline bool locked() const;
+
+private:
+  RWLock& rwlock_;
+  bool    locked_;
+};
+
+/** Utility class for exception-safe locking of read/write locks.
+ *
+ * @deprecated Use Glib::Threads::RWLock::WriterLock instead.
+ */
+class RWLock::WriterLock
+{
+public:
+  explicit inline WriterLock(RWLock& rwlock);
+  inline WriterLock(RWLock& rwlock, NotLock);
+  inline WriterLock(RWLock& rwlock, TryLock);
+
+  WriterLock(const RWLock::WriterLock&) = delete;
+  RWLock::WriterLock& operator=(const RWLock::WriterLock&) = delete;
+
+  inline ~WriterLock();
+
+  inline void acquire();
+  inline bool try_acquire();
+  inline void release();
+  inline bool locked() const;
+
+private:
+  RWLock& rwlock_;
+  bool    locked_;
+};
+
+/** An opaque data structure to represent a condition.
+ * A @a Cond is an object that threads can block on, if they find a certain
+ * condition to be false. If other threads change the state of this condition
+ * they can signal the @a Cond, such that the waiting thread is woken up.
+ * @par Usage example:
+ * @code
+ * Glib::Cond  data_cond;
+ * Glib::Mutex data_mutex;
+ * void* current_data = nullptr;
+ *
+ * void push_data(void* data)
+ * {
+ *   Glib::Mutex::Lock lock (data_mutex);
+ *
+ *   current_data = data;
+ *   data_cond.signal();
+ * }
+ *
+ * void* pop_data()
+ * {
+ *   Glib::Mutex::Lock lock (data_mutex);
+ *
+ *   while (!current_data)
+ *     data_cond.wait(data_mutex);
+ *
+ *   void *const data = current_data;
+ *   current_data = nullptr;
+ *
+ *   return data;
+ * }
+ * @endcode
+ *
+ * @deprecated Use Glib::Threads::Cond instead.
+ */
+class Cond
+{
+public:
+  Cond();
+
+  Cond(const Cond&) = delete;
+  Cond& operator=(const Cond&) = delete;
+
+  ~Cond();
+
+  /** If threads are waiting for this @a Cond, exactly one of them is woken up.
+   * It is good practice to hold the same lock as the waiting thread, while calling
+   * this method, though not required.
+   *
+   */
+  void signal();
+
+  /** If threads are waiting for this @a Cond, all of them are woken up.
+   * It is good practice to hold the same lock as the waiting thread, while calling
+   * this method, though not required.
+   */
+  void broadcast();
+
+  /** Waits until this thread is woken up on this @a Cond.
+   * The mutex is unlocked before falling asleep and locked again before resuming.
+   *
+   * @param mutex a @a Mutex that is currently locked.
+   *
+   * @note It is important to use the @a wait() and @a timed_wait() methods
+   * only inside a loop, which checks for the condition to be true as it is not
+   * guaranteed that the waiting thread will find it fulfilled, even if the signaling
+   * thread left the condition in that state. This is because another thread can have
+   * altered the condition, before the waiting thread got the chance to be woken up,
+   * even if the condition itself is protected by a @a Mutex.
+   */
+  void wait(Mutex& mutex);
+
+  /** Waits until this thread is woken up on this @a Cond, but not longer than until the time, that is specified by @a abs_time.
+   * The mutex is unlocked before falling asleep and locked again before resuming.
+   *
+   * @param mutex a @a Mutex that is currently locked.
+   * @param abs_time a max time to wait.
+   *
+   * @note It is important to use the @a wait() and @a timed_wait() methods
+   * only inside a loop, which checks for the condition to be true as it is not
+   * guaranteed that the waiting thread will find it fulfilled, even if the signaling
+   * thread left the condition in that state. This is because another thread can have
+   * altered the condition, before the waiting thread got the chance to be woken up,
+   * even if the condition itself is protected by a @a Mutex.
+   */
+  bool timed_wait(Mutex& mutex, const Glib::TimeVal& abs_time);
+
+  GCond* gobj() { return gobject_; }
+
+private:
+  GCond* gobject_;
+};
+
+
+/** Thread-local data pointer.
+ *
+ * @deprecated Use Glib::Threads::Private instead, which can be used statically.
+ */
+template <class T>
+struct StaticPrivate
+{
+  using DestroyNotifyFunc =  void (*) (void*);
+
+  static void delete_ptr(void* data);
+
+  inline T* get();
+  inline void set(T* data, DestroyNotifyFunc notify_func = &StaticPrivate<T>::delete_ptr);
+
+  GStaticPrivate* gobj() { return &gobject_; }
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  // Must be public to allow initialization at compile time.
+  GStaticPrivate gobject_;
+#endif
+};
+
+/** Thread-local data pointer.
+ *
+ * @deprecated Use Glib::Threads::Private instead.
+ */
+template <class T>
+class Private
+{
+public:
+
+  Private(const Private<T>&) = delete;
+  Private<T>& operator=(const Private<T>&) = delete;
+
+  using DestructorFunc = void (*) (void*);
+
+  static void delete_ptr(void* data);
+
+  explicit inline Private(DestructorFunc destructor_func = &Private<T>::delete_ptr);
+  inline T* get();
+  inline void set(T* data);
+
+  GPrivate* gobj() { return gobject_; }
+
+private:
+  GPrivate* gobject_;
+};
+
+/** @} group Threads */
+
+/*! A glibmm thread example.
+ * @example thread/thread.cc
+ */
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/***************************************************************************/
+/*  inline implementation                                                  */
+/***************************************************************************/
+
+// internal
+/** @deprecated This was always for internal glibmm use and is now unecessary even inside glibmm.
+ */
+void thread_init_impl();
+
+/**** Glib::Mutex::Lock ****************************************************/
+
+inline
+Mutex::Lock::Lock(Mutex& mutex)
+:
+  mutex_  (mutex),
+  locked_ (true)
+{
+  mutex_.lock();
+}
+
+inline
+Mutex::Lock::Lock(Mutex& mutex, NotLock)
+:
+  mutex_  (mutex),
+  locked_ (false)
+{}
+
+inline
+Mutex::Lock::Lock(Mutex& mutex, TryLock)
+:
+  mutex_  (mutex),
+  locked_ (mutex.trylock())
+{}
+
+inline
+Mutex::Lock::~Lock()
+{
+  if(locked_)
+    mutex_.unlock();
+}
+
+inline
+void Mutex::Lock::acquire()
+{
+  mutex_.lock();
+  locked_ = true;
+}
+
+inline
+bool Mutex::Lock::try_acquire()
+{
+  locked_ = mutex_.trylock();
+  return locked_;
+}
+
+inline
+void Mutex::Lock::release()
+{
+  mutex_.unlock();
+  locked_ = false;
+}
+
+inline
+bool Mutex::Lock::locked() const
+{
+  return locked_;
+}
+
+
+/**** Glib::RecMutex::Lock *************************************************/
+
+inline
+RecMutex::Lock::Lock(RecMutex& mutex)
+:
+  mutex_  (mutex),
+  locked_ (true)
+{
+  mutex_.lock();
+}
+
+inline
+RecMutex::Lock::Lock(RecMutex& mutex, NotLock)
+:
+  mutex_  (mutex),
+  locked_ (false)
+{}
+
+inline
+RecMutex::Lock::Lock(RecMutex& mutex, TryLock)
+:
+  mutex_  (mutex),
+  locked_ (mutex.trylock())
+{}
+
+inline
+RecMutex::Lock::~Lock()
+{
+  if(locked_)
+    mutex_.unlock();
+}
+
+inline
+void RecMutex::Lock::acquire()
+{
+  mutex_.lock();
+  locked_ = true;
+}
+
+inline
+bool RecMutex::Lock::try_acquire()
+{
+  locked_ = mutex_.trylock();
+  return locked_;
+}
+
+inline
+void RecMutex::Lock::release()
+{
+  mutex_.unlock();
+  locked_ = false;
+}
+
+inline
+bool RecMutex::Lock::locked() const
+{
+  return locked_;
+}
+
+
+/**** Glib::RWLock::ReaderLock *********************************************/
+
+inline
+RWLock::ReaderLock::ReaderLock(RWLock& rwlock)
+:
+  rwlock_ (rwlock),
+  locked_ (true)
+{
+  rwlock_.reader_lock();
+}
+
+inline
+RWLock::ReaderLock::ReaderLock(RWLock& rwlock, NotLock)
+:
+  rwlock_ (rwlock),
+  locked_ (false)
+{}
+
+inline
+RWLock::ReaderLock::ReaderLock(RWLock& rwlock, TryLock)
+:
+  rwlock_ (rwlock),
+  locked_ (rwlock.reader_trylock())
+{}
+
+inline
+RWLock::ReaderLock::~ReaderLock()
+{
+  if(locked_)
+    rwlock_.reader_unlock();
+}
+
+inline
+void RWLock::ReaderLock::acquire()
+{
+  rwlock_.reader_lock();
+  locked_ = true;
+}
+
+inline
+bool RWLock::ReaderLock::try_acquire()
+{
+  locked_ = rwlock_.reader_trylock();
+  return locked_;
+}
+
+inline
+void RWLock::ReaderLock::release()
+{
+  rwlock_.reader_unlock();
+  locked_ = false;
+}
+
+inline
+bool RWLock::ReaderLock::locked() const
+{
+  return locked_;
+}
+
+
+/**** Glib::RWLock::WriterLock *********************************************/
+
+inline
+RWLock::WriterLock::WriterLock(RWLock& rwlock)
+:
+  rwlock_ (rwlock),
+  locked_ (true)
+{
+  rwlock_.writer_lock();
+}
+
+inline
+RWLock::WriterLock::WriterLock(RWLock& rwlock, NotLock)
+:
+  rwlock_ (rwlock),
+  locked_ (false)
+{}
+
+inline
+RWLock::WriterLock::WriterLock(RWLock& rwlock, TryLock)
+:
+  rwlock_ (rwlock),
+  locked_ (rwlock.writer_trylock())
+{}
+
+inline
+RWLock::WriterLock::~WriterLock()
+{
+  if(locked_)
+    rwlock_.writer_unlock();
+}
+
+inline
+void RWLock::WriterLock::acquire()
+{
+  rwlock_.writer_lock();
+  locked_ = true;
+}
+
+inline
+bool RWLock::WriterLock::try_acquire()
+{
+  locked_ = rwlock_.writer_trylock();
+  return locked_;
+}
+
+inline
+void RWLock::WriterLock::release()
+{
+  rwlock_.writer_unlock();
+  locked_ = false;
+}
+
+inline
+bool RWLock::WriterLock::locked() const
+{
+  return locked_;
+}
+
+
+/**** Glib::StaticPrivate **************************************************/
+
+// static
+template <class T>
+void StaticPrivate<T>::delete_ptr(void* data)
+{
+  delete static_cast<T*>(data);
+}
+
+/** This is only for use by glibmm itself.
+ */
+void* StaticPrivate_get_helper(GStaticPrivate *private_key);
+
+template <class T> inline
+T* StaticPrivate<T>::get()
+{
+  return static_cast<T*>(StaticPrivate_get_helper(&gobject_));
+}
+
+/** This is only for use by glibmm itself.
+ */
+void StaticPrivate_set_helper(GStaticPrivate *private_key, gpointer data, GDestroyNotify notify);
+
+template <class T> inline
+void StaticPrivate<T>::set(T* data, typename StaticPrivate<T>::DestroyNotifyFunc notify_func)
+{
+  StaticPrivate_set_helper(&gobject_, data, notify_func);
+}
+
+
+/**** Glib::Private ********************************************************/
+
+// static
+template <class T>
+void Private<T>::delete_ptr(void* data)
+{
+  delete static_cast<T*>(data);
+}
+
+/** This is only for use by glibmm itself.
+ */
+GPrivate* GPrivate_new_helper(GDestroyNotify notify);
+
+template <class T> inline
+Private<T>::Private(typename Private<T>::DestructorFunc destructor_func)
+:
+  gobject_ (GPrivate_new_helper(destructor_func))
+{}
+
+template <class T> inline
+T* Private<T>::get()
+{
+  return static_cast<T*>(g_private_get(gobject_));
+}
+
+template <class T> inline
+void Private<T>::set(T* data)
+{
+  g_private_set(gobject_, data);
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} // namespace Glib
+
diff --git a/glib/src/threads.ccg b/glib/src/threads.ccg
new file mode 100644 (file)
index 0000000..274b5a1
--- /dev/null
@@ -0,0 +1,302 @@
+/* Copyright (C) 2002 The gtkmm 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, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/exceptionhandler.h>
+#include <glib.h>
+
+/* Why reinterpret_cast<Thread*>(gobject) is needed:
+ *
+ * A Thread instance is in fact always a GThread instance.
+ * Unfortunately, GThread cannot be a member of Thread,
+ * because it is an opaque struct. Also, the C interface does not provide
+ * any hooks to install a destroy notification handler, thus we cannot
+ * wrap it dynamically either.
+ *
+ * The cast works because Thread does not have any member data, and
+ * it is impossible to derive from it. This is ensured by not implementing
+ * the (private) default constructor.
+ * This trick is used also in classes declared as _CLASS_OPAQUE_REFCOUNTED.
+ */
+
+namespace
+{
+
+extern "C" {
+
+static void*
+call_thread_entry_slot(void* data)
+{
+  const auto slot = reinterpret_cast<sigc::slot_base*>(data);
+
+  try
+  {
+    // Recreate the specific slot.
+    (*static_cast<sigc::slot<void>*>(slot))();
+  }
+  catch (Glib::Threads::Thread::Exit&)
+  {
+    // Just exit from the thread.  The Threads::Thread::Exit exception
+    // is our sane C++ replacement of g_thread_exit().
+  }
+  catch (...)
+  {
+    Glib::exception_handlers_invoke();
+  }
+
+  delete slot;
+  return nullptr;
+}
+
+} // extern "C"
+
+} // anonymous namespace
+
+namespace Glib
+{
+
+namespace Threads
+{
+
+/**** Glib::Threads::Thread ************************************************/
+
+// static
+Thread*
+Thread::create(const sigc::slot<void>& slot, const std::string& name)
+{
+  // Make a copy of slot on the heap.
+  const auto slot_copy = new sigc::slot<void>(slot);
+
+  GError* error = nullptr;
+  auto thread = g_thread_try_new(
+    name.empty() ? nullptr : name.c_str(), &call_thread_entry_slot, slot_copy, &error);
+
+  if (error)
+  {
+    delete slot_copy;
+    Glib::Error::throw_exception(error);
+  }
+  if (!thread)
+  {
+    delete slot_copy;
+  }
+  return reinterpret_cast<Thread*>(thread);
+}
+
+// static
+Thread*
+Thread::create(const sigc::slot<void>& slot)
+{
+  return create(slot, std::string());
+}
+
+// static
+Thread*
+Thread::self()
+{
+  return reinterpret_cast<Thread*>(g_thread_self());
+}
+
+void
+Thread::join()
+{
+  g_thread_join(reinterpret_cast<GThread*>(this));
+}
+
+// static
+void
+Thread::yield()
+{
+  g_thread_yield();
+}
+
+GThread*
+Thread::gobj()
+{
+  return reinterpret_cast<GThread*>(this);
+}
+
+const GThread*
+Thread::gobj() const
+{
+  return reinterpret_cast<const GThread*>(this);
+}
+
+Thread*
+wrap(GThread* gobject)
+{
+  return reinterpret_cast<Thread*>(gobject);
+}
+
+/**** Glib::Threads::Mutex *************************************************/
+
+Mutex::Mutex()
+{
+  g_mutex_init(&gobject_);
+}
+
+Mutex::~Mutex()
+{
+  g_mutex_clear(&gobject_);
+}
+
+void
+Mutex::lock()
+{
+  g_mutex_lock(&gobject_);
+}
+
+bool
+Mutex::trylock()
+{
+  return g_mutex_trylock(&gobject_);
+}
+
+void
+Mutex::unlock()
+{
+  g_mutex_unlock(&gobject_);
+}
+
+Mutex*
+wrap(GMutex* gobject)
+{
+  return reinterpret_cast<Mutex*>(gobject);
+}
+
+/**** Glib::Threads::RecMutex **********************************************/
+
+RecMutex::RecMutex()
+{
+  g_rec_mutex_init(&gobject_);
+}
+
+RecMutex::~RecMutex()
+{
+  g_rec_mutex_clear(&gobject_);
+}
+
+void
+RecMutex::lock()
+{
+  g_rec_mutex_lock(&gobject_);
+}
+
+bool
+RecMutex::trylock()
+{
+  return g_rec_mutex_trylock(&gobject_);
+}
+
+void
+RecMutex::unlock()
+{
+  g_rec_mutex_unlock(&gobject_);
+}
+
+RecMutex*
+wrap(GRecMutex* gobject)
+{
+  return reinterpret_cast<RecMutex*>(gobject);
+}
+
+/**** Glib::Threads::RWLock ************************************************/
+
+void
+RWLock::reader_lock()
+{
+  g_rw_lock_reader_lock(&gobject_);
+}
+
+bool
+RWLock::reader_trylock()
+{
+  return g_rw_lock_reader_trylock(&gobject_);
+}
+
+void
+RWLock::reader_unlock()
+{
+  g_rw_lock_reader_unlock(&gobject_);
+}
+
+void
+RWLock::writer_lock()
+{
+  g_rw_lock_writer_lock(&gobject_);
+}
+
+bool
+RWLock::writer_trylock()
+{
+  return g_rw_lock_writer_trylock(&gobject_);
+}
+
+void
+RWLock::writer_unlock()
+{
+  g_rw_lock_writer_unlock(&gobject_);
+}
+
+RWLock::RWLock()
+{
+  g_rw_lock_init(&gobject_);
+}
+
+RWLock::~RWLock()
+{
+  g_rw_lock_clear(&gobject_);
+}
+
+/**** Glib::Threads::Cond **************************************************/
+
+Cond::Cond()
+{
+  g_cond_init(&gobject_);
+}
+
+Cond::~Cond()
+{
+  g_cond_clear(&gobject_);
+}
+
+void
+Cond::signal()
+{
+  g_cond_signal(&gobject_);
+}
+
+void
+Cond::broadcast()
+{
+  g_cond_broadcast(&gobject_);
+}
+
+void
+Cond::wait(Mutex& mutex)
+{
+  g_cond_wait(&gobject_, mutex.gobj());
+}
+
+bool
+Cond::wait_until(Mutex& mutex, gint64 end_time)
+{
+  return g_cond_wait_until(&gobject_, mutex.gobj(), end_time);
+}
+
+} // namespace Threads
+
+} // namespace Glib
diff --git a/glib/src/threads.hg b/glib/src/threads.hg
new file mode 100644 (file)
index 0000000..6340f45
--- /dev/null
@@ -0,0 +1,932 @@
+/* Copyright (C) 2002 The gtkmm 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, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_DEFS(glibmm,glib)
+_CONFIGINCLUDE(glibmmconfig.h)
+
+_IS_DEPRECATED // This whole file is deprecated.
+
+#m4 _PUSH(SECTION_CC_PRE_INCLUDES)
+// Don't let glibmm.h include thread.h. Pretend that it's already included.
+// glib.h can then be included with G_DISABLE_DEPRECATED defined, and
+// the compiler can react if deprecated glib functions are used.
+#define _GLIBMM_THREAD_H
+#m4 _POP()
+
+#include <glib.h>
+#include <glibmm/error.h>
+#include <sigc++/sigc++.h>
+#include <string>
+#include <cstddef>
+
+namespace Glib
+{
+
+/**
+ * @deprecated The entire Glib::Threads API is deprecated in favor of the
+ * standard C++ concurrency API in C++11 and C++14.
+ */
+namespace Threads
+{
+//The GMMPROC_EXTRA_NAMESPACE() macro is a hint to generate_wrap_init.pl to put it in the Threads sub-namespace
+_GMMPROC_EXTRA_NAMESPACE(Threads)
+
+/** @defgroup Threads Threads
+ * %Thread abstraction; including threads, different mutexes,
+ * conditions and thread private data.
+ *
+ * @deprecated The entire Glib::Threads API is deprecated in favor of the
+ * standard C++ concurrency API in C++11 and C++14.
+ * @{
+ */
+
+/// @deprecated Please use std::lock_guard or std::unique_lock instead.
+enum NotLock { NOT_LOCK };
+
+/// @deprecated Please use std::lock_guard or std::unique_lock instead.
+enum TryLock { TRY_LOCK };
+
+class Mutex;
+class RecMutex;
+class RWLock;
+
+/** %Exception class for thread-related errors.
+ *
+ * @deprecated Please use std::lock_guard or std::unique_lock instead.
+ */
+_WRAP_GERROR(ThreadError, GThreadError, G_THREAD_ERROR, NO_GTYPE)
+
+
+/** Represents a running thread.
+ * An instance of this class can only be obtained with create(), self(),
+ * or wrap(GThread*).  It's not possible to delete a Thread object.
+ * You must call join() to avoid a memory leak.
+ *
+ * @note g_thread_exit() is not wrapped, because that function exits a thread
+ * without any cleanup.  That's especially dangerous in C++ code, since the
+ * destructors of automatic objects won't be invoked.  Instead, you can throw
+ * a Threads::Thread::Exit exception, which will be caught by the internal thread
+ * entry function.
+ *
+ * @note The thread entry slot doesn't have the void* return value that a
+ * GThreadFunc has.  If you want to return any data from your thread,
+ * you can pass an additional output argument to the thread's entry slot.
+ *
+ * @deprecated Please use std::thread instead.
+ */
+class Thread
+{
+public:
+
+  Thread(const Thread&) = delete;
+  Thread& operator=(const Thread&) = delete;
+
+  class Exit;
+
+  //See http://bugzilla.gnome.org/show_bug.cgi?id=512348 about the sigc::trackable issue.
+  // TODO: At the next ABI break, consider changing const sigc::slot<void>& slot
+  // to const std::function<void()>& func, if it can be assumed that all supported
+  // compilers understand the C++11 template class std::function<>.
+  /** Creates a new thread.
+   * You can wait for this thread's termination by calling join().
+   *
+   * The new thread executes the function or method @a slot points to.  You can
+   * pass additional arguments using sigc::bind().  If the thread was created
+   * successfully, it is returned, otherwise a Threads::ThreadError exception is thrown.
+   *
+   * Because sigc::trackable is not thread-safe, if the slot represents a
+   * non-static class method and is created by sigc::mem_fun(), the class concerned
+   * should not derive from sigc::trackable. You can use, say, boost::bind() or,
+   * in C++11, std::bind() or a C++11 lambda expression instead of sigc::mem_fun().
+   *
+   * @param slot A slot to execute in the new thread.
+   * @return The new Thread* on success.
+   * @throw Glib::Threads::ThreadError
+   */
+  static Thread* create(const sigc::slot<void>& slot);
+
+  // TODO: At next ABI break, remove the single parameter create
+  //       method and default name to std::string()
+
+  /** Creates a new named thread.
+   * You can wait for this thread's termination by calling join().
+   *
+   * The new thread executes the function or method @a slot points to.  You can
+   * pass additional arguments using sigc::bind().  If the thread was created
+   * successfully, it is returned, otherwise a Threads::ThreadError exception is thrown.
+   *
+   * Because sigc::trackable is not thread-safe, if the slot represents a
+   * non-static class method and is created by sigc::mem_fun(), the class concerned
+   * should not derive from sigc::trackable. You can use, say, boost::bind() or,
+   * in C++11, std::bind() or a C++11 lambda expression instead of sigc::mem_fun().
+   *
+   * The @a name can be useful for discriminating threads in a debugger.
+   * It is not used for other purposes and does not have to be unique.
+   * Some systems restrict the length of @a name to 16 bytes.
+   *
+   * @param slot A slot to execute in the new thread.
+   * @param name A name for the new thread.
+   * @return The new Thread* on success.
+   * @throw Glib::Threads::ThreadError
+   *
+   * @newin{2,36}
+   */
+  static Thread* create(const sigc::slot<void>& slot, const std::string& name);
+
+  /** Returns the Thread* corresponding to the calling thread.
+   * @return The current thread.
+   */
+  static Thread* self();
+
+  /** Waits until the thread finishes.
+   * Waits until the thread finishes, i.e. the slot, as given to create(),
+   * returns or g_thread_exit() is called by the thread.  (Calling
+   * g_thread_exit() in a C++ program should be avoided.)  All resources of
+   * the thread including the Glib::Threads::Thread object are released.
+   */
+  void join();
+
+  /** Gives way to other threads waiting to be scheduled.
+   * This function is often used as a method to make busy wait less evil.  But
+   * in most cases, you will encounter, there are better methods to do that.
+   * So in general you shouldn't use this function.
+   */
+  static void yield();
+
+  GThread*       gobj();
+  const GThread* gobj() const;
+
+private:
+  // Glib::Thread can neither be constructed nor deleted.
+  Thread();
+  void operator delete(void*, std::size_t);
+};
+
+/** %Exception class used to exit from a thread.
+ * @code
+ * throw Glib::Threads::Thread::Exit();
+ * @endcode
+ * Write this if you want to exit from a thread created by Threads::Thread::create().
+ * Of course you must make sure not to catch Threads::Thread::Exit by accident, i.e.
+ * when using <tt>catch(...)</tt> somewhere in your code.
+ *
+ * @deprecated Please use std::thread instead.
+ */
+class Thread::Exit
+{};
+
+/** A C++ wrapper for the C object.
+ *
+ * @param gobject The C instance.
+ * @return The C++ wrapper.
+ *
+ * @relates Glib::Threads::Thread
+ *
+ * @deprecated Please use std::thread instead.
+ */
+Thread* wrap(GThread* gobject);
+
+/** Represents a mutex (mutual exclusion).
+ * It can be used to protect data against shared access.  Try to use
+ * Mutex::Lock instead of calling lock() and unlock() directly&nbsp;--
+ * it will make your life much easier.
+ *
+ * @note Glib::Threads::Mutex is not recursive, i.e. a thread will deadlock, if it
+ * already has locked the mutex while calling lock().  Use Glib::Threads::RecMutex
+ * instead, if you need recursive mutexes.
+ *
+ * @deprecated Please use std::mutex instead.
+ */
+class Mutex
+{
+public:
+  class Lock;
+
+  Mutex();
+
+  Mutex(const Mutex&) = delete;
+  Mutex& operator=(const Mutex&) = delete;
+
+  ~Mutex();
+
+  /** Locks the mutex.
+   * If mutex is already locked by another thread, the current thread will
+   * block until mutex is unlocked by the other thread.
+   * @see Mutex::Lock
+   */
+  void lock();
+
+  /** Tries to lock the mutex.
+   * If the mutex is already locked by another thread, it immediately returns
+   * @c false.  Otherwise it locks the mutex and returns @c true.
+   * @return Whether the mutex could be locked.
+   * @see Mutex::Lock
+   */
+  bool trylock();
+
+  /** Unlocks the mutex.
+   * If another thread is blocked in a lock() call for this mutex, it will be
+   * woken and can lock the mutex itself.
+   * @see Mutex::Lock
+   */
+  void unlock();
+
+  GMutex* gobj() { return &gobject_; }
+
+private:
+  GMutex gobject_;
+};
+
+/** Utility class for exception-safe mutex locking.
+ * @par Usage example:
+ * @code
+ * {
+ *   Glib::Threads::Mutex::Lock lock(mutex); // calls mutex.lock()
+ *   do_something();
+ * } // the destructor calls mutex.unlock()
+ * @endcode
+ * As you can see, the compiler takes care of the unlocking.  This is not
+ * only exception-safe but also much less error-prone.  You could even
+ * <tt>return</tt> while still holding the lock and it will be released
+ * properly.
+ *
+ * @deprecated Please use std::lock_guard or std::unique_lock instead.
+ */
+class Mutex::Lock
+{
+public:
+  explicit inline Lock(Mutex& mutex);
+  inline Lock(Mutex& mutex, NotLock);
+  inline Lock(Mutex& mutex, TryLock);
+
+  Lock(const Mutex::Lock&) = delete;
+  Mutex::Lock& operator=(const Mutex::Lock&) = delete;
+
+  inline ~Lock();
+
+  inline void acquire();
+  inline bool try_acquire();
+  inline void release();
+  inline bool locked() const;
+
+private:
+  Mutex&  mutex_;
+  bool    locked_;
+};
+
+/** A C++ wrapper for the C object.
+ * Do not use operator delete on the returned pointer. If the caller owns the
+ * GMutex object, the caller must destroy it in the same way as if this function
+ * had not been called.
+ *
+ * @param gobject The C instance.
+ * @result The GMutex* cast to a Glib::Threads::Mutex*.
+ *
+ * @relates Glib::Threads::Mutex
+ */
+Mutex* wrap(GMutex* gobject);
+
+/** This represents a recursive mutex.
+ * It is similar to a Mutex with the difference
+ * that it is possible to lock a RecMutex multiple times in the same
+ * thread without deadlock. When doing so, care has to be taken to
+ * unlock the recursive mutex as often as it has been locked.
+ *
+ * @deprecated Please use std::recursive_mutex instead.
+ */
+class RecMutex
+{
+public:
+  class Lock;
+
+  RecMutex();
+
+  RecMutex(const RecMutex&) = delete;
+  RecMutex& operator=(const RecMutex&) = delete;
+
+  ~RecMutex();
+
+  void lock();
+  bool trylock();
+  void unlock();
+
+  GRecMutex* gobj() { return &gobject_; }
+
+private:
+  GRecMutex gobject_;
+};
+
+/** Utility class for exception-safe locking of recursive mutexes.
+ *
+ * @deprecated Please use std::lock_guard or std::unique_lock instead.
+ */
+class RecMutex::Lock
+{
+public:
+  explicit inline Lock(RecMutex& mutex);
+  inline Lock(RecMutex& mutex, NotLock);
+  inline Lock(RecMutex& mutex, TryLock);
+
+  Lock(const RecMutex::Lock&) = delete;
+  RecMutex::Lock& operator=(const RecMutex::Lock&) = delete;
+
+  inline ~Lock();
+
+  inline void acquire();
+  inline bool try_acquire();
+  inline void release();
+  inline bool locked() const;
+
+private:
+  RecMutex& mutex_;
+  bool      locked_;
+};
+
+/** A C++ wrapper for the C object.
+ * Do not use operator delete on the returned pointer. If the caller owns the
+ * GRecMutex object, the caller must destroy it in the same way as if this function
+ * had not been called.
+ *
+ * @param gobject The C instance.
+ * @result The GRecMutex* cast to a Glib::Threads::RecMutex*.
+ *
+ * @relates Glib::Threads::RecMutex
+ */
+RecMutex* wrap(GRecMutex* gobject);
+
+/** This represents a reader-writer lock.
+ * It is similar to a Mutex in that it allows
+ * multiple threads to coordinate access to a shared resource.
+ *
+ * The difference to a mutex is that a reader-writer lock discriminates
+ * between read-only ('reader') and full ('writer') access. While only
+ * one thread at a time is allowed write access (by holding the 'writer'
+ * lock via writer_lock()), multiple threads can gain
+ * simultaneous read-only access (by holding the 'reader' lock via
+ * reader_lock()).
+ *
+ * @deprecated Please use std::lock_guard or std::unique_lock instead, with std::shared_timed_mutex.
+ */
+class RWLock
+{
+public:
+  class ReaderLock;
+  class WriterLock;
+
+  RWLock();
+
+  RWLock(const RWLock&) = delete;
+  RWLock& operator=(const RWLock&) = delete;
+
+  ~RWLock();
+
+  void reader_lock();
+  bool reader_trylock();
+  void reader_unlock();
+
+  void writer_lock();
+  bool writer_trylock();
+  void writer_unlock();
+
+  GRWLock* gobj() { return &gobject_; }
+
+private:
+  GRWLock gobject_;
+};
+
+/** Utility class for exception-safe locking of read/write locks.
+ *
+ * @deprecated Please use std::lock_guard or std::unique_lock instead, with std::shared_timed_mutex.
+ */
+class RWLock::ReaderLock
+{
+public:
+  explicit inline ReaderLock(RWLock& rwlock);
+  inline ReaderLock(RWLock& rwlock, NotLock);
+  inline ReaderLock(RWLock& rwlock, TryLock);
+
+  ReaderLock(const RWLock::ReaderLock&) = delete;
+  RWLock::ReaderLock& operator=(const RWLock::ReaderLock&) = delete;
+
+  inline ~ReaderLock();
+
+  inline void acquire();
+  inline bool try_acquire();
+  inline void release();
+  inline bool locked() const;
+
+private:
+  RWLock& rwlock_;
+  bool    locked_;
+};
+
+/** Utility class for exception-safe locking of read/write locks.
+ *
+ * @deprecated Please use std::lock_guard or std::unique_lock instead, with std::shared_timed_mutex.
+ */
+class RWLock::WriterLock
+{
+public:
+  explicit inline WriterLock(RWLock& rwlock);
+  inline WriterLock(RWLock& rwlock, NotLock);
+  inline WriterLock(RWLock& rwlock, TryLock);
+
+  WriterLock(const RWLock::WriterLock&) = delete;
+  RWLock::WriterLock& operator=(const RWLock::WriterLock&) = delete;
+
+  inline ~WriterLock();
+
+  inline void acquire();
+  inline bool try_acquire();
+  inline void release();
+  inline bool locked() const;
+
+private:
+  RWLock& rwlock_;
+  bool    locked_;
+};
+
+/** An opaque data structure to represent a condition.
+ * A @a Cond is an object that threads can block on, if they find a certain
+ * condition to be false. If other threads change the state of this condition
+ * they can signal the @a Cond, such that the waiting thread is woken up.
+ *
+ * @deprecated Please use std::condition_variable instead.
+ *
+ * @par Usage example:
+ * @code
+ * Glib::Threads::Cond  data_cond;
+ * Glib::Threads::Mutex data_mutex;
+ * void* current_data = nullptr;
+ *
+ * void push_data(void* data)
+ * {
+ *   Glib::Threads::Mutex::Lock lock(data_mutex);
+ *
+ *   current_data = data;
+ *   data_cond.signal();
+ * }
+ *
+ * void* pop_data()
+ * {
+ *   Glib::Threads::Mutex::Lock lock(data_mutex);
+ *
+ *   while (!current_data)
+ *     data_cond.wait(data_mutex);
+ *
+ *   void* const data = current_data;
+ *   current_data = nullptr;
+ *
+ *   return data;
+ * }
+ * @endcode
+ */
+class Cond
+{
+public:
+  Cond();
+
+  Cond(const Cond&) = delete;
+  Cond& operator=(const Cond&) = delete;
+
+  ~Cond();
+
+  /** If threads are waiting for this @a Cond, exactly one of them is woken up.
+   * It is good practice to hold the same lock as the waiting thread, while calling
+   * this method, though not required.
+   */
+  void signal();
+
+  /** If threads are waiting for this @a Cond, all of them are woken up.
+   * It is good practice to hold the same lock as the waiting threads, while calling
+   * this method, though not required.
+   */
+  void broadcast();
+
+  /** Waits until this thread is woken up on this @a Cond.
+   * The mutex is unlocked before falling asleep and locked again before resuming.
+   *
+   * @param mutex A @a Mutex that is currently locked.
+   *
+   * @note It is important to use the @a wait() and @a wait_until() methods
+   * only inside a loop, which checks for the condition to be true as it is not
+   * guaranteed that the waiting thread will find it fulfilled, even if the signaling
+   * thread left the condition in that state. This is because another thread can have
+   * altered the condition, before the waiting thread got the chance to be woken up,
+   * even if the condition itself is protected by a @a Mutex.
+   */
+  void wait(Mutex& mutex);
+
+  /** Waits until this thread is woken up on this @a Cond, but not longer
+   * than until the time specified by @a end_time.
+   * The mutex is unlocked before falling asleep and locked again before resuming.
+   *
+   * @par Usage example:
+   * Extending the example presented in the documentation of class Cond.
+   * @code
+   * void* pop_data_timed()
+   * {
+   *   Glib::Threads::Mutex::Lock lock(data_mutex);
+   *
+   *   // Wait at most 5 seconds.
+   *   const gint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
+   *   while (!current_data)
+   *     if (!data_cond.wait_until(data_mutex, end_time)
+   *       return nullptr; // timeout
+   *
+   *   void* const data = current_data;
+   *   current_data = nullptr;
+   *
+   *   return data;
+   * }
+   * @endcode
+   * The end time is calculated once, before entering the loop, and reused.
+   * This is the motivation behind the use of absolute time. If a relative time
+   * of 5 seconds were passed directly to the call and a spurious wakeup
+   * occurred, the program would have to start over waiting again, which would
+   * lead to a total wait time of more than 5 seconds.
+   *
+   * @param mutex A @a Mutex that is currently locked.
+   * @param end_time The monotonic time to wait until, in microseconds.
+   *                 See g_get_monotonic_time().
+   * @return <tt>true</tt> if the condition variable was signalled (or in the case
+   *         of a spurious wakeup), <tt>false</tt> if @a end_time has passed.
+   *
+   * @note It is important to use the @a wait() and @a wait_until() methods
+   * only inside a loop, which checks for the condition to be true as it is not
+   * guaranteed that the waiting thread will find it fulfilled, even if the signaling
+   * thread left the condition in that state. This is because another thread can have
+   * altered the condition, before the waiting thread got the chance to be woken up,
+   * even if the condition itself is protected by a @a Mutex.
+   */
+  bool wait_until(Mutex& mutex, gint64 end_time);
+
+  GCond* gobj() { return &gobject_; }
+
+private:
+  GCond gobject_;
+};
+
+/** Thread-local data pointer.
+ *
+ * It is recommended that all instances of this class are statically allocated.
+ * The first time an instance is used (get(), set() or replace() is called)
+ * glib allocates a scarce OS resource that cannot be deallocated.
+ *
+ * @deprecated Please use the thread_local keyword instead.
+ */
+template <class T>
+class Private
+{
+public:
+  Private(const Private<T>&) = delete;
+  Private<T>& operator=(const Private<T>&) = delete;
+
+  using DestructorFunc = void (*) (void*);
+
+  /** Deletes static_cast<T*>(data)
+   */
+  static void delete_ptr(void* data);
+
+  /** Constructor.
+   *
+   * @param destructor_func Function pointer, or <tt>nullptr</tt>. If @a destructor_func is not <tt>nullptr</tt>
+   * and the stored data pointer is not <tt>nullptr</tt>, this function is called when replace()
+   * is called and when the thread exits.
+   */
+  explicit inline Private(DestructorFunc destructor_func = &Private<T>::delete_ptr);
+
+  /** Gets the pointer stored in the calling thread.
+   *
+   * @return If no value has yet been set in this thread, <tt>nullptr</tt> is returned.
+   */
+  inline T* get();
+
+  /** Sets the pointer in the calling thread without calling <tt>destructor_func()</tt>.
+   */
+  inline void set(T* data);
+
+  /** Sets the pointer in the calling thread and calls <tt>destructor_func()</tt>.
+   * If a function pointer (and not <tt>nullptr</tt>) was specified in the constructor, and
+   * the stored data pointer before the call to replace() is not <tt>nullptr</tt>, then
+   * <tt>destructor_func()</tt> is called with this old pointer value.
+   *
+   * @newin{2,32}
+   */
+  inline void replace(T* data);
+
+  GPrivate* gobj() { return gobject_; }
+
+private:
+  GPrivate gobject_;
+};
+
+/** @} group Threads */
+
+/*! A glibmm thread example.
+ * @example thread/thread.cc
+ */
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+/***************************************************************************/
+/*  inline implementation                                                  */
+/***************************************************************************/
+
+/**** Glib::Threads::Mutex::Lock *******************************************/
+
+inline
+Mutex::Lock::Lock(Mutex& mutex)
+:
+  mutex_  (mutex),
+  locked_ (true)
+{
+  mutex_.lock();
+}
+
+inline
+Mutex::Lock::Lock(Mutex& mutex, NotLock)
+:
+  mutex_  (mutex),
+  locked_ (false)
+{}
+
+inline
+Mutex::Lock::Lock(Mutex& mutex, TryLock)
+:
+  mutex_  (mutex),
+  locked_ (mutex.trylock())
+{}
+
+inline
+Mutex::Lock::~Lock()
+{
+  if(locked_)
+    mutex_.unlock();
+}
+
+inline
+void Mutex::Lock::acquire()
+{
+  mutex_.lock();
+  locked_ = true;
+}
+
+inline
+bool Mutex::Lock::try_acquire()
+{
+  locked_ = mutex_.trylock();
+  return locked_;
+}
+
+inline
+void Mutex::Lock::release()
+{
+  mutex_.unlock();
+  locked_ = false;
+}
+
+inline
+bool Mutex::Lock::locked() const
+{
+  return locked_;
+}
+
+
+/**** Glib::Threads::RecMutex::Lock ****************************************/
+
+inline
+RecMutex::Lock::Lock(RecMutex& mutex)
+:
+  mutex_  (mutex),
+  locked_ (true)
+{
+  mutex_.lock();
+}
+
+inline
+RecMutex::Lock::Lock(RecMutex& mutex, NotLock)
+:
+  mutex_  (mutex),
+  locked_ (false)
+{}
+
+inline
+RecMutex::Lock::Lock(RecMutex& mutex, TryLock)
+:
+  mutex_  (mutex),
+  locked_ (mutex.trylock())
+{}
+
+inline
+RecMutex::Lock::~Lock()
+{
+  if(locked_)
+    mutex_.unlock();
+}
+
+inline
+void RecMutex::Lock::acquire()
+{
+  mutex_.lock();
+  locked_ = true;
+}
+
+inline
+bool RecMutex::Lock::try_acquire()
+{
+  locked_ = mutex_.trylock();
+  return locked_;
+}
+
+inline
+void RecMutex::Lock::release()
+{
+  mutex_.unlock();
+  locked_ = false;
+}
+
+inline
+bool RecMutex::Lock::locked() const
+{
+  return locked_;
+}
+
+
+/**** Glib::Threads::RWLock::ReaderLock ************************************/
+
+inline
+RWLock::ReaderLock::ReaderLock(RWLock& rwlock)
+:
+  rwlock_ (rwlock),
+  locked_ (true)
+{
+  rwlock_.reader_lock();
+}
+
+inline
+RWLock::ReaderLock::ReaderLock(RWLock& rwlock, NotLock)
+:
+  rwlock_ (rwlock),
+  locked_ (false)
+{}
+
+inline
+RWLock::ReaderLock::ReaderLock(RWLock& rwlock, TryLock)
+:
+  rwlock_ (rwlock),
+  locked_ (rwlock.reader_trylock())
+{}
+
+inline
+RWLock::ReaderLock::~ReaderLock()
+{
+  if(locked_)
+    rwlock_.reader_unlock();
+}
+
+inline
+void RWLock::ReaderLock::acquire()
+{
+  rwlock_.reader_lock();
+  locked_ = true;
+}
+
+inline
+bool RWLock::ReaderLock::try_acquire()
+{
+  locked_ = rwlock_.reader_trylock();
+  return locked_;
+}
+
+inline
+void RWLock::ReaderLock::release()
+{
+  rwlock_.reader_unlock();
+  locked_ = false;
+}
+
+inline
+bool RWLock::ReaderLock::locked() const
+{
+  return locked_;
+}
+
+
+/**** Glib::Threads::RWLock::WriterLock ************************************/
+
+inline
+RWLock::WriterLock::WriterLock(RWLock& rwlock)
+:
+  rwlock_ (rwlock),
+  locked_ (true)
+{
+  rwlock_.writer_lock();
+}
+
+inline
+RWLock::WriterLock::WriterLock(RWLock& rwlock, NotLock)
+:
+  rwlock_ (rwlock),
+  locked_ (false)
+{}
+
+inline
+RWLock::WriterLock::WriterLock(RWLock& rwlock, TryLock)
+:
+  rwlock_ (rwlock),
+  locked_ (rwlock.writer_trylock())
+{}
+
+inline
+RWLock::WriterLock::~WriterLock()
+{
+  if(locked_)
+    rwlock_.writer_unlock();
+}
+
+inline
+void RWLock::WriterLock::acquire()
+{
+  rwlock_.writer_lock();
+  locked_ = true;
+}
+
+inline
+bool RWLock::WriterLock::try_acquire()
+{
+  locked_ = rwlock_.writer_trylock();
+  return locked_;
+}
+
+inline
+void RWLock::WriterLock::release()
+{
+  rwlock_.writer_unlock();
+  locked_ = false;
+}
+
+inline
+bool RWLock::WriterLock::locked() const
+{
+  return locked_;
+}
+
+/**** Glib::Threads::Private<T> ********************************************/
+
+// static
+template <class T>
+void Private<T>::delete_ptr(void* data)
+{
+  delete static_cast<T*>(data);
+}
+
+template <class T> inline
+Private<T>::Private(typename Private<T>::DestructorFunc destructor_func)
+{
+  // gobject_ = G_PRIVATE_INIT(destructor_func);
+  // does not compile with --enable-warnings=fatal.
+  // GPrivate is a struct, and G_PRIVATE_INIT is an initializer of type { ... }.
+  // G_PRIVATE_INIT can be used only in initializations.
+  const GPrivate temp = G_PRIVATE_INIT(destructor_func);
+  gobject_ = temp;
+}
+
+template <class T> inline
+T* Private<T>::get()
+{
+  return static_cast<T*>(g_private_get(&gobject_));
+}
+
+template <class T> inline
+void Private<T>::set(T* data)
+{
+  g_private_set(&gobject_, data);
+}
+
+template <class T> inline
+void Private<T>::replace(T* data)
+{
+  g_private_replace(&gobject_, data);
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+} //namespace Threads
+
+} // namespace Glib
index f2448dc..ec37c61 100644 (file)
@@ -78,6 +78,9 @@ G_GNUC_EXTENSION typedef long long long_long;
 G_GNUC_EXTENSION typedef unsigned long long unsigned_long_long;
 
 GLIB_VALUE_BASIC(bool, boolean)
+#ifndef GLIBMM_DISABLE_DEPRECATED
+GLIB_VALUE_BASIC(char, char, -128, 127)
+#endif // GLIBMM_DISABLE_DEPRECATED
 GLIB_VALUE_BASIC(signed char, schar, -128, 127)
 GLIB_VALUE_BASIC(unsigned char, uchar, 0, 255)
 GLIB_VALUE_BASIC(int, int, G_MININT, G_MAXINT)
index e4b5885..91a3a4b 100644 (file)
@@ -67,6 +67,10 @@ divert[]dnl
 namespace Glib
 {
 GLIB_VALUE_BASIC(bool, boolean)
+#ifndef GLIBMM_DISABLE_DEPRECATED
+/// @deprecated Use Value<signed char> instead.
+GLIB_VALUE_BASIC(char, char)
+#endif // GLIBMM_DISABLE_DEPRECATED
 /// @newin{2,44}
 GLIB_VALUE_BASIC(signed char, int8)
 GLIB_VALUE_BASIC(unsigned char, uchar)
diff --git a/glib/src/valuearray.ccg b/glib/src/valuearray.ccg
new file mode 100644 (file)
index 0000000..e50323f
--- /dev/null
@@ -0,0 +1,99 @@
+/* Copyright (C) 2002-2009 The gtkmm 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, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/exceptionhandler.h>
+
+static int
+ValueArray_Compare_glibmm_callback(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+  Glib::ValueArray::SlotCompare* the_slot = static_cast<Glib::ValueArray::SlotCompare*>(user_data);
+
+  try
+  {
+    return (*the_slot)(
+      *reinterpret_cast<const Glib::ValueBase*>(a), *reinterpret_cast<const Glib::ValueBase*>(b));
+  }
+  catch (...)
+  {
+    Glib::exception_handlers_invoke();
+  }
+
+  return 0;
+}
+
+namespace Glib
+{
+
+ValueArray::ValueArray() : gobject_(g_value_array_new(0))
+{
+}
+
+ValueArray::ValueArray(guint n_preallocated) : gobject_(g_value_array_new(n_preallocated))
+{
+}
+
+bool
+ValueArray::get_nth(guint index, Glib::ValueBase& value)
+{
+  const auto g_value = g_value_array_get_nth(gobj(), index);
+
+  if (g_value)
+  {
+    value.init(g_value);
+    return true;
+  }
+  else
+    return false;
+}
+
+Glib::ValueArray&
+ValueArray::append(const Glib::ValueBase& value)
+{
+  g_value_array_append(gobj(), value.gobj());
+  return *this;
+}
+
+Glib::ValueArray&
+ValueArray::prepend(const Glib::ValueBase& value)
+{
+  g_value_array_prepend(gobj(), value.gobj());
+  return *this;
+}
+
+Glib::ValueArray&
+ValueArray::insert(guint index, const Glib::ValueBase& value)
+{
+  g_value_array_insert(gobj(), index, value.gobj());
+  return *this;
+}
+
+Glib::ValueArray&
+ValueArray::remove(guint index)
+{
+  g_value_array_remove(gobj(), index);
+  return *this;
+}
+
+Glib::ValueArray&
+ValueArray::sort(const SlotCompare& compare_func)
+{
+  SlotCompare slot_copy(compare_func);
+  g_value_array_sort_with_data(gobj(), &ValueArray_Compare_glibmm_callback, &slot_copy);
+  return *this;
+}
+
+} // Glib namespace
diff --git a/glib/src/valuearray.hg b/glib/src/valuearray.hg
new file mode 100644 (file)
index 0000000..c1b5638
--- /dev/null
@@ -0,0 +1,95 @@
+/* Copyright (C) 2002-2009 The gtkmm 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, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_CONFIGINCLUDE(glibmmconfig.h)
+
+_DEFS(glibmm,glib)
+
+#include <glib-object.h>
+#include <glibmm/value.h>
+#include <sigc++/functors/slot.h>
+
+#m4 _PUSH(SECTION_CC_PRE_INCLUDES)
+#undef G_DISABLE_DEPRECATED
+#define GLIB_DISABLE_DEPRECATION_WARNINGS 1
+#m4 _POP()
+
+_IS_DEPRECATED // This whole file is deprecated.
+
+namespace Glib
+{
+
+/** A container structure to maintain an array of generic values.
+ * The prime purpose of a ValueArray is for it to be used as an object property
+ * that holds an array of values. A ValueArray wraps an array of ValueBase
+ * elements.
+ *
+ * @newin{2,22}
+ *
+ * @deprecated Use std::vector<Glib::ValueBase*> or std::vector< Glib::Value<> >
+ *             instead of Glib::ValueArray.
+ */
+class ValueArray
+{
+  _CLASS_BOXEDTYPE(ValueArray, GValueArray, NONE, g_value_array_copy, g_value_array_free)
+  _IGNORE(g_value_array_copy, g_value_array_free)
+  _CUSTOM_DEFAULT_CTOR
+
+public:
+  /** For example,
+   *  int on_compare(const Glib::ValueBase& v1, const Glib::ValueBase& v2);.
+   *  The compare function should return -1 if v1 < v2, 0 if v1 == v2, and 1 if
+   *  v1 > v2.
+   */
+  using SlotCompare = sigc::slot<int, const Glib::ValueBase&, const Glib::ValueBase&>;
+
+  /** Default constructor.  Constructs a new array with no pre-allocation.
+   */
+  ValueArray();
+
+  /** Constructs a new array with pre-allocation.
+   */
+  ValueArray(guint n_preallocated);
+
+  /** Return the value at @a index contained in the value array.
+   * @param index Index of the value of interest.
+   * @param value An uninitialized ValueBase in which to store the result.  If
+   * the get is successful, @a value will be valid, otherwise it will remain
+   * uninitialized.
+   * @return whether the get was successful or not.
+   */
+  bool get_nth(guint index, Glib::ValueBase& value);
+  _IGNORE(g_value_array_get_nth)
+
+  _WRAP_METHOD_DOCS_ONLY(g_value_array_append)
+  Glib::ValueArray& append(const Glib::ValueBase& value);
+
+  _WRAP_METHOD_DOCS_ONLY(g_value_array_prepend)
+  Glib::ValueArray& prepend(const Glib::ValueBase& value);
+
+  _WRAP_METHOD_DOCS_ONLY(g_value_array_insert)
+  Glib::ValueArray& insert(guint index, const Glib::ValueBase& value);
+
+  _WRAP_METHOD_DOCS_ONLY(g_value_array_remove)
+  Glib::ValueArray& remove(guint index);
+
+  _WRAP_METHOD_DOCS_ONLY(g_value_array_sort)
+  Glib::ValueArray& sort(const SlotCompare& compare_func);
+  _IGNORE(g_value_array_sort_with_data)
+};
+
+} //namespace Glib
index 2418798..06923a7 100644 (file)
@@ -245,6 +245,13 @@ VariantContainerBase::get_iter(const VariantType& container_variant_type) const
 
 /****************** Specializations ***********************************/
 
+_DEPRECATE_IFDEF_START
+VariantBase::operator const void*() const
+{
+  return gobj() ? GINT_TO_POINTER(1) : nullptr;
+}
+_DEPRECATE_IFDEF_END
+
 VariantBase::operator bool() const
 {
   return gobj() ? GINT_TO_POINTER(1) : nullptr;
@@ -324,6 +331,30 @@ Variant<Glib::ustring>::get() const
   return convert_const_gchar_ptr_to_ustring(g_variant_get_string(gobject_, nullptr));
 }
 
+// Variant<Glib::ustring> makes sense for multiple types.
+// See http://library.gnome.org/devel/glib/unstable/glib-GVariant.html#g-variant-get-string
+template <>
+Variant<Glib::ustring>
+VariantBase::cast_dynamic<Variant<Glib::ustring>>(const VariantBase& v) throw(std::bad_cast)
+{
+  if (!v.gobj())
+  {
+    return Variant<Glib::ustring>();
+  }
+
+  const VariantType vtype = v.get_type();
+  if (vtype.equal(VARIANT_TYPE_STRING) || vtype.equal(VARIANT_TYPE_OBJECT_PATH) ||
+      vtype.equal(VARIANT_TYPE_SIGNATURE))
+  {
+    return Variant<Glib::ustring>(const_cast<GVariant*>(v.gobj()), true);
+  }
+  else
+  {
+    // std::cerr << "vtype=" << v.get_type_string() << std::endl;
+    throw std::bad_cast();
+  }
+}
+
 /*--------------------Variant<std::string>---------------------*/
 
 Variant<std::string>::Variant() : VariantStringBase()
@@ -349,6 +380,30 @@ Variant<std::string>::create(const std::string& data)
   return result;
 }
 
+// Variant<std::string> makes sense for multiple types.
+// See http://library.gnome.org/devel/glib/unstable/glib-GVariant.html#g-variant-get-string
+template <>
+Variant<std::string>
+VariantBase::cast_dynamic<Variant<std::string>>(const VariantBase& v) throw(std::bad_cast)
+{
+  if (!v.gobj())
+  {
+    return Variant<std::string>();
+  }
+
+  const VariantType vtype = v.get_type();
+  if (vtype.equal(VARIANT_TYPE_STRING) || vtype.equal(VARIANT_TYPE_BYTESTRING) ||
+      vtype.equal(VARIANT_TYPE_OBJECT_PATH) || vtype.equal(VARIANT_TYPE_SIGNATURE))
+  {
+    return Variant<std::string>(const_cast<GVariant*>(v.gobj()), true);
+  }
+  else
+  {
+    // std::cerr << "vtype=" << v.get_type_string() << std::endl;
+    throw std::bad_cast();
+  }
+}
+
 std::string
 Variant<std::string>::get() const
 {
index 4843398..5de30dc 100644 (file)
@@ -26,7 +26,6 @@ _DEFS(glibmm,glib)
 #include <utility>
 #include <vector>
 #include <map>
-#include <tuple>
 #include <stdexcept>
 #include <typeinfo>
 
@@ -96,6 +95,29 @@ class VariantBase
     g_variant_get, g_variant_get_va)
 public:
 
+_DEPRECATE_IFDEF_START
+  /** This typedef is just to make it more obvious that
+   * our operator const void* should be used like operator bool().
+   *
+   * @deprecated Use the explicit operator bool() instead.
+   */
+  using BoolExpr = const void*;
+
+  /** Test whether the Variant has an underlying instance.
+   *
+   * Mimics usage of pointers:
+   * @code
+   *   if (variant)
+   *     do_something();
+   * @endcode
+   *
+   * @deprecated Use the explicit operator bool() instead.
+   *
+   * @newin{2,36}
+   */
+   operator BoolExpr() const;
+_DEPRECATE_IFDEF_END
+
    /** Test whether the Variant has an underlying instance.
     *
     * @newin{2,50}
@@ -124,6 +146,7 @@ public:
   _WRAP_METHOD(GVariantClass classify() const, g_variant_classify)
 
   _WRAP_METHOD(gsize get_size() const, g_variant_get_size)
+  _WRAP_METHOD(gconstpointer get_data(), g_variant_get_data, deprecated "Use the const version instead.")
   _WRAP_METHOD(gconstpointer get_data() const, g_variant_get_data, newin "2,46")
   _WRAP_METHOD(Glib::RefPtr<const Glib::Bytes> get_data_as_bytes() const, g_variant_get_data_as_bytes, newin "2,46")
   _WRAP_METHOD(void store(gpointer data) const, g_variant_store)
@@ -568,6 +591,11 @@ public:
   _IGNORE(g_variant_get_string, g_variant_dup_string)
 };
 
+//TODO: When we can break ABI, remove this template specialization.
+template<>
+Variant<Glib::ustring> VariantBase::cast_dynamic< Variant<Glib::ustring> >(const VariantBase& v)
+throw(std::bad_cast);
+
 /** Specialization of Variant containing a std::string, for variants of type
  * bytestring, string, object path, or signature.
  * See also Variant<Glib::ustring> for UTF-8 strings.
@@ -612,6 +640,11 @@ public:
   _IGNORE(g_variant_get_bytestring, g_variant_dup_bytestring)
 };
 
+//TODO: When we can break ABI, remove this template specialization.
+template<>
+Variant<std::string> VariantBase::cast_dynamic< Variant<std::string> >(const VariantBase& v)
+throw(std::bad_cast);
+
 /** Specialization of Variant containing a dictionary entry.  See also
  * Variant< std::map<K, V> >.
  * @newin{2,28}
@@ -945,71 +978,6 @@ public:
   VariantIter get_iter() const;
 };
 
-/** Specialization of Variant containing a tuple.
- * @newin{2,52}
- * @ingroup Variant
- */
-template <class... Types>
-class Variant<std::tuple<Types...>> : public VariantContainerBase
-{
-public:
-  using CppContainerType = std::tuple<Types...>;
-
-  /// Default constructor
-  Variant<std::tuple<Types...>>()
-  : VariantContainerBase()
-  {}
-
-  /** GVariant constructor.
-   * @param castitem The GVariant to wrap.
-   * @param take_a_reference Whether to take an extra reference of the GVariant
-   *        or not (not taking one could destroy the GVariant with the wrapper).
-   */
-  explicit Variant<std::tuple<Types...>>(GVariant* castitem, bool take_a_reference = false)
-  : VariantContainerBase(castitem, take_a_reference)
-  {}
-
-  /** Creates a new Variant containing a tuple.
-   * @param data The tuple to use for creation.
-   * @return The new Variant holding a tuple.
-   * @newin{2,52}
-   */
-  static Variant<std::tuple<Types...>> create(const std::tuple<Types...>& data);
-
-  /** Gets the VariantType.
-   * @return The VariantType.
-   * @newin{2,52}
-   */
-  static const VariantType& variant_type() G_GNUC_CONST;
-
-  /** Gets a specific element from the tuple.
-   * It is an error if @a index is greater than or equal to the number of
-   * elements in the tuple. See VariantContainerBase::get_n_children().
-   *
-   * @param index The index of the element.
-   * @return The tuple element at index @a index.
-   * @throw std::out_of_range
-   * @newin{2,52}
-   */
-  template<class T>
-  T get_child(gsize index) const;
-
-  template<class T>
-  Variant<T> get_child_variant(gsize index) const;
-
-  /** Gets the tuple of the Variant.
-   * @return The tuple.
-   * @newin{2,52}
-   */
-  std::tuple<Types...> get() const;
-
-  /** Gets a VariantIter of the Variant.
-   * @return The VariantIter.
-   * @newin{2,52}
-   */
-  VariantIter get_iter() const;
-};
-
 } // namespace Glib
 
 
@@ -1295,124 +1263,4 @@ VariantIter Variant< std::map<K, V> >::get_iter() const
   return VariantContainerBase::get_iter(variant_type());
 }
 
-/*---------------------Variant<std::tuple<class... Types>> --------------------*/
-
-// static
-template <class... Types>
-const VariantType& Variant<std::tuple<Types...>>::variant_type()
-{
-  std::vector<VariantType> types;
-  auto expander = [&types](const VariantType &type) mutable -> int
-  {
-    types.push_back(type);
-    return 0;
-  };
-
-  // expands the variadic template parameters
-  using swallow = int[]; // ensures left to right order
-  swallow{(expander(Variant<Types>::variant_type()))...};
-  static auto type = VariantType::create_tuple(types);
-
-  return type;
-}
-
-namespace detail
-{
-template <class Tuple, std::size_t... Is>
-void expand_tuple(std::vector<VariantBase> &variants, const Tuple & t,
-                  std::index_sequence<Is...>)
-{
-  using swallow = int[]; // ensures left to right order
-  auto expander = [&variants](const VariantBase &variant) -> int
-  {
-    variants.push_back(variant);
-    return 0;
-  };
-  (void)swallow {(expander(Variant<typename std::tuple_element<Is, Tuple>::type>::create(std::get<Is>(t))))...};
-}
-} // namespace detail
-
-template <class... Types>
-Variant<std::tuple<Types...>>
-Variant<std::tuple<Types...>>::create(const std::tuple<Types...>& data)
-{
-  // create a vector containing all tuple values as variants
-  std::vector<Glib::VariantBase> variants;
-  detail::expand_tuple(variants, data, std::index_sequence_for<Types...>{});
-
-  using var_ptr = GVariant*;
-  var_ptr* const var_array = new var_ptr[sizeof... (Types)];
-
-  for (std::vector<VariantBase>::size_type i = 0; i < variants.size(); i++)
-    var_array[i] = const_cast<GVariant*>(variants[i].gobj());
-
-  Variant<std::tuple<Types...>> result = Variant<std::tuple<Types...>>(
-          g_variant_new_tuple(var_array, variants.size()));
-
-  return result;
-}
-
-template <class... Types>
-template <class T>
-T Variant<std::tuple<Types...>>::get_child(gsize index) const
-{
-  Variant<T> entry;
-  VariantContainerBase::get_child(entry, index);
-  return entry.get();
-}
-
-template <class... Types>
-template <class T>
-Variant<T> Variant<std::tuple<Types...>>::get_child_variant(gsize index) const
-{
-  Variant<T> entry;
-  VariantContainerBase::get_child(entry, index);
-  return entry;
-}
-
-namespace detail
-{
-// swallows any argument
-template <class T>
-constexpr int any_arg(T&& arg)
-{
-  (void)arg;
-  return 0;
-}
-
-template <class Tuple, std::size_t... Is>
-void assign_tuple(std::vector<VariantBase> &variants, Tuple & t, std::index_sequence<Is...>)
-{
-  int i = 0;
-  using swallow = int[]; // ensures left to right order
-  (void)swallow {(any_arg(std::get<Is>(t) = VariantBase::cast_dynamic<Variant<typename std::tuple_element<Is, Tuple>::type > >(variants[i++]).get()))...};
-}
-} // namespace detail
-
-template <class... Types>
-std::tuple<Types...> Variant<std::tuple<Types...>>::get() const
-{
-  std::tuple<Types...> data;
-  int i = 0;
-
-  std::vector<VariantBase> variants;
-  using swallow = int[]; // ensures left to right order
-  auto expander = [&variants, &i](const VariantBase &variant) -> int
-  {
-    variants.push_back(variant);
-    return i++;
-  };
-  swallow{(expander(get_child_variant<Types>(i)))...};
-  detail::assign_tuple(variants, data, std::index_sequence_for<Types...>{});
-
-  return data;
-}
-
-template< class... Types>
-VariantIter Variant<std::tuple<Types...>>::get_iter() const
-{
-  const auto type = variant_type();
-  return VariantContainerBase::get_iter(type);
-}
-
 } // namespace Glib
index d4032c1..8274c93 100644 (file)
@@ -122,17 +122,4 @@ VariantType::get_string() const
 {
   return std::string(g_variant_type_peek_string(gobj()), g_variant_type_get_string_length(gobj()));
 }
-
-std::vector<VariantType> VariantType::get_item_types() const
-{
-  std::vector<VariantType> result;
-  auto next_item_type = g_variant_type_first(gobj());
-  while (next_item_type)
-  {
-    result.emplace_back(const_cast<GVariantType*>(next_item_type), true);
-    next_item_type = g_variant_type_next(next_item_type);
-  }
-  return result;
 }
-
-} // namespace GLib
index 509eaa6..19327ab 100644 (file)
@@ -162,31 +162,15 @@ public:
   _WRAP_METHOD(bool is_subtype_of(const VariantType& supertype) const, g_variant_type_is_subtype_of)
 
 // It's necessary to take an extra reference of the 'const GVariantType*'
-// returned by g_variant_type_element(), g_variant_type_key() and
-// g_variant_type_value() because they don't do that already.
+// returned by g_variant_type_element() because it doesn't do that already.
 #m4 _CONVERSION(`const GVariantType*',`VariantType',`Glib::wrap(const_cast<GVariantType*>($3), true)')
   _WRAP_METHOD(VariantType element() const, g_variant_type_element)
+  _WRAP_METHOD(VariantType first() const, g_variant_type_first)
+  _WRAP_METHOD(VariantType next () const, g_variant_type_next)
   _WRAP_METHOD(gsize n_items() const, g_variant_type_n_items)
   _WRAP_METHOD(VariantType key() const, g_variant_type_key)
   _WRAP_METHOD(VariantType value() const, g_variant_type_value)
 
-  /** Determines the item types of a tuple or dictionary entry type.
-   *
-   * This function may only be used with tuple or dictionary entry types,
-   * but must not be used with the generic tuple type VARIANT_TYPE_TUPLE.
-   *
-   * In the case of a dictionary entry type, returns a vector with
-   * 2 elements, the type of the key followed by the value type.
-   *
-   * An empty vector is returned in case of this %VariantType being VARIANT_TYPE_UNIT.
-   *
-   * @newin{2,52}
-   *
-   * @return The item types of this %VariantType, or an empty vector.
-   */
-  std::vector<VariantType> get_item_types() const;
-  _IGNORE(g_variant_type_first, g_variant_type_next)
-
   // This function is part of unexposed API in gvarianttypeinfo.{h,c} for an
   // also unexposed GVariantTypeInfo structure of glib.
   _IGNORE(g_variant_type_info_get)
index bbe85ae..2cb35ab 100644 (file)
@@ -22,7 +22,6 @@ check_PROGRAMS =                              \
        giomm_ioerror_and_iodbuserror/test      \
        giomm_memoryinputstream/test                    \
        giomm_simple/test                       \
-  giomm_stream_vfuncs/test \
        giomm_asyncresult_sourceobject/test     \
        giomm_tls_client/test                   \
        giomm_listmodel/test \
@@ -39,6 +38,7 @@ check_PROGRAMS =                              \
        glibmm_ustring_compose/test             \
        glibmm_ustring_format/test              \
        glibmm_value/test                       \
+       glibmm_valuearray/test                  \
        glibmm_variant/test                     \
        glibmm_vector/test                      \
        glibmm_bool_vector/test                 \
@@ -56,9 +56,8 @@ glibmm_includes = -I$(top_builddir)/glib $(if $(srcdir:.=),-I$(top_srcdir)/glib)
 giomm_includes  = -I$(top_builddir)/gio $(if $(srcdir:.=),-I$(top_srcdir)/gio)
 local_cppflags  = -I$(top_builddir) $(glibmm_includes) $(giomm_includes)
 
-cxxflags_disable_deprecated = $(GLIBMM_WXXFLAGS) -DGLIBMM_DISABLE_DEPRECATED -DGIOMM_DISABLE_DEPRECATED
 AM_CPPFLAGS = $(local_cppflags) $(GIOMM_CFLAGS)
-AM_CXXFLAGS = $(GLIBMM_WXXFLAGS) $(cxxflags_disable_deprecated)
+AM_CXXFLAGS = $(GLIBMM_WXXFLAGS) -DGLIBMM_DISABLE_DEPRECATED -DGIOMM_DISABLE_DEPRECATED
 
 
 local_libglibmm = $(top_builddir)/glib/glibmm/libglibmm-$(GLIBMM_API_VERSION).la
@@ -79,9 +78,6 @@ giomm_memoryinputstream_test_LDADD   = $(giomm_ldadd)
 giomm_simple_test_SOURCES  = giomm_simple/main.cc
 giomm_simple_test_LDADD    = $(giomm_ldadd)
 
-giomm_stream_vfuncs_test_SOURCES = giomm_stream_vfuncs/main.cc
-giomm_stream_vfuncs_test_LDADD   = $(giomm_ldadd)
-
 giomm_asyncresult_sourceobject_test_SOURCES  = giomm_asyncresult_sourceobject/main.cc
 giomm_asyncresult_sourceobject_test_LDADD    = $(giomm_ldadd)
 
@@ -100,8 +96,6 @@ glibmm_interface_implementation_test_SOURCES = glibmm_interface_implementation/m
 glibmm_interface_implementation_test_LDADD = $(giomm_ldadd)
 
 glibmm_interface_move_test_SOURCES       = glibmm_interface_move/main.cc
-glibmm_interface_move_test_CXXFLAGS = $(GLIBMM_INTERFACE_TEST_WXXFLAGS) $(cxxflags_disable_deprecated)
-
 glibmm_mainloop_test_SOURCES             = glibmm_mainloop/main.cc
 glibmm_nodetree_test_SOURCES             = glibmm_nodetree/main.cc
 glibmm_object_move_test_SOURCES          = glibmm_object_move/main.cc
@@ -109,6 +103,7 @@ glibmm_objectbase_move_test_SOURCES      = glibmm_objectbase_move/main.cc
 glibmm_ustring_compose_test_SOURCES      = glibmm_ustring_compose/main.cc
 glibmm_ustring_format_test_SOURCES       = glibmm_ustring_format/main.cc
 glibmm_value_test_SOURCES                = glibmm_value/glibmm_value.cc glibmm_value/main.cc
+glibmm_valuearray_test_SOURCES           = glibmm_valuearray/main.cc
 glibmm_variant_test_SOURCES              = glibmm_variant/main.cc
 glibmm_vector_test_SOURCES               = glibmm_vector/main.cc
 glibmm_vector_test_LDADD                 = $(giomm_ldadd)
index 1016b58..f40a943 100644 (file)
@@ -255,7 +255,7 @@ void test_store_sorted1()
 class MyObject : public Glib::Object
 {
 protected:
-  explicit MyObject(int id) : m_id(id) {}
+  MyObject(int id) : m_id(id) {}
 
 public:
   static Glib::RefPtr<MyObject> create(int id)
diff --git a/tests/giomm_stream_vfuncs/main.cc b/tests/giomm_stream_vfuncs/main.cc
deleted file mode 100644 (file)
index 7284ebb..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/* Copyright (C) 2016 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.h>
-#include <iostream>
-#include <string>
-#include <cstdlib>
-
-// A simple custom stream that base64 encodes data.
-// Do not copy it to your code, because it's very slow.
-class Base64OutputStream : public Gio::FilterOutputStream
-{
-public:
-  unsigned get_column_width() const { return column_width; }
-  void set_column_width(unsigned cw) { column_width = cw; }
-  static Glib::RefPtr<Base64OutputStream> create(const Glib::RefPtr<OutputStream>& base_stream)
-  {
-    return Glib::RefPtr<Base64OutputStream>(new Base64OutputStream(base_stream));
-  }
-
-protected:
-  explicit Base64OutputStream(const Glib::RefPtr<Gio::OutputStream>& base_stream)
-    : Gio::FilterOutputStream(base_stream), column(0), bit_count(0), bit_buffer(0), column_width(72) {}
-
-  gssize write_vfunc(const void* buffer, gsize count, const Glib::RefPtr<Gio::Cancellable>& cancellable) override
-  {
-    char const *byte = (char const *) buffer;
-    for (unsigned i = 0; i < count; ++i, ++byte)
-    {
-      // kindergarten implementation, because the object is not performance :)
-      bit_buffer <<= 8;
-      bit_buffer |= (*byte & 0xff);
-      bit_count += 8;
-
-      if (bit_count == 24)
-      {
-        clear_pending(); // TODO why is this necessary to avoid an outstanding op. exception?
-        flush(cancellable);
-        set_pending();
-        bit_count = 0;
-      }
-
-      if (cancellable && cancellable->is_cancelled())
-        throw Gio::Error(Gio::Error::CANCELLED, "Operation cancelled");
-    }
-    return count;
-  }
-
-  bool flush_vfunc(const Glib::RefPtr<Gio::Cancellable>& cancellable) override
-  {
-    if (bit_count != 24)
-      return true;
-    char to_write[5];
-    gsize len = 4;
-
-    for (unsigned i=0; i<4; ++i)
-    {
-      unsigned index = (bit_buffer & (0x3f<<(i*6))) >> (i*6);
-      to_write[3-i] = base64_encode_str[index];
-    }
-    column += 4;
-    // Yes, I know this is completely wrong.
-    if (column >= column_width)
-    {
-      column = 0;
-      to_write[4] = '\n';
-      ++len;
-    }
-
-    get_base_stream()->write(&to_write, len, cancellable);
-
-    bit_count = 0;
-    bit_buffer = 0;
-
-    return true;
-  }
-
-  bool close_vfunc(const Glib::RefPtr<Gio::Cancellable>& cancellable) override
-  {
-    char to_write[5] = "====";
-    //get any last bytes (1 or 2) out of the buffer
-    switch (bit_count)
-    {
-    case 16:
-      bit_buffer <<= 2;  //pad to make 18 bits
-      to_write[0] = base64_encode_str[(bit_buffer & (0x3f << 12)) >> 12];
-      to_write[1] = base64_encode_str[(bit_buffer & (0x3f << 6)) >> 6];
-      to_write[2] = base64_encode_str[bit_buffer & 0x3f];
-      break;
-
-    case 8:
-      bit_buffer <<= 4; //pad to make 12 bits
-      to_write[0] = base64_encode_str[(bit_buffer & (0x3f << 6)) >> 6];
-      to_write[1] = base64_encode_str[bit_buffer & 0x3f];
-      break;
-    }
-
-    if (bit_count > 0)
-    {
-      get_base_stream()->write(&to_write, 5, cancellable);
-    }
-    else
-    {
-      // null terminate output
-      get_base_stream()->write("", 1, cancellable);
-    }
-    if (get_close_base_stream())
-      get_base_stream()->close(cancellable);
-
-    return true;
-  }
-
-private:
-  static char const *const base64_encode_str;
-  unsigned column;
-  unsigned bit_count;
-  unsigned bit_buffer;
-  unsigned column_width;
-};
-
-char const *const Base64OutputStream::base64_encode_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-int main(int, char**)
-{
-  Glib::init();
-  Gio::init();
-
-  try
-  {
-    char result[256];
-    Glib::RefPtr<Gio::MemoryOutputStream> memory_chunk = Gio::MemoryOutputStream::create(result, 256, nullptr, nullptr);
-    Glib::RefPtr<Base64OutputStream> base64 = Base64OutputStream::create(memory_chunk);
-
-    std::string data = "Custom GIO streams are cool!";
-
-    base64->set_close_base_stream(true);
-    base64->write(data);
-    base64->close();
-
-    const std::string base64_should_be("Q3VzdG9tIEdJTyBzdHJlYW1zIGFyZSBjb29sIQ==");
-    std::cout << "Original data:       " << data << std::endl;
-    std::cout << "base64-encoded data: " << result << std::endl;
-    std::cout << "base64 should be:    " << base64_should_be << std::endl;
-    if (base64_should_be != result)
-    {
-      std::cout << "Not correct!" << std::endl;
-      return EXIT_FAILURE;
-    }
-  }
-  catch (Gio::Error e)
-  {
-    std::cout << "Gio error: " << e.what() << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  return EXIT_SUCCESS;
-}
index 16fa72a..c097cbb 100644 (file)
@@ -109,7 +109,7 @@ class TestInterface : public Glib::Interface
 protected:
   using CppClassType = TestInterface_Class;
 
-  TestInterface() : Glib::Interface(derived_interface_class_.init()), i_(0) {}
+  TestInterface() : Glib::Interface(derived_interface_class_.init()) {}
 
 public:
   // A real application would never make the constructor public.
@@ -187,7 +187,7 @@ public:
 
   // A real application would never make the constructor public.
   // It would instead have a protected constructor and a public create() method.
-  explicit DerivedObject(int i)
+  DerivedObject(int i)
   : Glib::ObjectBase(nullptr),
     Glib::Object(Glib::ConstructParams(derived_object_class_.init())),
     i_(i)
index c4033de..0554c48 100644 (file)
@@ -14,6 +14,7 @@ node_build_string(type_nodetree_string& node, std::string& string)
 int
 main()
 {
+  std::list<std::string> alma;
   std::string tstring, cstring;
   type_nodetree_string* root;
   type_nodetree_string* node;
diff --git a/tests/glibmm_valuearray/main.cc b/tests/glibmm_valuearray/main.cc
new file mode 100644 (file)
index 0000000..b9fc12a
--- /dev/null
@@ -0,0 +1,102 @@
+// Glib::ValueArray is deprecated, but let's keep the test.
+// The recommended replacement is std::vector<> which requires no test here.
+#undef GLIBMM_DISABLE_DEPRECATED
+
+#include <glibmm.h>
+#include <iostream>
+
+#ifdef GLIBMM_DISABLE_DEPRECATED
+int
+main(int, char**)
+{
+  // If glibmm is configured with --disable-deprecated-api, GLIBMM_DISABLE_DEPRECATED
+  // is defined in glibmm.h (actually in glibmmconfig.h). The undef at the start of
+  // this file has no effect.
+  return 77; // Tell automake's test harness to skip this test.
+}
+
+#else
+
+// Use this line if you want debug output:
+// std::ostream& ostr = std::cout;
+
+// This seems nicer and more useful than putting an ifdef around the use of ostr:
+std::stringstream debug;
+std::ostream& ostr = debug;
+
+int
+on_compare(const Glib::ValueBase& v1, const Glib::ValueBase& v2)
+{
+  const Glib::Value<int>& intVal1 = static_cast<const Glib::Value<int>&>(v1);
+  const Glib::Value<int>& intVal2 = static_cast<const Glib::Value<int>&>(v2);
+
+  int int1 = intVal1.get();
+  int int2 = intVal2.get();
+
+  if (int1 < int2)
+    return -1;
+  else if (int1 == int2)
+    return EXIT_SUCCESS;
+  else
+    return 1;
+}
+
+int
+main(int, char**)
+{
+  const int VALUES_COUNT = 10;
+
+  Glib::init();
+
+  Glib::Value<int> values[VALUES_COUNT];
+  Glib::ValueArray array;
+
+  for (int i = 0; i < VALUES_COUNT; i++)
+  {
+    values[i].init(Glib::Value<int>::value_type());
+    values[i].set(i + 1); //  (i + 1) ==> Set to natural counting numbers.
+    array.prepend(values[i]);
+  }
+
+  ostr << "Array members before sorting:" << std::endl;
+
+  for (int i = 0; i < VALUES_COUNT; i++)
+  {
+    Glib::ValueBase value;
+
+    if (!array.get_nth(i, value))
+    {
+      std::cerr << "Error getting element " << i << " of value array." << std::endl;
+      return EXIT_FAILURE;
+      break;
+    }
+
+    auto int_val = static_cast<Glib::Value<int>&>(value);
+    ostr << int_val.get() << " ";
+  }
+  ostr << std::endl; // End of line for list of array elements.
+
+  // Sort array and remove last element:
+  array.sort(sigc::ptr_fun(&on_compare)).remove(VALUES_COUNT - 1);
+
+  ostr << "Array members after sorting without last element:" << std::endl;
+
+  for (int i = 0; i < VALUES_COUNT - 1; i++)
+  {
+    Glib::ValueBase value;
+
+    if (!array.get_nth(i, value))
+    {
+      std::cerr << "Error getting element " << i << " of value array." << std::endl;
+      return EXIT_FAILURE;
+      break;
+    }
+
+    auto int_val = static_cast<Glib::Value<int>&>(value);
+    ostr << int_val.get() << " ";
+  }
+  ostr << std::endl; // End of line for list of array elements.
+
+  return EXIT_SUCCESS;
+}
+#endif // GLIBMM_DISABLE_DEPRECATED
index 4d3c2c7..8ac5d50 100644 (file)
@@ -11,70 +11,6 @@ std::ostream& ostr = debug;
 static void test_variant_floating();
 static void test_dynamic_cast();
 
-namespace
-{
-
-int test_tuple()
-{
-  using TupleType = std::tuple<guint16, Glib::ustring, bool>;
-  using MapType = std::map<guint16, TupleType>;
-  bool result_ok = true;
-
-  // First tuple
-  const guint16 q1 = 2;
-  const Glib::ustring s1 = "Hi there";
-  const bool b1 = false;
-  auto t1 = std::make_tuple(q1, s1, b1);
-  auto tuple1_variant = Glib::Variant<TupleType>::create(t1);
-
-  // Second tuple
-  const guint16 q2 = 3;
-  const Glib::ustring s2 = "Hello";
-  const bool b2 = true;
-  auto t2 = std::make_tuple(q2, s2, b2);
-  auto tuple2_variant = Glib::Variant<TupleType>::create(t2);
-
-  // Insert the tuples in a map.
-  MapType m;
-  m[4] = t1;
-  m[5] = t2;
-  auto map_variant = Glib::Variant<MapType>::create(m);
-
-  std::string type_string = tuple1_variant.variant_type().get_string();
-  ostr << "Type string of tuple1: " << type_string << std::endl;
-  result_ok &= type_string == "(qsb)";
-
-  type_string = tuple2_variant.get_type_string();
-  ostr << "Type string of tuple2: " << type_string << std::endl;
-  result_ok &= type_string == "(qsb)";
-
-  type_string = map_variant.variant_type().get_string();
-  ostr << "Type string of map of tuples: " << type_string << std::endl;
-  result_ok &= map_variant.get_type_string() == "a{q(qsb)}";
-
-  // Extract from the map of tuples.
-  std::pair<guint16, TupleType> child0 = map_variant.get_child(0);
-  ostr << "Index of first map entry: " << child0.first << std::endl;
-  result_ok &= child0.first == 4;
-  auto extracted_tuple = child0.second;
-  auto q3 = std::get<guint16>(extracted_tuple);
-  auto s3 = std::get<Glib::ustring>(extracted_tuple);
-  auto b3 = std::get<bool>(extracted_tuple);
-  ostr << "Extracted tuple1 from map: (" << q3 << ", " << s3 << ", " << b3 << ")" << std::endl;
-  result_ok &= q3 == q1 && s3 == s1 && b3 == b1;
-
-  // Extract from a tuple.
-  auto q4 = tuple2_variant.get_child<guint16>(0);
-  auto s4 = tuple2_variant.get_child_variant<Glib::ustring>(1).get();
-  auto b4 = std::get<bool>(tuple2_variant.get());
-  ostr << "Extracted tuple2: (" << q4 << ", " << s4 << ", " << b4 << ")" << std::endl;
-  result_ok &= q4 == q2 && s4 == s2 && b4 == b2;
-
-  return result_ok ? EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-} // anonymous namespace
-
 int
 main(int, char**)
 {
@@ -227,7 +163,7 @@ main(int, char**)
   test_variant_floating();
   test_dynamic_cast();
 
-  return test_tuple();
+  return EXIT_SUCCESS;
 }
 
 // Test casting of multiple types to a ustring:
@@ -465,7 +401,7 @@ get_log_flags()
 
 struct WarnCatcher
 {
-  explicit WarnCatcher(const std::string& domain)
+  WarnCatcher(const std::string& domain)
   : m_domain(domain), m_old_flags(g_log_set_fatal_mask(m_domain.c_str(), get_log_flags()))
   {
   }
index e0f6818..af53de8 100644 (file)
@@ -34,16 +34,16 @@ dist_noinst_DATA    = README TODO
 dist_noinst_SCRIPTS = enum.pl
 
 noinst_PROGRAMS = extra_defs_gen/generate_defs_glib extra_defs_gen/generate_defs_gio
-lib_LTLIBRARIES = extra_defs_gen/libglibmm_generate_extra_defs-2.52.la
+lib_LTLIBRARIES = extra_defs_gen/libglibmm_generate_extra_defs-2.4.la
 
 extradefs_includedir      = $(includedir)/$(GLIBMM_MODULE_NAME)/glibmm_generate_extra_defs
 extradefs_include_HEADERS = extra_defs_gen/generate_extra_defs.h
 
 extradefs_ldflags = -no-undefined -version-info $(LIBGLIBMM_SO_VERSION)
 
-extra_defs_gen_libglibmm_generate_extra_defs_2_52_la_SOURCES = extra_defs_gen/generate_extra_defs.cc
-extra_defs_gen_libglibmm_generate_extra_defs_2_52_la_LDFLAGS = $(extradefs_ldflags)
-extra_defs_gen_libglibmm_generate_extra_defs_2_52_la_LIBADD  = $(GLIBMM_LIBS)
+extra_defs_gen_libglibmm_generate_extra_defs_2_4_la_SOURCES = extra_defs_gen/generate_extra_defs.cc
+extra_defs_gen_libglibmm_generate_extra_defs_2_4_la_LDFLAGS = $(extradefs_ldflags)
+extra_defs_gen_libglibmm_generate_extra_defs_2_4_la_LIBADD  = $(GLIBMM_LIBS)
 
 extra_defs_gen_generate_defs_glib_SOURCES = extra_defs_gen/generate_defs_glib.cc
 extra_defs_gen_generate_defs_glib_LDADD   = $(GLIBMM_LIBS) $(lib_LTLIBRARIES)
index 3ff1c4b..e6f7cb4 100644 (file)
@@ -229,7 +229,7 @@ _CONVERSION(`const Glib::RefPtr<MenuModel>&',`GMenuModel*',__CONVERT_CONST_REFPT
 
 # MenuItem
 _CONVERSION(`GMenuItem*',`Glib::RefPtr<MenuItem>',`Glib::wrap($3)')
-_CONVERSION(`const Glib::RefPtr<const MenuItem>&',`GMenuItem*',__CONVERT_CONST_REFPTR_TO_P)
+_CONVERSION(`const Glib::RefPtr<MenuItem>&',`GMenuItem*',__CONVERT_CONST_REFPTR_TO_P)
 
 # Mount
 _CONVERSION(`GMount*',`Glib::RefPtr<Mount>',`Glib::wrap($3)')
index fa2cd99..5b680f4 100644 (file)
@@ -24,17 +24,17 @@ ifelse(`$9',,,`_DEPRECATE_IFDEF_START
 ')dnl
 ifelse($13,,`dnl no detail_name
 $10
-  Glib::SignalProxy<$5`'($6)> signal_$4`'();
+  Glib::SignalProxy< $5`'_COMMA_PREFIX($6) > signal_$4`'();
 ',dnl detail_name
 $14,0,`dnl
 $10
-  Glib::SignalProxyDetailed<$5`'($6)> signal_$4`'(const Glib::ustring& $13 = Glib::ustring());
+  Glib::SignalProxyDetailedAnyType< $5`'_COMMA_PREFIX($6) > signal_$4`'(const Glib::ustring& $13 = Glib::ustring());
 ',`dnl detail_name and two_signal_methods
 $10
-  Glib::SignalProxy<$5`'($6)> signal_$4`'();
+  Glib::SignalProxy< $5`'_COMMA_PREFIX($6) > signal_$4`'();
 
 $10
-  Glib::SignalProxyDetailed<$5`'($6)> signal_$4`'(const Glib::ustring& $13);
+  Glib::SignalProxyDetailedAnyType< $5`'_COMMA_PREFIX($6) > signal_$4`'(const Glib::ustring& $13);
 ')dnl end detail_name
 ifelse(`$9',,,`_DEPRECATE_IFDEF_END
 ')dnl
@@ -65,7 +65,7 @@ ifelse($8,`1',,`dnl Do not generate the implementation if it should be custom:
 static $2 __CPPNAME__`'_signal_$4_callback`'(__CNAME__`'* self, _COMMA_SUFFIX($3)`'void* data)
 {
   using namespace __NAMESPACE__;
-  using SlotType = sigc::slot<$5`'($6)>;
+  using SlotType = sigc::slot< $5`'_COMMA_PREFIX($6) >;
 
   auto obj = dynamic_cast<__CPPNAME__*>(Glib::ObjectBase::_get_current_wrapper((GObject*) self));
   // Do not try to call a signal on a disassociated wrapper.
@@ -107,7 +107,7 @@ ifelse($2,void,,`dnl else
 static $2 __CPPNAME__`'_signal_$4_notify_callback`'(__CNAME__`'* self, _COMMA_SUFFIX($3)`' void* data)
 {
   using namespace __NAMESPACE__;
-  using SlotType = sigc::slot<void($6)>;
+  using SlotType = sigc::slot< void`'_COMMA_PREFIX($6) >;
 
   auto obj = dynamic_cast<__CPPNAME__*>(Glib::ObjectBase::_get_current_wrapper((GObject*) self));
   // Do not try to call a signal on a disassociated wrapper.
@@ -161,25 +161,25 @@ ifelse(`$11',,,`#ifdef $11'
 ifelse(`$9',,,`_DEPRECATE_IFDEF_START
 ')dnl
 ifelse($13,,`dnl no detail_name
-Glib::SignalProxy<$5`'($6)> __CPPNAME__::signal_$4`'()
+Glib::SignalProxy< $5`'_COMMA_PREFIX($6) > __CPPNAME__::signal_$4`'()
 {
-  return Glib::SignalProxy<$5`'($6) >(this, &__CPPNAME__`'_signal_$4_info);
+  return Glib::SignalProxy< $5`'_COMMA_PREFIX($6) >(this, &__CPPNAME__`'_signal_$4_info);
 }
 ',dnl detail_name
 $14,0,`dnl
-Glib::SignalProxyDetailed<$5`'($6)> __CPPNAME__::signal_$4`'(const Glib::ustring& $13)
+Glib::SignalProxyDetailedAnyType< $5`'_COMMA_PREFIX($6) > __CPPNAME__::signal_$4`'(const Glib::ustring& $13)
 {
-  return Glib::SignalProxyDetailed<$5`'($6)>(this, &__CPPNAME__`'_signal_$4_info, $13);
+  return Glib::SignalProxyDetailedAnyType< $5`'_COMMA_PREFIX($6) >(this, &__CPPNAME__`'_signal_$4_info, $13);
 }
 ',`dnl detail_name and two_signal_methods
-Glib::SignalProxy<$5`'($6)> __CPPNAME__::signal_$4`'()
+Glib::SignalProxy< $5`'_COMMA_PREFIX($6) > __CPPNAME__::signal_$4`'()
 {
-  return Glib::SignalProxy<$5`'($6)>(this, &__CPPNAME__`'_signal_$4_info);
+  return Glib::SignalProxy< $5`'_COMMA_PREFIX($6) >(this, &__CPPNAME__`'_signal_$4_info);
 }
 
-Glib::SignalProxyDetailed<$5`'($6)> __CPPNAME__::signal_$4`'(const Glib::ustring& $13)
+Glib::SignalProxyDetailedAnyType< $5`'_COMMA_PREFIX($6) > __CPPNAME__::signal_$4`'(const Glib::ustring& $13)
 {
-  return Glib::SignalProxyDetailed<$5`'($6)>(this, &__CPPNAME__`'_signal_$4_info, $13);
+  return Glib::SignalProxyDetailedAnyType< $5`'_COMMA_PREFIX($6) >(this, &__CPPNAME__`'_signal_$4_info, $13);
 }
 ')dnl end detail_name
 ifelse(`$9',,,`_DEPRECATE_IFDEF_END
index 1c9e274..150ada4 100755 (executable)
@@ -5,9 +5,9 @@
 # files that it depends on.
 
 # Example: In glibmm, go to directory glibmm, and run
-#   tools/test_scripts/testheaders.sh -I glib glibmm-2.52 gio # compile glibmm/gio/giomm/*.h
-#   tools/test_scripts/testheaders.sh glibmm-2.52 glib gio    # compile glibmm/glib/glibmm/*.h and glibmm/gio/giomm/*.h
-#   tools/test_scripts/testheaders.sh -I glib -I gio glibmm-2.52 glib/glibmm/ustring.h # compile glibmm/glib/glibmm/ustring.h
+#   tools/test_scripts/testheaders.sh -I glib glibmm-2.4 gio # compile glibmm/gio/giomm/*.h
+#   tools/test_scripts/testheaders.sh glibmm-2.4 glib gio    # compile glibmm/glib/glibmm/*.h and glibmm/gio/giomm/*.h
+#   tools/test_scripts/testheaders.sh -I glib -I gio glibmm-2.4 glib/glibmm/ustring.h # compile glibmm/glib/glibmm/ustring.h
 
 # Usage: testheaders.sh [-I<dir>]... <pkg> [<dir> | <file>]...
 # -I<dir> is added to the g++ command.