|
Packit |
1470ea |
|
|
Packit |
1470ea |
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" xmlns:xi="http://www.w3.org/2003/XInclude" type="guide" style="task" id="custom-gsource.c" xml:lang="el">
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<info>
|
|
Packit |
1470ea |
<link type="guide" xref="c#examples"/>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<credit type="author copyright">
|
|
Packit |
1470ea |
<name>Philip Withnall</name>
|
|
Packit |
1470ea |
<email its:translate="no">philip.withnall@collabora.co.uk</email>
|
|
Packit |
1470ea |
<years>2015</years>
|
|
Packit |
1470ea |
</credit>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<include xmlns="http://www.w3.org/2001/XInclude" href="legal.xml"/>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<desc>Μάθημα για την εγγραφή μιας προσαρμοσμένης υλοποίησης GSource </desc>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
|
|
Packit |
1470ea |
<mal:name>Ελληνική μεταφραστική ομάδα GNOME</mal:name>
|
|
Packit |
1470ea |
<mal:email>team@gnome.gr</mal:email>
|
|
Packit |
1470ea |
<mal:years>2012-2015</mal:years>
|
|
Packit |
1470ea |
</mal:credit>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
|
|
Packit |
1470ea |
<mal:name>Δημήτρης Σπίγγος</mal:name>
|
|
Packit |
1470ea |
<mal:email>dmtrs32@gmail.com</mal:email>
|
|
Packit |
1470ea |
<mal:years>2012, 2013</mal:years>
|
|
Packit |
1470ea |
</mal:credit>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
|
|
Packit |
1470ea |
<mal:name>Μαρία Θουκιδίδου</mal:name>
|
|
Packit |
1470ea |
<mal:email>marablack3@gmail.com</mal:email>
|
|
Packit |
1470ea |
<mal:years>2014</mal:years>
|
|
Packit |
1470ea |
</mal:credit>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
|
|
Packit |
1470ea |
<mal:name>Θάνος Τρυφωνίδης</mal:name>
|
|
Packit |
1470ea |
<mal:email>tomtryf@gmail.com</mal:email>
|
|
Packit |
1470ea |
<mal:years>2014, 2015</mal:years>
|
|
Packit |
1470ea |
</mal:credit>
|
|
Packit |
1470ea |
</info>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<title>Προσαρμοσμένα GSources</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<synopsis>
|
|
Packit |
1470ea |
<title>Περίληψη</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Αυτό το κείμενο είναι ένα μάθημα για την δημιουργία ενός προσαρμοσμένου GSource . Αν θέλετε να δείτε περισσότερη τεκμηρίωση, επισκεφθείτε την <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#GSource">αναφορά του GLib API</link>.
|
|
Packit |
1470ea |
</synopsis>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="what-is-gsource">
|
|
Packit |
1470ea |
<title>Τι είναι GSource ;</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Το <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#GSource">GSource </link> είναι ένα γεγονός με μια συσχετισμένη συνάρτηση επανάκλησης η οποία καλείται όταν λαμβάνεται το γεγονός. Το γεγονός αυτό μπορεί να είναι ένα χρονικό όριο ή δεδομένα που λαμβάνονται από μια υποδοχή.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Το GLib περιλαμβάνει διάφορους τύπους GSource , αλλά επιτρέπει επίσης της εφαρμογές να ορίσουν τα δικά τους, επιτρέποντας προσαρμοσμένα συμβάντα να ενσωματωθούν στον κύριο βρόγχο του προγράμματος.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Η δομή του GSource και των εικονικών συναρτήσεων περιγράφονται λεπτομερώς στην <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#GSourceFuncs">αναφορά του GLib API</link>.
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="queue-source">
|
|
Packit |
1470ea |
<title>Πηγή μιας ουράς μηνύματος</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Για παράδειγμα, η πηγή μιας ουράς μηνύματος θα χρησιμοποιηθεί για να σταλθεί η επανάκληση της κάθε φορά που ένα μήνυμα θα μπει στην ουρά της πηγής (συνήθως από άλλο νήμα).
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Αυτός ο τύπος πηγής είναι χρήσιμος για την αποτελεσματική μεταφορά μεγάλου αριθμού μηνυμάτων. Ένας εναλλακτικός τρόπος είναι η μεταφορά κάθε μηνύματος ως ξεχωριστό GSource χρησιμοποιώντας το g_source_attach() . Για μεγάλο αριθμό μηνυμάτων, αυτό σημαίνει πως θα υπάρχουν πολλές λειτουργίες κατανομών και ελευθέρωσης των GSource .
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="gsource-structure">
|
|
Packit |
1470ea |
<title>Δομή</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Αρχικά, πρέπει να οριστεί μια δομή για τις ανάγκες του κώδικα. Αυτή η δομή πρέπει να περιέχει ένα GSource ως γονικό, ακολουθόμενο από ιδιωτικά πεδία: την ουρά και μια συνάρτηση για να καλεστεί κάθε μήνυμα όταν τελειώσει.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
typedef struct {
|
|
Packit |
1470ea |
GSource parent;
|
|
Packit |
1470ea |
GAsyncQueue *queue; /* owned */
|
|
Packit |
1470ea |
GDestroyNotify destroy_message;
|
|
Packit |
1470ea |
} MessageQueueSource;
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="prepare-function">
|
|
Packit |
1470ea |
<title>Συνάρτηση προετοιμασίας</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Στη συνέχεια, πρέπει να οριστεί η συνάρτηση προετοιμασίας. Αυτή καθορίζει αν ο κώδικας είναι έτοιμος να σταλθεί. Καθώς αυτός ο κώδικας χρησιμοποιεί μια ουρά μνήμης, η ενέργεια μπορεί να καθοριστεί ελέγχοντας το μήκος της ουράς: αν υπάρχουν στοιχεία στην ουρά, τότε ο κώδικας μπορεί να σταλθεί για να τα διαχειριστεί.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
return (g_async_queue_length (message_queue_source->queue) > 0);
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="check-function">
|
|
Packit |
1470ea |
<title>Συνάρτηση ελέγχου</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Καθώς αυτή η πηγή δεν έχει καθόλου περιγραφείς αρχείων, οι συναρτήσεις προετοιμασίας και ελέγχου εκτελούν την ίδια δουλειά, έτσι δεν είναι αναγκαία μια συνάρτηση ελέγχου. Ορίζοντας το πεδίο σε NULL στο GSourceFuncs παρακάμπτεται η συνάρτηση ελέγχου για αυτόν τον τύπο πηγής.
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="dispatch-function">
|
|
Packit |
1470ea |
<title>Συνάρτηση αποστολής</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Η συνάρτηση αποστολής είναι το πιο πολύπλοκο κομμάτι. Πρέπει να πάρει ένα μήνυμα από την ουρά και να το περάσει στην συνάρτηση επανάκλησης του GSource . Δεν είναι απαραίτητο να υπάρχουν μηνύματα στην ουρά: ακόμα και αν η συνάρτηση προετοιμασίας επιστρέψει αληθές, μια άλλη πηγή μπορεί να έχει δεχτεί το τελικό μήνυμα από την ουρά. Επίσης, αν δεν είχε οριστεί μια συνάρτηση επανάκλησης για το GSource (το οποίο είναι αποδεκτό), το μήνυμα πρέπει να καταστραφεί.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Αν έχει οριστεί ένα μήνυμα και μια επανάκληση, η επανάκληση μπορεί να καλεστεί από το μήνυμα και να επιστρέψει μια τιμή, όπως η τιμή που επιστρέφεται από την συνάρτηση αποστολής. Αυτό ορίζεται ως FALSE για την καταστροφή του GSource και TRUE για να παραμείνει ως έχει, όπως και το GSourceFunc — αυτά παραμένουν τα ίδια για όλες τις υλοποιήσεις μιας συνάρτησης αποστολής.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/* Pop a message off the queue. */
|
|
Packit |
1470ea |
message = g_async_queue_try_pop (message_queue_source->queue);
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/* If there was no message, bail. */
|
|
Packit |
1470ea |
if (message == NULL)
|
|
Packit |
1470ea |
{
|
|
Packit |
1470ea |
/* Keep the source around to handle the next message. */
|
|
Packit |
1470ea |
return TRUE;
|
|
Packit |
1470ea |
}
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/* @func may be %NULL if no callback was specified.
|
|
Packit |
1470ea |
* If so, drop the message. */
|
|
Packit |
1470ea |
if (func == NULL)
|
|
Packit |
1470ea |
{
|
|
Packit |
1470ea |
if (message_queue_source->destroy_message != NULL)
|
|
Packit |
1470ea |
{
|
|
Packit |
1470ea |
message_queue_source->destroy_message (message);
|
|
Packit |
1470ea |
}
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/* Keep the source around to consume the next message. */
|
|
Packit |
1470ea |
return TRUE;
|
|
Packit |
1470ea |
}
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
return func (message, user_data);
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="callback">
|
|
Packit |
1470ea |
<title>Συναρτήσεις επανάκλησης</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Η επανάκληση από το GSource δεν είναι αναγκαίο να είναι τύπου GSourceFunc . Μπορεί να είναι οποιουδήποτε τύπου συνάρτηση στην πηγή της συνάρτησης επανάκλησης, εφόσον αυτός ο τύπος είναι επαρκώς τεκμηριωμένος.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Συνήθως, το g_source_set_callback() χρησιμοποιείται για να οριστεί η συνάρτηση επανάκλησης για ένα στιγμιότυπο πηγής. Με το GDestroyNotify του, μια ισχυρή αναφορά μπορεί να δημιουργηθεί για να κρατήσει ζωντανό το αντικείμενο καθώς η πηγή είναι ακόμα ενεργή:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
g_source_set_callback (source, callback_func,
|
|
Packit |
1470ea |
g_object_ref (object_to_strong_ref),
|
|
Packit |
1470ea |
(GDestroyNotify) g_object_unref);
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Ωστόσο, το GSource διαθέτει μια στρώση για τη ήψη της επανάκλησης, ως g_source_set_callback_indirect() . Αυτό επιτρέπει το GObject να ορίσει ένα GClosure ως επανάκληση για την πηγή, επιτρέποντας τις πηγές να καταστρέφονται αυτόματα όταν οριστοποιηθεί ένα αντικείμενο — μια χαλαρή αναφορά, σε αντίθεση με την ισχυρή αναφορά παραπάνω:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
g_source_set_closure (source,
|
|
Packit |
1470ea |
g_cclosure_new_object (callback_func,
|
|
Packit |
1470ea |
object_to_weak_ref));
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Επιτρέπει επίσης για μια γενική, εικονική επανάκληση, η οποία μπορεί να χρησιμοποιηθεί όταν μια πηγή χρειάζεται να τερματιστεί αλλά δεν απαιτείται να εκτελεστούν ενέργειες στην επανάκληση της:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
g_source_set_dummy_callback (source);
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="constructor">
|
|
Packit |
1470ea |
<title>Κατασκευαστής</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Τέλος, ο ορισμός του GSourceFuncs για το GSource μπορεί να γραφεί μαζί με μια συνάρτηση κατασκευαστή. Είναι κοινή πρακτική να παρουσιάζονται οι νέοι τύποι πηγών ως GSource , αλλά όχι ως τύπο της δομής, έτσι ώστε ο κατασκευαστής να επιστρέφει το GSource* .
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Το παράδειγμα του κατασκευαστή παρουσιάζει τη χρήση μιας θυγατρικής πηγής για την υποστήριξη της λειτουργίας ακύρωσης. Αν ακυρωθεί το GCancellable , η επανάκλαση της εφαρμογής θα σταλθεί και θα ελέγξει για την ακύρωση. (Ο κώδικας της εφαρμογής θα πρέπει να δημιουργήσει έναν δείκτη στο GCancellable που θα είναι διαθέσιμο στην επανάκληση ως ένα πεδίο για τα δεδομένα του χρήστη στο g_source_set_callback() ).
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
GSource *
|
|
Packit |
1470ea |
message_queue_source_new (GAsyncQueue *queue,
|
|
Packit |
1470ea |
GDestroyNotify destroy_message,
|
|
Packit |
1470ea |
GCancellable *cancellable)
|
|
Packit |
1470ea |
{
|
|
Packit |
1470ea |
GSource *source; /* alias of @message_queue_source */
|
|
Packit |
1470ea |
MessageQueueSource *message_queue_source; /* alias of @source */
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
g_return_val_if_fail (queue != NULL, NULL);
|
|
Packit |
1470ea |
g_return_val_if_fail (cancellable == NULL ||
|
|
Packit |
1470ea |
G_IS_CANCELLABLE (cancellable), NULL);
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
source = g_source_new (&message_queue_source_funcs,
|
|
Packit |
1470ea |
sizeof (MessageQueueSource));
|
|
Packit |
1470ea |
message_queue_source = (MessageQueueSource *) source;
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/* The caller can overwrite this name with something more useful later. */
|
|
Packit |
1470ea |
g_source_set_name (source, "MessageQueueSource");
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
message_queue_source->queue = g_async_queue_ref (queue);
|
|
Packit |
1470ea |
message_queue_source->destroy_message = destroy_message;
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/* Add a cancellable source. */
|
|
Packit |
1470ea |
if (cancellable != NULL)
|
|
Packit |
1470ea |
{
|
|
Packit |
1470ea |
GSource *cancellable_source;
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
cancellable_source = g_cancellable_source_new (cancellable);
|
|
Packit |
1470ea |
g_source_set_dummy_callback (cancellable_source);
|
|
Packit |
1470ea |
g_source_add_child_source (source, cancellable_source);
|
|
Packit |
1470ea |
g_source_unref (cancellable_source);
|
|
Packit |
1470ea |
}
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
return source;
|
|
Packit |
1470ea |
}
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="full-listing">
|
|
Packit |
1470ea |
<title>Πλήρες παράδειγμα</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<listing>
|
|
Packit |
1470ea |
<title>Δείγμα πλήρους κώδικα</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/**
|
|
Packit |
1470ea |
* MessageQueueSource:
|
|
Packit |
1470ea |
*
|
|
Packit |
1470ea |
* This is a #GSource which wraps a #GAsyncQueue and is dispatched whenever a
|
|
Packit |
1470ea |
* message can be pulled off the queue. Messages can be enqueued from any
|
|
Packit |
1470ea |
* thread.
|
|
Packit |
1470ea |
*
|
|
Packit |
1470ea |
* The callbacks dispatched by a #MessageQueueSource have type
|
|
Packit |
1470ea |
* #MessageQueueSourceFunc.
|
|
Packit |
1470ea |
*
|
|
Packit |
1470ea |
* #MessageQueueSource supports adding a #GCancellable child source which will
|
|
Packit |
1470ea |
* additionally dispatch if a provided #GCancellable is cancelled.
|
|
Packit |
1470ea |
*/
|
|
Packit |
1470ea |
typedef struct {
|
|
Packit |
1470ea |
GSource parent;
|
|
Packit |
1470ea |
GAsyncQueue *queue; /* owned */
|
|
Packit |
1470ea |
GDestroyNotify destroy_message;
|
|
Packit |
1470ea |
} MessageQueueSource;
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/**
|
|
Packit |
1470ea |
* MessageQueueSourceFunc:
|
|
Packit |
1470ea |
* @message: (transfer full) (nullable): message pulled off the queue
|
|
Packit |
1470ea |
* @user_data: user data provided to g_source_set_callback()
|
|
Packit |
1470ea |
*
|
|
Packit |
1470ea |
* Callback function type for #MessageQueueSource.
|
|
Packit |
1470ea |
*/
|
|
Packit |
1470ea |
typedef gboolean (*MessageQueueSourceFunc) (gpointer message,
|
|
Packit |
1470ea |
gpointer user_data);
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
static gboolean
|
|
Packit |
1470ea |
message_queue_source_prepare (GSource *source,
|
|
Packit |
1470ea |
gint *timeout_)
|
|
Packit |
1470ea |
{
|
|
Packit |
1470ea |
MessageQueueSource *message_queue_source = (MessageQueueSource *) source;
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
return (g_async_queue_length (message_queue_source->queue) > 0);
|
|
Packit |
1470ea |
}
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
static gboolean
|
|
Packit |
1470ea |
message_queue_source_dispatch (GSource *source,
|
|
Packit |
1470ea |
GSourceFunc callback,
|
|
Packit |
1470ea |
gpointer user_data)
|
|
Packit |
1470ea |
{
|
|
Packit |
1470ea |
MessageQueueSource *message_queue_source = (MessageQueueSource *) source;
|
|
Packit |
1470ea |
gpointer message;
|
|
Packit |
1470ea |
MessageQueueSourceFunc func = (MessageQueueSourceFunc) callback;
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/* Pop a message off the queue. */
|
|
Packit |
1470ea |
message = g_async_queue_try_pop (message_queue_source->queue);
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/* If there was no message, bail. */
|
|
Packit |
1470ea |
if (message == NULL)
|
|
Packit |
1470ea |
{
|
|
Packit |
1470ea |
/* Keep the source around to handle the next message. */
|
|
Packit |
1470ea |
return TRUE;
|
|
Packit |
1470ea |
}
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/* @func may be %NULL if no callback was specified.
|
|
Packit |
1470ea |
* If so, drop the message. */
|
|
Packit |
1470ea |
if (func == NULL)
|
|
Packit |
1470ea |
{
|
|
Packit |
1470ea |
if (message_queue_source->destroy_message != NULL)
|
|
Packit |
1470ea |
{
|
|
Packit |
1470ea |
message_queue_source->destroy_message (message);
|
|
Packit |
1470ea |
}
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/* Keep the source around to consume the next message. */
|
|
Packit |
1470ea |
return TRUE;
|
|
Packit |
1470ea |
}
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
return func (message, user_data);
|
|
Packit |
1470ea |
}
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
static void
|
|
Packit |
1470ea |
message_queue_source_finalize (GSource *source)
|
|
Packit |
1470ea |
{
|
|
Packit |
1470ea |
MessageQueueSource *message_queue_source = (MessageQueueSource *) source;
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
g_async_queue_unref (message_queue_source->queue);
|
|
Packit |
1470ea |
}
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
static gboolean
|
|
Packit |
1470ea |
message_queue_source_closure_callback (gpointer message,
|
|
Packit |
1470ea |
gpointer user_data)
|
|
Packit |
1470ea |
{
|
|
Packit |
1470ea |
GClosure *closure = user_data;
|
|
Packit |
1470ea |
GValue param_value = G_VALUE_INIT;
|
|
Packit |
1470ea |
GValue result_value = G_VALUE_INIT;
|
|
Packit |
1470ea |
gboolean retval;
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/* The invoked function is responsible for freeing @message. */
|
|
Packit |
1470ea |
g_value_init (&result_value, G_TYPE_BOOLEAN);
|
|
Packit |
1470ea |
g_value_init (¶m_value, G_TYPE_POINTER);
|
|
Packit |
1470ea |
g_value_set_pointer (¶m_value, message);
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
g_closure_invoke (closure, &result_value, 1, ¶m_value, NULL);
|
|
Packit |
1470ea |
retval = g_value_get_boolean (&result_value);
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
g_value_unset (¶m_value);
|
|
Packit |
1470ea |
g_value_unset (&result_value);
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
return retval;
|
|
Packit |
1470ea |
}
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
static GSourceFuncs message_queue_source_funcs =
|
|
Packit |
1470ea |
{
|
|
Packit |
1470ea |
message_queue_source_prepare,
|
|
Packit |
1470ea |
NULL, /* check */
|
|
Packit |
1470ea |
message_queue_source_dispatch,
|
|
Packit |
1470ea |
message_queue_source_finalize,
|
|
Packit |
1470ea |
(GSourceFunc) message_queue_source_closure_callback,
|
|
Packit |
1470ea |
NULL,
|
|
Packit |
1470ea |
};
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/**
|
|
Packit |
1470ea |
* message_queue_source_new:
|
|
Packit |
1470ea |
* @queue: the queue to check
|
|
Packit |
1470ea |
* @destroy_message: (nullable): function to free a message, or %NULL
|
|
Packit |
1470ea |
* @cancellable: (nullable): a #GCancellable, or %NULL
|
|
Packit |
1470ea |
*
|
|
Packit |
1470ea |
* Create a new #MessageQueueSource, a type of #GSource which dispatches for
|
|
Packit |
1470ea |
* each message queued to it.
|
|
Packit |
1470ea |
*
|
|
Packit |
1470ea |
* If a callback function of type #MessageQueueSourceFunc is connected to the
|
|
Packit |
1470ea |
* returned #GSource using g_source_set_callback(), it will be invoked for each
|
|
Packit |
1470ea |
* message, with the message passed as its first argument. It is responsible for
|
|
Packit |
1470ea |
* freeing the message. If no callback is set, messages are automatically freed
|
|
Packit |
1470ea |
* as they are queued.
|
|
Packit |
1470ea |
*
|
|
Packit |
1470ea |
* Returns: (transfer full): a new #MessageQueueSource
|
|
Packit |
1470ea |
*/
|
|
Packit |
1470ea |
GSource *
|
|
Packit |
1470ea |
message_queue_source_new (GAsyncQueue *queue,
|
|
Packit |
1470ea |
GDestroyNotify destroy_message,
|
|
Packit |
1470ea |
GCancellable *cancellable)
|
|
Packit |
1470ea |
{
|
|
Packit |
1470ea |
GSource *source; /* alias of @message_queue_source */
|
|
Packit |
1470ea |
MessageQueueSource *message_queue_source; /* alias of @source */
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
g_return_val_if_fail (queue != NULL, NULL);
|
|
Packit |
1470ea |
g_return_val_if_fail (cancellable == NULL ||
|
|
Packit |
1470ea |
G_IS_CANCELLABLE (cancellable), NULL);
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
source = g_source_new (&message_queue_source_funcs,
|
|
Packit |
1470ea |
sizeof (MessageQueueSource));
|
|
Packit |
1470ea |
message_queue_source = (MessageQueueSource *) source;
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/* The caller can overwrite this name with something more useful later. */
|
|
Packit |
1470ea |
g_source_set_name (source, "MessageQueueSource");
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
message_queue_source->queue = g_async_queue_ref (queue);
|
|
Packit |
1470ea |
message_queue_source->destroy_message = destroy_message;
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
/* Add a cancellable source. */
|
|
Packit |
1470ea |
if (cancellable != NULL)
|
|
Packit |
1470ea |
{
|
|
Packit |
1470ea |
GSource *cancellable_source;
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
cancellable_source = g_cancellable_source_new (cancellable);
|
|
Packit |
1470ea |
g_source_set_dummy_callback (cancellable_source);
|
|
Packit |
1470ea |
g_source_add_child_source (source, cancellable_source);
|
|
Packit |
1470ea |
g_source_unref (cancellable_source);
|
|
Packit |
1470ea |
}
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
return source;
|
|
Packit |
1470ea |
}
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</listing>
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="further-examples">
|
|
Packit |
1470ea |
<title>Περισσότερα παραδείγματα</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Ο κώδικας μπορεί να είναι πιο πολύπλοκος από τα παραπάνω παραδείγματα. Στο <link href="http://nice.freedesktop.org/">libnice</link>, ένα προσαρμοσμένο GSource χρειάζεται για να λαμβάνει μια ομάδα υποδοχών που αλλάζει δυναμικά. Η υλοποίηση του γίνεται με το ComponentSource στο αρχείο <link href="http://cgit.freedesktop.org/libnice/libnice/tree/agent/component.c#n941">component.c</link> και παρουσιάζει μια πιο πολύπλοκη συνάρτηση προετοιμασίας.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Ένα άλλο παράδειγμα είναι ένας προσαρμοσμένος κώδικας για την επικοινωνία του GnuTLS με το GLib και την υλοποίηση GTlsConnection του. Το <link href="https://git.gnome.org/browse/glib-networking/tree/tls/gnutls/gtlsconnection-gnutls.c#n871">GTlsConnectionGnutlsSource </link> συγχρονίζει το κύριο νήμα με ένα νήμα TLS το οποίο εκτελεί τις εργασίες του TLS.
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
</page>
|