Re: Signal emission from an object thread
- From: Tristan Van Berkom <tristan vanberkom codethink co uk>
- To: Emmanuel Pacaud <emmanuel gnome org>
- Cc: gtk-list gnome org
- Subject: Re: Signal emission from an object thread
- Date: Sat, 18 Mar 2017 14:29:22 +0900
On Fri, 2017-03-17 at 14:26 +0100, Emmanuel Pacaud wrote:
Le ven. 17 mars 2017 Ã 9:52, Emmanuel Pacaud <emmanuel gnome org> aÂ
écrit :
Le ven. 17 mars 2017 Ã 6:43, Tristan Van Berkom
<tristan vanberkom codethink co uk> a écrit :
On Thu, 2017-03-16 at 10:42 +0100, Emmanuel Pacaud wrote:
 I have an issue related to the use of g_signal_emit called
from an
 object thread.
I have used GWeakRef for references that threads make to objectsÂ
owned
by parent thread which may finalize with parent, to solve similar
problems, but I dont believe I've tried using signals belonging
to a
thread spawning object from the thread itself.
Another approach, if you want to keep using GSignal, would be to
create
a different object that is owned completely by the thread.
I think I will use this solution.
I have just had a go at implementing something like that, but failed
toÂ
find the right way to do it. May be what I want to do is not
possible:
Currently, the 'new-buffer' signal is emitted by a ArvStream object,Â
which leads to the thread join issue I have described. What I wouldÂ
like to do is to define a signal in ArvStream, but with a signalÂ
callback that doesn't have ArvStream as the first parameter, but anÂ
ArvBuffer. Do the signal callbacks always have the object emitingÂ
instance in their parameters ?
No.
I took a brief look into your code, your thread it calling:
  arv_stream_push_output_buffer()
Which is emitting a gsignal. I'm not going to get a full handle on what
your code is trying to do, but I can only presume that you intend for
that to let your parent thread know that a buffer is ready ?
Ok, well, here are a few tips I think you can use to correct your code.
 o The `gboolean cancel` is wrong, setting this is not a guaranteed
  atomic operation.
  There are some facilities for atomic integers which you can use,
  such as g_atomic_int_set/get(), which act as a memory barrier which
  is less overhead than using mutexes.
 o Whenever sharing data with your thread, always protect it with
  g_mutex_lock() / g_mutex_unlock(), (there are also reader/writer
  locks available but I dont see you needing this here).
  The case of the boolean cancel is a bit exceptional, it can be
  set with an atomic operation. You may also consider using
  GCancellable for this.
 o If you want to communicate something back to the thread in which
  your main object was created, from the child worker thread, use
  the GMainLoop for this, that is easiest.
  Â
  So, in your object initializer or constructed() method (which
  is where the bulk of your code that is currently in
   arv_uv_stream_new() should ideally be instead), you want to take
  note of the active thread context (the GMainContext).
  This makes sure that if some program decides to use your object
  in a mainloop which they created in a *different* thread, your
  code does not blindly assume it was created in the main thread
  but will still work.
  You just make the assertion that "The user which created this
  object did so in a thread with a GMainContext where they are
  running a GMainLoop".
  Once you've got this far, you'll want to share that parent thread
  context with your worker thread, so that ArvUvStreamThreadData
  now has a GMainContext pointer to the thread context of the parent.
  In order to deliver some notification to the calling object, you
  will now use:
    source = g_idle_source_new()
    g_source_set_callback(source,
               parent_receive_func,
               data,
               free_data_func)
    g_source_attach(source, parent_thread_context)
  The object which created the thread, will then handle the
  'data' you sent in parent_receive_func the next time that
  that main thread is not busy and tries to go to sleep in
  it's GMainLoop.
 o There is something relatively new called GTask which has appeared,
  and it might take care of some of the above for you so that there
  are less lines of code overall, I have not really tried working
  with GTask since it's creation.
Please note that GSignal by itself is _only_ a means for marshalling of
callbacks via it's implicit invocation mechanism, and asides from
protecting itself and being "thread aware", it does not care what
thread was active when somebody called g_signal_connect().
In other words, any handlers connected to a GSignal will be called
_right now_ when g_signal_emit() is called, in the active thread where
g_signal_emit() is called.
I hope this was helpful :)
Cheers,
  -Tristan
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]