Omezení

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

27.1.1. Pravidla

Celé to vyžaduje řadu pravidel, kterých je třeba se držet při psaní vícevláknových aplikací pomocí gtkmm. Jsou uvedena níže, ale jedna věc stojí zvlášť za pozornost, a to, že je potřeba věnovat speciální péči odvozování tříd z sigc::trackable, protože efekty jsou nepředvidatelné (viz hlavně body 4 a 5 níže).

  1. Použijte Glib::Dispatcher k vyvolání funkcí gtkmm z pracovních vláken (podrobněji bude rozebráno dále).

  2. Objekt sigc::signal by měl být považován za vlastněný vláknem, které jej vytvořilo. Pouze toto vlákno by mělo napojit objekt sigc::slot na objekt signálu a pouze toto vlákno by mělo vyslat signál pomocí emit(), nebo na signál zavolat operator()(), nebo napojený objekt sigc::slot anulovat. Z toho vyplývá (mimo jiné), že objekt signálu poskytovaný widgetem gtkmm by měl operovat jen v hlavním vlákně starajícím se o grafické uživatelské rozhraní a objekt odvozený z sigc::trackable mající nestatické metody, na které se odkazuje slot napojený na objekt signálu, by měl být zlikvidován v tomto vlákně.

  3. Objekt sigc::connection by měl být považován za vlastněný vláknem, ve kterém byl metoda vracející objekt sigc::connection zavolána. Jen toto vlákno by mělo volat metody sigc::connection na objektu.

  4. A sigc::slot object created by a call to sigc::mem_fun() which references a method of a class deriving from sigc::trackable should never be copied to another thread, nor destroyed by a different thread than the one which created it.

  5. Pokud je určitý objekt třídy odvozený z sigc::trackable, jen jedno vlákno by mělo vytvářet objekty sigc::slot představující některou z nestatických metod třídy volánm sigc::mem_fun(). První vlákno, které má vytvořit takovýto slot, by mělo být považováno za vlastníka příslušného objektu za účelem vytváření dalších slotů odkazujících na kteroukoliv z jeho nestatických metod používajících tuto funkci, nebo anulovat tyto sloty jejich odpojením nebo zničeném sledovacího objektu.

  6. Ačkoliv glib je sama o sobě z hlediska vláken bezpečná, některé obalující funkce z glibmm, které používají libsigc++, bezpečné nebudou. Takže například jen vlákno, ve kterém běží hlavní smyčka by mělo volat Glib::SignalIdle::connect(), Glib::SignalIO::connect(), Glib::SignalTimeout::connect(), Glib::SignalTimeout::connect_seconds pro hlavní smyčku, nebo manipulovat s objektem sigc::connection, který vrací.

    The connect*_once() variants, Glib::SignalIdle::connect_once(), Glib::SignalTimeout::connect_once(), Glib::SignalTimeout::connect_seconds_once(), are thread-safe for any case where the slot is not created by a call to sigc::mem_fun() which represents a method of a class deriving from sigc::trackable.

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.