Search code examples
callbacksignalsglibgobject

GLib - invoke callback for all instances of a class


I started to look into Glib signals. In my scenario I want to connect several instances of a class to a signal and if one of those instances calls g_signal_emit(...), the provided callback function should be called for all instances of that class. Let me try to explain this with an example.

What I tried is to create two instance of a class A (A0 and A1). Class A registers a very simple signal in its _class_init function.

 file_signals[0] = g_signal_newv("a_signal",
      G_TYPE_FROM_CLASS(ACLASS),
      G_SIGNAL_ACTION,
      NULL          /* closure */,
      NULL          /* accumulator */,
      NULL          /* accumulator data */,
      NULL          /* C marshaller */,
      G_TYPE_NONE   /* return_type */,
      0             /* n_params */,
      NULL);        /* argument types*/

Then I connect a simple callback function (cb_a) for both instances A0 and A1 to the signal "a_signal". (For example in the _instance_init function)

g_signal_connect(A0, "a_signal", (GCallback)cb_a, NULL);
g_signal_connect(A1, "a_signal", (GCallback)cb_a, NULL); ,

where cb_a is a function defined in A.c:

static void cb_a(void)
{
printf("cb_a called!\");
}

What happens now is that if I invoke

g_signal_emit(A0, file_signals[0], 0);

is that only the callback associated to A0 is invoked. I couldn´t figure out how to call the function for each instance of A with e.g. a single call to g_signal_emit(...)?

Any help is appreciated. Thanks.


Solution

  • That’s not how GObject signals work. A signal is a one-to-many notification from a single class instance to all the connected callbacks for that class instance. If you want to emit the A::a_signal signal from several instances of the class, you need to call g_signal_emit() for each of those instances.

    Note that g_signal_emit() is only meant to be called from within the implementation of a class, not from code outside that class.

    One approach to your problem is to have a separate class (let’s call it Signaller) with a signal on it, to store a reference to a single instance of Signaller within A0 and A1, and to connect a_cb to that instance within each of A0 and A1. To notify all instances of the A class, emit Signaller::a_signal on the single Signaller instance.

    However, without more concrete information about the particular problem you’re trying to solve, it’s hard to say what the right architecture is. My suggestion above may not be the most appropriate solution.