Las limitaciones

glibmm proporciona el conjunto normal de funciones de lanzamiento de hilos, exclusión mutua, variables condicionales y clases de bloqueo de alcance requeridas para escribir programas de múltiples hilos usando C++.

However, care is required when writing programs based on gtkmm using multiple threads of execution, arising from the fact that libsigc++, and in particular sigc::trackable, are not thread-safe. That's because none of the complex interactions that occur behind the scenes when using libsigc++ are protected by a mutex or other means of synchronization. 1

29.1.1. Las reglas

Esto requiere que se observen una cantidad de reglas cuando escribe programas de múltiples hilos usando gtkmm. Estas se exponen abajo, pero un punto a destacar es que se requiere cuidado adicional cuando deriva clases de sigc::trackable, porque los efectos no son intuitivos (consulte particularmente los puntos 4 y 5 debajo).

  1. Use Glib::Dispatcher para invocar las funciones de gtkmm desde hilos de trabajo (esto se explica con má detalle en la próxima sección).

  2. Un objeto sigc::signal debe considerarse propiedad del hilo que lo creó. Solo ese hilo debe conectar un objeto sigc::slot al objeto de la señal, y solo ese hilo debe llamar a emit() u operator()() sobre la señal, o anular cualquier objeto sigc::slot conectado. Sigue (junto a otras cosas) que cualquier objeto de señal proporcionado por un widget de gtkmm solo se opere en el hilo principal de la IGU y cualquier objeto que derive de sigc::trackable con métodos no estáticos referenciados por «slots» conectados al objeto de señal solo deben destruirse en ese hilo.

  3. Cualquier objeto sigc::connection solo debe considerarse propiedad del hilo en el que se llamó al método que devuelve el objeto sigc::connection. Solo ese hilo debe llamar a métodos de sigc::connection sobre el objeto.

  4. Un objeto sigc::slot creado por una llamada a sigc::mem_fun() que referencia un método de una clase que deriva de sigc::trackable nunca debe copiarse a otro hilo, ni otro hilo aparte del que lo creó lo debe destruir. (Una consecuencia de esto es que Glib::Threads::Thread::create() no debe llamarse con un argumento de «slot» creado por una llamada a sigc::mem_fun() que represente a un método de una clase semejante. Sin embargo, es seguro pasarle Glib::Threads::Thread::create() a un objeto de función representando un método así usando, por ejemplo, boost::bind() o, en C++11, std::bin() o una expresión lambda de C++11).

  5. Si un objeto de clase particular deriva de sigc::trackable, solo un hilo debe crear objetos sigc::slot representando cualquiera de los métodos no estáticos de la clase llamando a sigc::mem_fun(). El primer hilo que cree un «slot» semejante debe considerarse dueño del objeto relevante con el propósito de crear más «slots» referenciando a cualquiera de sus métodos no estáticos que usan esa función, o anulando aquellos «slots» desconectándolos o destruyendo el objeto «trackable».

  6. A pesar de que glib en sí es segura para hilos, cualquier envoltorio de glibmm que use libsigc++ no lo será. Entonces por ejemplo solo el hilo en el bucle principal debe llamar a Glib::SignalIdle::connect(), Glib::SignalIO::connect(), Glib::SignalTimeout::connect(), Glib::SignalTimeout::connect_seconds para ese bucle principal, o manipular cualquier objeto sigc::connection que devuelvan.

    Las variantes de «connect*_once()», Glib::SignalIdle::connect_once(), Glib::SignalTimeout::connect_once(), Glib::SignalTimeout::connect_seconds_once(), son seguras para hilos para cualquier caso en el que el «slot» no lo cree una llamada a sigc::mem_fun() que represente a un método de una clase derivada de sigc::trackable. Esto es similar a Glib::Threads::Thread::create() como se menciona en el punto 4.

1

These interactions arise from the fact that, amongst other things, a class inheriting from sigc::trackable will, via that inheritance, have a std::list object keeping track of slots created by calls to sigc::mem_fun() representing any of its non-static methods (more particularly it keeps a list of callbacks which will null the connected slots on its destruction). Each sigc::slot object also keeps, via sigc::slot_rep, its own sigc::trackable object to track any sigc::connection objects which it needs to inform about its demise, and also has a function to deregister itself from any sigc::trackable on disconnection or destruction. sigc::signal objects also keep lists of slots, which will be updated by a call to their connect() method or calls to any sigc::connection object relating to such a connection.