/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/
/examples/settings/gschemas.compiled
/examples/thread/dispatcher
/examples/thread/dispatcher2
+/examples/thread/thread
+/examples/thread/threadpool
# gio/
/gio/giomm-*.pc
/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
/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
-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:
* 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
## 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])
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,
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])
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"
# 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,
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
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)
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 = \
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
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
class JoinAndDelete
{
public:
- void operator()(std::thread* thread) const
+ void operator()(std::thread* thread)
{
stop_thread = true;
cond_thread.notify_all();
class JoinAndDelete
{
public:
- void operator()(std::thread* thread) const
+ void operator()(std::thread* thread)
{
stop_thread = true;
cond_thread.notify_all();
--- /dev/null
+
+#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;
+}
--- /dev/null
+
+#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
#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>
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 (...)
{
}
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)
{
* @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);
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)
_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
_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.
_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
_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.
*
}
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;
}
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
{
_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.
*
*/
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.
*
* @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
* 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
*/
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.
* 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.
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")
};
_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,
#include <giomm/init.h>
#include <cstring> // std::memset()
#include <map>
-#include <mutex>
#include <vector>
namespace // anonymous
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)
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++)
(*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);
}
*/
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
// _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)
_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);
_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")
_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
*
* @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.
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.
_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
+
_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
_CTOR_DEFAULT
public:
- using SlotCancelledCallback = sigc::slot<void()>;
+ using SlotCancelledCallback = sigc::slot<void>;
_WRAP_CREATE()
* @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
* Glib::ustring& signal_name, const Glib::VariantContainerBase& parameters);.
* @endcode
*/
- using SlotSignal = sigc::slot<void(const Glib::RefPtr<Connection>&,
+ using SlotSignal = sigc::slot<void, const 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,
* 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.
*
_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).
* @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
* @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
* @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.
* @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.
#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>
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:
* @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.
* @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
* @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.
* 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
_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)
_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)
/** 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.
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)
*
* @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.
/** 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.
+// -*- 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
_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)')
_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())')
_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)
_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)
_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),
_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)
+// -*- 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
_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)
};
permission.hg \
pollableinputstream.hg \
pollableoutputstream.hg \
- propertyaction.hg \
proxy.hg \
proxyaddress.hg \
proxyresolver.hg \
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
(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
_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
*
* @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,
*
* @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.
*
{
}
- SlotWithData(const SlotWithData& src) = delete;
- SlotWithData& operator=(const SlotWithData& src) = delete;
-
~SlotWithData() { delete m_slot; }
void operator()() { (*m_slot)(m_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)
{
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,
*
* @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.
*
_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)
_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)
_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)
};
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)
{
//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.
//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().
*
#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)
_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.
};
+// -*- 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
_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)
* 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
*
* @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")
_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)
_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
//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
//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
+++ /dev/null
-/* 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
+++ /dev/null
-/* 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
* 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
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
* 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)
#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
_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);
#include <gio/gio.h>
#include <glibmm/exceptionhandler.h>
#include <glibmm/vectorutils.h>
-#include <giomm/settingsschema.h>
namespace Gio
{
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
}
namespace Gio
{
-class SettingsSchema;
_WRAP_ENUM(SettingsBindFlags, GSettingsBindFlags)
_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)
_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)
_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.
_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)
_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)
_CONFIGINCLUDE(giommconfig.h)
#include <glibmm/variant.h>
-#include <glibmm/varianttype.h>
_DEFS(giomm,gio)
_PINCLUDE(glibmm/private/object_p.h)
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
_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)
_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
_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
};
+// -*- 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
#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
_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)
_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")
_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>)
_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)
_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)
*
* 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>
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
}
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);
// 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);
}
}
}
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);
+// -*- c++ -*-
#ifndef _GLIBMM_CLASS_H
#define _GLIBMM_CLASS_H
+/* $Id$ */
+
/* Copyright 2001 Free Software Foundation
* Copyright (C) 1998-2002 The gtkmm Development Team
*
#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
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
* @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_;
* 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>
#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
}
#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:
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
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
/**** 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
}
// 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
}
// 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)
{
}
#else /* !G_OS_WIN32 */
- DispatchNotifyData data(dispatcher_impl, this);
+ DispatchNotifyData data(dispatcher, this);
gssize n_written;
do
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
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.
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.
* 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>
// 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)
{
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);
// 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();
/** 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
+++ /dev/null
-/* 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
+++ /dev/null
-#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 */
error.cc \
exception.cc \
exceptionhandler.cc \
- extraclassinit.cc \
init.cc \
interface.cc \
main.cc \
signalproxy_connectionnode.cc \
streamiochannel.cc \
stringutils.cc \
+ threadpool.cc \
timer.cc \
timeval.cc \
ustring.cc \
error.h \
exception.h \
exceptionhandler.h \
- extraclassinit.h \
helperlist.h \
i18n-lib.h \
i18n.h \
slisthandle.h \
streamiochannel.h \
stringutils.h \
+ threadpool.h \
timer.h \
timeval.h \
ustring.h \
#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
+// -*- 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
{
/** 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, locale_name).
- * The "C" locale is the classic locale, set by std::setlocale(LC_ALL, "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, 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 */
}
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);
}
}
}
#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)
{
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();
slot_.set_parent(this, &SourceConnectionNode::notify);
}
-void
-SourceConnectionNode::notify(sigc::notifiable* data)
+void*
+SourceConnectionNode::notify(void* data)
{
SourceConnectionNode* const self = static_cast<SourceConnectionNode*>(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);
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;
}
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 (...)
{
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 (...)
{
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)
{
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 (...)
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 (...)
{
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);
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);
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 (...)
{
/* 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());
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_);
}
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_);
/* 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());
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_);
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_);
}
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());
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_);
}
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_);
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);
}
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);
}
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());
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_);
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()
{
}
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);
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
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_, ¤t_time);
+}
+G_GNUC_END_IGNORE_DEPRECATIONS
+#endif // GLIBMM_DISABLE_DEPRECATED
+
gint64
Source::get_time() const
{
// 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;
}
}
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);
}
sigc::connection
-TimeoutSource::connect(const sigc::slot<bool()>& slot)
+TimeoutSource::connect(const sigc::slot<bool>& slot)
{
return connect_generic(slot);
}
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);
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);
}
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_));
}
}
sigc::connection
-IdleSource::connect(const sigc::slot<bool()>& slot)
+IdleSource::connect(const sigc::slot<bool>& slot)
{
return connect_generic(slot);
}
bool
IdleSource::dispatch(sigc::slot_base* slot)
{
- return (*static_cast<sigc::slot<bool()>*>(slot))();
+ return (*static_cast<sigc::slot<bool>*>(slot))();
}
/**** Glib::IOSource *******************************************************/
}
sigc::connection
-IOSource::connect(const sigc::slot<bool(IOCondition)>& slot)
+IOSource::connect(const sigc::slot<bool, IOCondition>& slot)
{
return connect_generic(slot);
}
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
#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.
* @{
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:
* @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
* @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.
*
* @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.
* @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_;
* @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
* @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_;
* @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.
* @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:
* @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_;
*/
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
*
* @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().
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);
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);
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);
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();
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);
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);
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.
/**** 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),
}
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)
{
}
// 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
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.
}
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.
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)
{
#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" {
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
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
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
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);
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))();
}
}
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}
*/
*/
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}
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
}
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());
// 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_;
}
try
{
if (sigc::slot_base* const slot = data_to_slot(data))
- (*static_cast<sigc::slot<void()>*>(slot))();
+ (*static_cast<sigc::slot<void>*>(slot))();
}
catch (...)
{
}
}
-// SignalProxyDetailedBase implementation:
+// SignalProxyDetailed implementation:
-SignalProxyDetailedBase::SignalProxyDetailedBase(
+SignalProxyDetailed::SignalProxyDetailed(
Glib::ObjectBase* obj, const SignalProxyInfo* info, const Glib::ustring& detail_name)
: SignalProxyBase(obj),
info_(info),
{
}
-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());
}
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());
}
void
-SignalProxyDetailedBase::emission_stop()
+SignalProxyDetailed::emission_stop()
{
g_signal_stop_emission_by_name(obj_->gobj(), detailed_name_.c_str());
}
#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:
ObjectBase* obj_;
private:
- SignalProxyBase& operator=(const SignalProxyBase&) = delete;
+ SignalProxyBase& operator=(const SignalProxyBase&); // not implemented
};
// Shared portion of a Signal without detail
* 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
{
*/
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}
*/
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) {}
*/
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.
* 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,
*/
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.
}
};
+/* 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.
* 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();
* 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().
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)
{
}
* 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,
}
};
+/* 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 */
// 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);
g_signal_handler_disconnect(o, connection_id);
}
}
+
+ return nullptr; // apparently unused in libsigc++
}
// static
* 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.
* 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).
--- /dev/null
+/* 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
--- /dev/null
+#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 = -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 */
* 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()));
#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.
*
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)
{
_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() :
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);
*/
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);
/// 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));
}
*
* @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.
* 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()
*
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));
* 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()
*
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));
* 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()
*
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));
* 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()
*
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));
* 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()
*
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),
// 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)
{
* 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)
_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.
};
} //namespace Glib
+
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)
{
*/
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
regex.hg \
shell.hg \
spawn.hg \
+ thread.hg \
+ threads.hg \
timezone.hg \
unicode.hg \
uriutils.hg \
+ valuearray.hg \
variant.hg \
variantdict.hg \
variantiter.hg \
#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);
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)
{
*/
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.
{
_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)
*/
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));
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));
}
}
- /// 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);
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);
* 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
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());
/** 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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 = 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 --
+ * 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
+
--- /dev/null
+/* 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
--- /dev/null
+/* 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 --
+ * 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
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)
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)
--- /dev/null
+/* 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
--- /dev/null
+/* 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
/****************** 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;
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()
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
{
#include <utility>
#include <vector>
#include <map>
-#include <tuple>
#include <stdexcept>
#include <typeinfo>
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}
_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)
_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.
_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}
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
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
{
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
_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)
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 \
glibmm_ustring_compose/test \
glibmm_ustring_format/test \
glibmm_value/test \
+ glibmm_valuearray/test \
glibmm_variant/test \
glibmm_vector/test \
glibmm_bool_vector/test \
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
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)
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
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)
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)
+++ /dev/null
-/* 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;
-}
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.
// 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)
int
main()
{
+ std::list<std::string> alma;
std::string tstring, cstring;
type_nodetree_string* root;
type_nodetree_string* node;
--- /dev/null
+// 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
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**)
{
test_variant_floating();
test_dynamic_cast();
- return test_tuple();
+ return EXIT_SUCCESS;
}
// Test casting of multiple types to a ustring:
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()))
{
}
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)
# 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)')
')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
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.
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.
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
# 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.