After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 757674 - Deprecate Glib::Threads:: in favour of the C++11/C++14 concurrency API
Deprecate Glib::Threads:: in favour of the C++11/C++14 concurrency API
Status: RESOLVED FIXED
Product: glibmm
Classification: Bindings
Component: threads
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gtkmm-forge
gtkmm-forge
Depends on:
Blocks: 755091
 
 
Reported: 2015-11-06 10:23 UTC by Murray Cumming
Modified: 2015-11-28 13:47 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
0001-Threads-Deprecate-in-favour-of-the-C-11-C-14-concurr.patch (3.74 KB, patch)
2015-11-06 10:23 UTC, Murray Cumming
none Details | Review
0001-tests-glibmm_mainloop-Use-the-std-thread-API-instead.patch (3.04 KB, patch)
2015-11-06 10:48 UTC, Murray Cumming
committed Details | Review
0001-Network-examples-Use-std-thread-instead-of-Glib-Thre.patch (4.02 KB, patch)
2015-11-06 11:09 UTC, Murray Cumming
committed Details | Review
0001-examples-dispatcher-Use-std-thread-and-friends.patch (4.71 KB, patch)
2015-11-06 12:24 UTC, Murray Cumming
committed Details | Review
0001-thread-example-Use-std-thread-etc-instead-of-depreca.patch (3.13 KB, patch)
2015-11-06 12:38 UTC, Murray Cumming
committed Details | Review
0001-threadpool-example-Use-std-mutex-instead-of-Glib-Thr.patch (1.10 KB, patch)
2015-11-06 12:46 UTC, Murray Cumming
committed Details | Review
0005-Threads-Deprecate-in-favour-of-the-C-11-C-14-concurr.patch (3.88 KB, patch)
2015-11-06 12:51 UTC, Murray Cumming
committed Details | Review
0001-Use-thread_local-instead-of-Glib-Threads-Private.patch (4.26 KB, patch)
2015-11-27 08:41 UTC, Murray Cumming
none Details | Review

Description Murray Cumming 2015-11-06 10:23:58 UTC
Created attachment 314968 [details] [review]
0001-Threads-Deprecate-in-favour-of-the-C-11-C-14-concurr.patch

Let's depend on C++14 for glibmm 2.48 so we can deprecate our Glib::Threads API:
https://mail.gnome.org/archives/gtkmm-list/2015-August/msg00062.html

This patch deprecates almost all the Glib::Threads:: classes. It does not yet deprecate Glib::Threads::Private. I wonder if that is still useful.

The patches in bug #755091 update the book's example code and text appropriately.
Comment 1 Murray Cumming 2015-11-06 10:31:30 UTC
Glib::Threads::Private wraps GPrivate, which seems to wrap pthread_setspecific() and pthread_getspecific():
https://developer.gnome.org/glib/stable/glib-Threads.html#GPrivate

Maybe we should generally discourage use of any pthread API at the same time as the higher-level C++ concurrency API?
Comment 2 Murray Cumming 2015-11-06 10:48:07 UTC
Created attachment 314972 [details] [review]
0001-tests-glibmm_mainloop-Use-the-std-thread-API-instead.patch
Comment 3 Murray Cumming 2015-11-06 11:09:33 UTC
Created attachment 314973 [details] [review]
0001-Network-examples-Use-std-thread-instead-of-Glib-Thre.patch
Comment 4 Murray Cumming 2015-11-06 12:24:33 UTC
Created attachment 314980 [details] [review]
0001-examples-dispatcher-Use-std-thread-and-friends.patch
Comment 5 Murray Cumming 2015-11-06 12:38:01 UTC
Created attachment 314983 [details] [review]
0001-thread-example-Use-std-thread-etc-instead-of-depreca.patch

For this one, I added some unlock() calls before the condition_variable::notify_one() calls, even though there were no corresponding Glib::Threads::Lock::release() calls to replace.
Comment 6 Murray Cumming 2015-11-06 12:46:41 UTC
Created attachment 314984 [details] [review]
0001-threadpool-example-Use-std-mutex-instead-of-Glib-Thr.patch

Glib::ThreadPool doesn't use the Glib::Threads::* API but I wonder if we should deprecate it anyway.

There seems to be some confusion about whether a thread pool is necessary with C++11 std::thread, or whether that is implementation dependent. Anyway, we would be encouraging mixing of 2 thread APIs if we left it undeprecated.
Comment 7 Murray Cumming 2015-11-06 12:51:57 UTC
Created attachment 314985 [details] [review]
0005-Threads-Deprecate-in-favour-of-the-C-11-C-14-concurr.patch

This one mentions std::lock_guard and (std::unique_lock) instead of std::lock.
Comment 8 Murray Cumming 2015-11-06 12:52:43 UTC
It would be nice if people could check my patches that update the tests and examples. We could then push them already without waiting for the Glib::Threads deprecation.
Comment 9 Andrew Potter 2015-11-08 01:20:29 UTC
Review of attachment 314983 [details] [review]:

::: examples/thread/thread.cc
@@ +112,3 @@
   MessageQueue queue;
 
+  auto *const producer = new std::thread(

std::unique_ptr would be nicer here. And since we'll be turning on c++14 you can std::make_unique
Comment 10 Kjell Ahlstedt 2015-11-09 11:59:33 UTC
examples/network
  resolver.cc:
      G_LOCK_DEFINE_STATIC (response);
    can be replaced by
      static std::mutex response;

  socket-client.cc and socket-server.cc:
    //TODO: This won't happen if we returned earlier.
    is a note that something remains to be done with std::thread* thread.
    A have no detailed solution now. Perhaps replace the dumb pointer by
      std::unique_ptr<std::thread, join_and_delete> thread;
      //...
      void join_and_delete(std::thread* thread)
      {
        thread->join();
        delete thread;
      }

examples/thread/dispatcher
examples/thread/dispatcher2
  OK

examples/thread/thread
  The main function can be simplified to
    int main(int, char**)
    {
      Glib::init();

      MessageQueue queue;

      std::thread producer(&MessageQueue::producer, &queue);
      std::thread consumer(&MessageQueue::consumer, &queue);

      producer.join();
      consumer.join();

      std::cout << std::endl;

      return 0;
    }
  Well, the replacement of the lambda expressions is perhaps not an obvious
  simplification, but allocating the threads on the stack is.

examples/thread/threadpool
  OK

tests/glibmm_mainloop
  second_thread can be allocated on the stack:
    std::thread second_thread(
      [first_thread_id, first_mainloop]
      {
        thread_function(first_thread_id, first_mainloop);
      });
    // ...
    second_thread.join();

  An alternative to the lambda expression:
    std::thread second_thread(thread_function, first_thread_id, first_mainloop);


>>>Comments to the patch that deprecates Glib::Threads

When all of glib/src/threads.hg is deprecated, it should be moved to
glibmm_files_deprecated_hg in glib/src/filelist.am.

When everything in the Glib::Threads namespace is deprecated, it should not be
used in glibmm. But it is. Deprecated stuff is used in

  glib/glibmm/dispatcher.cc
    static Threads::Private<> Glib::DispatchNotifier::thread_specific_instance_
    Threads::Mutex Glib::DispatchNotifier::mutex_ // ifdef G_OS_WIN32

  glib/glibmm/exceptionhandler.cc
    static Glib::Threads::Private<HandlerList> thread_specific_handler_list

  glib/glibmm/main.[h|cc]
  glib/glibmm/main.cc
    Glib::MainContext::wait(Glib::Threads::Cond&, Glib::Threads::Mutex&)

  glib/glibmm/main.cc
    Glib::Threads::Mutex extra_source_data_mutex;

  glib/glibmm/objectbase.[h|cc]
  glib/glibmm/object.cc
  glib/glibmm/interface.cc
    static Threads::Mutex* Glib::ObjectBase::extra_object_base_data_mutex

  glib/glibmm/threadpool.cc
    Glib::Threads::Mutex Glib::ThreadPool::SlotList::mutex_
    catch(Glib::Threads::Thread::Exit&)

  gio/src/application.ccg
    Glib::Threads::Mutex option_arg_callback_data_mutex
Comment 11 Murray Cumming 2015-11-09 14:16:57 UTC
(In reply to Kjell Ahlstedt from comment #10)

>   glib/glibmm/main.[h|cc]
>   glib/glibmm/main.cc
>     Glib::MainContext::wait(Glib::Threads::Cond&, Glib::Threads::Mutex&)

That wraps g_main_context_wait(). I cannot think of any way to replace our wait() with a wait() that uses std::condition_variable, without reimplementing g_main_context_wait or, maybe notifying a std::condition_variable when an internal GCond is notified, which sounds a bit unpleasant.

We could say "Use the C API if you really want this". It doesn't seem really generally useful, right?

>   glib/glibmm/objectbase.[h|cc]
>   glib/glibmm/object.cc
>   glib/glibmm/interface.cc
>     static Threads::Mutex* Glib::ObjectBase::extra_object_base_data_mutex

I wonder if it would break ABI to change that static Mutex* (as in, exported to other object files) to a std::mutex*. It's meant to be private API anyway, right? Or is it used outside of glibmm?
Comment 12 Kjell Ahlstedt 2015-11-09 19:08:02 UTC
(In reply to Murray Cumming from comment #11)
> >     Glib::MainContext::wait(Glib::Threads::Cond&, Glib::Threads::Mutex&)
>
> We could say "Use the C API if you really want this". It doesn't seem really
> generally useful, right?

I don't know if it's useful. It doesn't look very useful to me. And I realize
that it would be difficult to replace Glib::Threads::Cond and Glib::Threads::Mutex
by std::condition_variable and std::mutex here. So yes, it's probably best to
deprecate Glib::MainContext::wait(), direct app programmers to the C API, and
see if anyone complains.

> >   glib/glibmm/objectbase.[h|cc]
> >   glib/glibmm/object.cc
> >   glib/glibmm/interface.cc
> >     static Threads::Mutex* Glib::ObjectBase::extra_object_base_data_mutex
>
> I wonder if it would break ABI to change that static Mutex* (as in, exported
> to other object files) to a std::mutex*. It's meant to be private API
> anyway, right? Or is it used outside of glibmm?

It shall not be used in any class except ObjectBase, Object and Interface.
It's part of a workaround for added instance data in ObjectBase, which we can add
only at the next ABI break. It was changed from std::auto_ptr<Threads::Mutex> to
Threads::Mutex* as a fix for bug 748630. Now it can be changed to
std::unique_ptr<std::mutex> or even to std::mutex. The reason why it's a pointer
is explained in objectbase.h. That reason does not apply, if it's replaced by
a std::mutex.
Comment 13 Murray Cumming 2015-11-26 10:07:59 UTC
OK. I've pushed all the patches to glibmm's master and I think I've addressed all the suggestions in subsequent commits. Thanks.
Comment 14 Kjell Ahlstedt 2015-11-26 18:26:54 UTC
Deprecated classes (Threads::Private, Threads::Mutex, Threads::Thread::Exit)
are still used in several glib/glibmm/*.cc files and in gio/src/application.ccg.
Are they deliberately not replaced?
Comment 15 Murray Cumming 2015-11-26 20:01:51 UTC
No, that wasn't on purpose. I've just replaced the use of Glib::Threads::* in giomm' application.cc glibmm's main.c.

I have not done anything about the use of Glib::Threads::Private<> in dispatcher.cc and exceptionhandler.cc. I wonder if we can replace Private with the thread_local keyword in C++11:
http://en.cppreference.com/w/cpp/language/storage_duration
Comment 16 Murray Cumming 2015-11-27 08:41:16 UTC
Created attachment 316366 [details] [review]
0001-Use-thread_local-instead-of-Glib-Threads-Private.patch

Hopefully it's this easy to replace Glib::Threads::Private<> with thread_local, but it would be nice if someone more familiar with it could check this patch, please.
Comment 17 Kjell Ahlstedt 2015-11-28 10:34:50 UTC
I have fixed a bug that crept into the code when Glib::Threads::Mutex::Lock was
replaced by std::unique_lock. Glib::Threads::Mutex::Lock::release() must be
replaced by std::unique_lock::unlock().
https://git.gnome.org/browse/glibmm/commit/?id=c7d7d5f169103b2d16527c52a95a5dc78e216da6

Then I tested the patch that replaces Glib::Threads::Private by thread_local.
The test cases that use Glib::Dispatcher (glibmm/examples/thread/dispatcher.cc,
dispatcher2.cc and gtkmm-documentation/examples/book/multithread) all work as
expected. I just changed
  // This causes deletion of the notifier object.
  thread_specific_instance_ = nullptr;
to
  delete instance;
  thread_specific_instance_ = nullptr;
Comment 18 Murray Cumming 2015-11-28 13:47:46 UTC
Thanks. That all now in master and I've release a tarball.