+2.47.4:
+
+Glib::
+* ustring: Don't allow comparison to 0.
+ (Kjell Ahlstedt) Bug #572978 (Armin Burgmeier)
+
+Gio:
+* ActionMap: Fix the ref count in lookup_action_vfunc().
+ (Kjell Ahlstedt) Bug #758813 (Aurimas Černius)
+
+Build:
+* Dispatcher: #include <mutex> in Windows builds.
+ (T Sailor) Bug #758894
+* Gio::Application: Destructor: Use noexcept in the implementation too.
+ (Murray Cumming) Bug #758798 (Émeric MASCHINO)
+* Fix the build with --disable-deprecated-api.
+ (Kjell Ahlstedt)
+
+2.47.3.1:
+
+* Use thread_local instead of (deprecated) Glib::Threads::Private.
+ (Murray Cumming, Kjell Ahlstedt)
+
2.47.3:
* Deprecate all of Glib::Threads, including Mutex, Lock, Thread, etc.
-* Deprecated Glib::ThreadPool
+* Deprecated Glib::ThreadPool.
+ (Murray Cumming, Kjell Ahlstedt)
+
2.46.2:
* ObjectBase, Object, Interface: Correct move constructors and move assignment
## 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.47.3],
+AC_INIT([glibmm], [2.47.4],
[http://bugzilla.gnome.org/enter_bug.cgi?product=glibmm],
[glibmm], [http://www.gtkmm.org/])
AC_PREREQ([2.59])
AC_DEFINE([GIOMM_STATIC_LIB], [1], [Define if giomm is built as a static library])
])
-glibreq='2.0 >= 2.46.0'
+glibreq='2.0 >= 2.47.4'
GLIBMM_MODULES="sigc++-2.0 >= 2.6.0 glib-$glibreq gobject-$glibreq gmodule-$glibreq"
GIOMM_MODULES="$GLIBMM_MODULES gio-$glibreq"
#include <giomm.h>
#include <glibmm.h>
#include <thread>
+#include <mutex>
+#include <condition_variable>
+#include <chrono>
+#include <memory>
#include <iostream>
namespace
bool use_source = false;
bool use_ipv6 = false;
int cancel_timeout = 0;
+bool stop_thread = false;
+std::mutex mutex_thread;
+std::condition_variable cond_thread;
class ClientOptionGroup : public Glib::OptionGroup
{
static void
cancel_thread (Glib::RefPtr<Gio::Cancellable> cancellable)
{
- g_usleep (1000*1000*cancel_timeout);
+ std::unique_lock<std::mutex> lock(mutex_thread);
+ if (!cond_thread.wait_for(lock, std::chrono::seconds(cancel_timeout),
+ [](){ return stop_thread; }))
+ {
+ // !stop_thread, i.e. timeout
std::cout << "Cancelling\n";
- cancellable->cancel ();
+ cancellable->cancel();
+ }
}
+class JoinAndDelete
+{
+public:
+ void operator()(std::thread* thread)
+ {
+ stop_thread = true;
+ cond_thread.notify_all();
+ thread->join();
+ delete thread;
+ }
+};
+
} // end anonymous namespace
int
return 1;
}
- std::thread* thread = nullptr;
+ std::unique_ptr<std::thread, JoinAndDelete> thread;
if (cancel_timeout)
{
cancellable = Gio::Cancellable::create ();
- thread = new std::thread(&cancel_thread, cancellable);
+ thread.reset(new std::thread(&cancel_thread, cancellable));
}
loop = Glib::MainLoop::create ();
return 1;
}
- //TODO: This won't happen if we returned earlier.
- if(thread)
- {
- thread->join();
- delete thread;
- }
-
return 0;
}
-#include <thread>
-#include <iostream>
#include <giomm.h>
#include <glibmm.h>
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#include <chrono>
+#include <memory>
+#include <iostream>
namespace
{
bool use_source = false;
bool use_ipv6 = false;
int cancel_timeout = 0;
+bool stop_thread = false;
+std::mutex mutex_thread;
+std::condition_variable cond_thread;
class ServerOptionGroup : public Glib::OptionGroup
{
static void
cancel_thread (Glib::RefPtr<Gio::Cancellable> cancellable)
{
- g_usleep (1000*1000*cancel_timeout);
+ std::unique_lock<std::mutex> lock(mutex_thread);
+ if (!cond_thread.wait_for(lock, std::chrono::seconds(cancel_timeout),
+ [](){ return stop_thread; }))
+ {
+ // !stop_thread, i.e. timeout
std::cout << "Cancelling\n";
- cancellable->cancel ();
+ cancellable->cancel();
+ }
}
+class JoinAndDelete
+{
+public:
+ void operator()(std::thread* thread)
+ {
+ stop_thread = true;
+ cond_thread.notify_all();
+ thread->join();
+ delete thread;
+ }
+};
+
} // end anonymous namespace
int
return 1;
}
- std::thread* thread = nullptr;
+ std::unique_ptr<std::thread, JoinAndDelete> thread;
if (cancel_timeout)
{
cancellable = Gio::Cancellable::create ();
- thread = new std::thread(&cancel_thread, cancellable);
+ thread.reset(new std::thread(&cancel_thread, cancellable));
}
loop = Glib::MainLoop::create ();
return 1;
}
-
- //TODO: This won't happen if we returned earlier.
- if(thread)
- {
- thread->join();
- delete thread;
- }
-
return 0;
}
//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
{
return 0;
}
-
+#endif //GLIBMM_DISABLE_DEPRECATED
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+_CONFIGINCLUDE(giommconfig.h)
+
#include <glibmm/interface.h>
#include <glibmm/varianttype.h>
#include <gio/gio.h>
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+_CONFIGINCLUDE(giommconfig.h)
+
#include <glibmm/interface.h>
#include <glibmm/varianttype.h>
#include <gio/gio.h> //To declare g_action_group_get_action_state_type().
-// -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-
/* Copyright (C) 2012 The giomm Development Team
*
* This library is free software; you can redistribute it and/or
_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")
+ _WRAP_VFUNC(Glib::RefPtr<Action> lookup_action(const Glib::ustring& name) const, "lookup_action", refreturn)
//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. )
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+_CONFIGINCLUDE(giommconfig.h)
+
#include <giomm/applaunchcontext.h>
#include <exception>
}
-Application::~Application()
+Application::~Application() noexcept
{
// Delete all OptionArgCallbackData instances that belong to this application.
std::lock_guard<std::mutex> lock(option_arg_callback_data_mutex);
-// -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-
/* Copyright (C) 2007 The giomm Development Team
*
* This library is free software; you can redistribute it and/or
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+_CONFIGINCLUDE(giommconfig.h)
+
#include <glibmm/interface.h>
#include <glibmm/object.h>
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+_CONFIGINCLUDE(giommconfig.h)
+
#include <giomm/inputstream.h>
#include <giomm/seekable.h>
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)
{
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+_CONFIGINCLUDE(giommconfig.h)
+
#include <glibmm/object.h>
#include <giomm/menumodel.h>
#include <giomm/icon.h>
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
+_CONFIGINCLUDE(giommconfig.h)
+
#include <glibmm/object.h>
#include <glibmm/ustring.h>
#include <glibmm/variant.h>
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+_CONFIGINCLUDE(giommconfig.h)
+
#include <giomm/socketaddress.h>
_DEFS(giomm,gio)
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <glibmm/threads.h>
#include <glibmm/dispatcher.h>
#include <glibmm/exceptionhandler.h>
#include <glibmm/fileutils.h>
# include <io.h>
# include <direct.h>
# include <list>
+# include <mutex>
#else
# include <unistd.h>
#endif
explicit DispatchNotifier(const Glib::RefPtr<MainContext>& context);
private:
- static Glib::Threads::Private<DispatchNotifier> thread_specific_instance_;
+ static thread_local DispatchNotifier* thread_specific_instance_;
std::set<const Dispatcher*> deleted_dispatchers_;
/**** Glib::DispatchNotifier ***********************************************/
// static
-Glib::Threads::Private<DispatchNotifier> DispatchNotifier::thread_specific_instance_;
+thread_local DispatchNotifier* DispatchNotifier::thread_specific_instance_ = nullptr;
DispatchNotifier::DispatchNotifier(const Glib::RefPtr<MainContext>& context)
:
DispatchNotifier* DispatchNotifier::reference_instance
(const Glib::RefPtr<MainContext>& context, const Dispatcher* dispatcher)
{
- DispatchNotifier* instance = thread_specific_instance_.get();
+ DispatchNotifier* instance = thread_specific_instance_;
if(!instance)
{
instance = new DispatchNotifier(context);
- thread_specific_instance_.replace(instance);
+ thread_specific_instance_ = instance;
}
else
{
void DispatchNotifier::unreference_instance(
DispatchNotifier* notifier, const Dispatcher* dispatcher)
{
- DispatchNotifier* const instance = thread_specific_instance_.get();
+ DispatchNotifier* const instance = thread_specific_instance_;
// Yes, the notifier argument is only used to check for sanity.
g_return_if_fail(instance == notifier);
{
g_return_if_fail(instance->ref_count_ == 0); // could be < 0 if messed up
- // This causes deletion of the notifier object.
- thread_specific_instance_.replace(nullptr);
+ delete thread_specific_instance_;
+ thread_specific_instance_ = nullptr;
}
}
*/
#include <glibmmconfig.h>
-#include <glibmm/threads.h>
#include <glibmm/error.h>
#include <glibmm/exceptionhandler.h>
#include <glib.h>
// Each thread has its own list of exception handlers
// to avoid thread synchronization problems.
-static Glib::Threads::Private<HandlerList> thread_specific_handler_list;
+static thread_local HandlerList* thread_specific_handler_list = nullptr;
static void glibmm_exception_warning(const GError* error)
sigc::connection add_exception_handler(const sigc::slot<void>& slot)
{
- HandlerList* handler_list = thread_specific_handler_list.get();
+ HandlerList* handler_list = thread_specific_handler_list;
if(!handler_list)
{
handler_list = new HandlerList();
- thread_specific_handler_list.set(handler_list);
+ thread_specific_handler_list = handler_list;
}
handler_list->slots().push_front(slot);
// handled. If there are no more handlers in the list and the exception
// is still unhandled, call glibmm_unexpected_exception().
- if(HandlerList *const handler_list = thread_specific_handler_list.get())
+ if(HandlerList *const handler_list = thread_specific_handler_list)
{
HandlerList::iterator pslot = handler_list->slots().begin();
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#undef G_DISABLE_DEPRECATED //So we can use newly-deprecated API, to preserve our API.
-#define GLIB_DISABLE_DEPRECATION_WARNINGS 1
-
-#include <glibmm/threads.h>
+#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>
}
#ifndef GLIBMM_DISABLE_DEPRECATED
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
void Source::get_current_time(Glib::TimeVal& current_time)
{
g_source_get_current_time(gobject_, ¤t_time);
}
+G_GNUC_END_IGNORE_DEPRECATIONS
#endif //GLIBMM_DISABLE_DEPRECATED
gint64 Source::get_time() const
-// -*- c++ -*-
#ifndef _GLIBMM_MAIN_H
#define _GLIBMM_MAIN_H
#ifndef GLIBMM_DISABLE_DEPRECATED
class Cond;
class Mutex;
-#endif //GLIBMM_DISABLE_DEPRECATED
namespace Threads
{
class Cond;
class Mutex;
}
+#endif //GLIBMM_DISABLE_DEPRECATED
/** @defgroup MainLoop The Main Event Loop
* Manages all available sources of events.
-// -*- c++ -*-
#ifndef _GLIBMM_SARRAY_H
#define _GLIBMM_SARRAY_H
-/* $Id$ */
-
/* array.h
*
* Copyright (C) 2002 The gtkmm Development Team
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <glibmmconfig.h>
+
#ifndef GLIBMM_DISABLE_DEPRECATED
#include <glibmm/arrayhandle.h>
#include <glibmm/ustring.h>
#endif //GLIBMM_DISABLE_DEPRECATED
#endif // _GLIBMM_SARRAY_H
-
-// -*- c++ -*-
-
/* Copyright (C) 2002 The gtkmm Development Team
*
* This library is free software; you can redistribute it and/or
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <glibmmconfig.h>
#ifndef GLIBMM_DISABLE_DEPRECATED
-#include <glibmmconfig.h>
#include <glibmm/threadpool.h>
#include <glibmm/exceptionhandler.h>
#include <glibmm/threads.h>
-// -*- c++ -*-
#ifndef _GLIBMM_THREADPOOL_H
#define _GLIBMM_THREADPOOL_H
-/* $Id$ */
-
/* Copyright (C) 2002 The gtkmm Development Team
*
* This library is free software; you can redistribute it and/or
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <glibmmconfig.h>
+
#ifndef GLIBMM_DISABLE_DEPRECATED
#include <sigc++/sigc++.h>
inline bool operator>=(const char* lhs, const ustring& rhs)
{ return (rhs.compare(lhs) <= 0); }
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+// Don't allow implicit conversion of integer 0 to nullptr in the relational operators.
+// If the int versions of the relational operators are not deleted, attempts to
+// compare with other integer values than 0 can result in really unexpected behaviour.
+// See https://bugzilla.gnome.org/show_bug.cgi?id=572978#c10
+bool operator==(const ustring& lhs, int rhs) = delete;
+bool operator==(int lhs, const ustring& rhs) = delete;
+bool operator!=(const ustring& lhs, int rhs) = delete;
+bool operator!=(int lhs, const ustring& rhs) = delete;
+bool operator<(const ustring& lhs, int rhs) = delete;
+bool operator<(int lhs, const ustring& rhs) = delete;
+bool operator>(const ustring& lhs, int rhs) = delete;
+bool operator>(int lhs, const ustring& rhs) = delete;
+bool operator<=(const ustring& lhs, int rhs) = delete;
+bool operator<=(int lhs, const ustring& rhs) = delete;
+bool operator>=(const ustring& lhs, int rhs) = delete;
+bool operator>=(int lhs, const ustring& rhs) = delete;
+#endif // DOXYGEN_SHOULD_SKIP_THIS
/**** Glib::ustring -- concatenation operators *****************************/
regex.hg \
shell.hg \
spawn.hg \
+ thread.hg \
threads.hg \
timezone.hg \
unicode.hg \
uriutils.hg \
+ valuearray.hg \
variant.hg \
variantdict.hg \
variantiter.hg \
varianttype.hg
-glibmm_files_deprecated_hg = \
- thread.hg \
- valuearray.hg
-
-if DISABLE_DEPRECATED_API
+## Unconditionally used files,
+## deprecated files (even if configured with --disable-deprecated-api),
+## if there are architecture-specific files, only those for the present architecture.
glibmm_files_used_hg = $(glibmm_files_any_hg)
-else
-glibmm_files_used_hg = $(glibmm_files_any_hg) $(glibmm_files_deprecated_hg)
-endif
-glibmm_files_hg = $(glibmm_files_any_hg) $(glibmm_files_deprecated_hg)
+## All .hg files
+glibmm_files_hg = $(glibmm_files_any_hg)
glibmm_files_ccg = $(glibmm_files_hg:.hg=.ccg)
/** @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.
* @{
*/
_PUSH(SECTION_HEADER_FIRST)
#include <$1>
_POP()
+_PUSH()
+dnl Define this macro to be tested for later.
+define(`__FILENAME_CONFIGINCLUDE__',`$1')
+_POP()
')
dnl Start of processing
#endif // __DEPRECATION_GUARD__'
)
-dnl begin optional deprecation of whole class
+dnl begin optional deprecation of whole file
define(`_DEPRECATE_IFDEF_CLASS_START',`dnl
ifdef(`__BOOL_DEPRECATED__',`dnl
_DEPRECATE_IFDEF_START',`dnl
')
')
-dnl end optional deprecation of whole class
+dnl begin optional deprecation of whole file,
+dnl preceded by inclusion of config file
+dnl (the config file may define the __DEPRECATION_GUARD__)
+define(`_DEPRECATE_IFDEF_CLASS_CONFIG_START',`dnl
+ifdef(`__BOOL_DEPRECATED__',`dnl
+ifdef(`__FILENAME_CONFIGINCLUDE__',`dnl
+#include <__FILENAME_CONFIGINCLUDE__>',`dnl
+')
+_DEPRECATE_IFDEF_START',`dnl
+')
+')
+
+dnl end optional deprecation of whole file
define(`_DEPRECATE_IFDEF_CLASS_END',`dnl
ifdef(`__BOOL_DEPRECATED__',`dnl
_DEPRECATE_IFDEF_END',`dnl
m4_divert(0)dnl
#S 0 dnl Marks the beginning of the header file.
-// -*- c++ -*-
// Generated by gmmproc __GLIBMM_VERSION__ -- DO NOT MODIFY!
#ifndef __HEADER_GUARD__`'_H
#define __HEADER_GUARD__`'_H
#S 1 dnl Marks the beginning of the private header file.
-// -*- c++ -*-
// Generated by gmmproc __GLIBMM_VERSION__ -- DO NOT MODIFY!
#ifndef __HEADER_GUARD__`'_P_H
#define __HEADER_GUARD__`'_P_H
_IMPORT(SECTION_CC_PRE_INCLUDES)
-_DEPRECATE_IFDEF_CLASS_START
+_DEPRECATE_IFDEF_CLASS_CONFIG_START
#include <glibmm.h>