Οι περιορισμοί
Η glibmm παρέχει το κανονικό σύνολο των συναρτήσεων εκκίνησης νήματος, αμοιβαίων αποκλεισμών, μεταβλητών συνθηκών και κλάσεων κλειδώματος εμβέλειας που απαιτούνται για συγγραφή πολυνηματικών προγραμμάτων χρησιμοποιώντας την 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. Οι κανόνες
29.1.1. Οι κανόνες
Αυτό απαιτεί έναν αριθμό από κανόνες να παρατηρούνται κατά την εγγραφή πολυνηματικών προγραμμάτων χρησιμοποιώντας την gtkmm. Αυτοί εκτίθενται παρακάτω, αλλά σημειώστε ένα σημείο ότι απαιτείται ιδιαίτερη φροντίδα όταν παράγεται κλάσεις από την sigc::trackable, επειδή τα αποτελέσματα δεν είναι διαισθητικά (δείτε ιδιαίτερα τα παρακάτω σημεία 4 και 5).
-
Χρησιμοποιήστε την Glib::Dispatcher για να καλέσετε συναρτήσεις gtkmm από νήματα εργασίας (αυτό αναφέρεται με περισσότερη λεπτομέρεια στην επόμενη ενότητα).
-
Ένα αντικείμενο sigc::signal πρέπει να θεωρείται ως κατεχόμενο από το νήμα που το δημιούργησε. Μόνο αυτό το νήμα συνδέει ένα αντικείμενο sigc::slot με το αντικείμενο σήματος και μόνο αυτό το νήμα πρέπει να emit() ή να καλεί την operator()() με το σήμα, ή να αδειάζει οποιοδήποτε συνδεμένο αντικείμενο sigc::slot. Ακολουθεί (μεταξύ άλλων) ότι οποιοδήποτε αντικείμενο σήματος που παρέχεται από το γραφικό συστατικό gtkmm πρέπει να λειτουργεί μόνο στο κύριο νήμα γραφικής διεπαφής χρήστη και οποιοδήποτε αντικείμενο παράγεται από την sigc::trackable να έχει τις μη στατικές μεθόδους του που αναφέρονται από τις συνδεμένες υποδοχές στο αντικείμενο σήματος που πρέπει να καταστραφεται μόνο σε αυτό το νήμα.
-
Οποιοδήποτε αντικείμενο sigc::connection πρέπει να θεωρείται ως κατεχόμενο από το νήμα στο οποίο η μέθοδος επιστρέφει το αντικείμενο sigc::connection που κλήθηκε. Μόνο αυτό το νήμα πρέπει να καλεί τις μεθόδους sigc::connection στο αντικείμενο.
-
Ένα αντικείμενο sigc::slot που δημιουργήθηκε από μια κλήση στην sigc::mem_fun() που αναφέρει μια μέθοδο μιας κλάσης που παράγεται από sigc::trackable δεν θα πρέπει ποτέ να αντιγραφεί σε άλλο νήμα, ή να καταστραφεί από διαφορετικό νήμα από αυτό που το δημιούργησε. (Μια συνέπεια αυτού είναι ότι η Glib::Threads::Thread::create() δεν πρέπει να κληθεί με ένα όρισμα υποδοχής που δημιουργήθηκε από μια κλήση της sigc::mem_fun() που αναπαριστά μια μέθοδο μιας τέτοιας κλάσης. Είναι όμως ασφαλές να περάσετε στην Glib::Threads::Thread::create() ένα αντικείμενο συνάρτησης που απεικονίζει μια τέτοια μέθοδο χρησιμοποιώντας boost::bind() ή, στην C++11, std::bind() ή μία έκφραση λάμδα C++11.)
-
Αν ένα ειδικό αντικείμενο κλάσης προέρχεται από την sigc::trackable, μόνο ένα νήμα πρέπει να δημιουργήσει αντικείμενα sigc::slot που αναπαριστούν οποιεσδήποτε μη στατικές μεθόδους της κλάσης καλώντας την sigc::mem_fun(). Το πρώτο νήμα για να δημιουργήσει μια τέτοια υποδοχή πρέπει να θεωρηθεί ως κάτοχος του σχετικού αντικειμένου για τον σκοπό της δημιουργίας παραπέρα υποδοχών αναφορικά με οποιαδήποτε από τις μη στατικές μεθόδους που χρησιμοποιούν αυτή τη συνάρτηση, ή αδειάζοντας αυτές τις υποδοχές αποσυνδέοντας τες ή καταστρέφοντας το ανιχνεύσιμο αντικείμενο.
-
Αν και η glib είναι η ίδια με ασφάλεια νήματος, οποιοιδήποτε συσκευαστές glibmm που χρησιμοποιούν libsigc++ δεν είναι. Έτσι για παράδειγμα, μόνο το νήμα στο οποίο ο κύριος βρόχος εκτελείται πρέπει να καλεί τις Glib::SignalIdle::connect(), Glib::SignalIO::connect(), Glib::SignalTimeout::connect(), Glib::SignalTimeout::connect_seconds για τον κύριο βρόχο, ή να χειρίζεται οποιοδήποτε αντικείμενο sigc::connection που επιστρέφεται από αυτές.
Οι παραλλαγές connect*_once(), Glib::SignalIdle::connect_once(), Glib::SignalTimeout::connect_once(), Glib::SignalTimeout::connect_seconds_once(), είναι με ασφάλεια νήματος για κάθε περίπτωση όπου η υποδοχή δεν δημιουργείται από μια κλήση στην sigc::mem_fun() που αντιπροσωπεύει μια μέθοδο κλάσης που παράγεται από την sigc::trackable. Αυτή είναι παρόμοια με την Glib::Threads::Thread::create() όπως αναφέρθηκε στο σημείο 4.
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.