Основной цикл событий

The Main Event Loop — Управление всеми доступными источниками событий.

Краткое описание

#include <glib.h> GMainLoop; GMainLoop* g_main_loop_new (GMainContext *context, gboolean is_running); GMainLoop* g_main_loop_ref (GMainLoop *loop); void g_main_loop_unref (GMainLoop *loop); void g_main_loop_run (GMainLoop *loop); void g_main_loop_quit (GMainLoop *loop); gboolean g_main_loop_is_running (GMainLoop *loop); GMainContext* g_main_loop_get_context (GMainLoop *loop); #define g_main_new (is_running) #define g_main_destroy (loop) #define g_main_run (loop) #define g_main_quit (loop) #define g_main_is_running (loop) #define G_PRIORITY_HIGH #define G_PRIORITY_DEFAULT #define G_PRIORITY_HIGH_IDLE #define G_PRIORITY_DEFAULT_IDLE #define G_PRIORITY_LOW GMainContext; GMainContext* g_main_context_new (void); GMainContext* g_main_context_ref (GMainContext *context); void g_main_context_unref (GMainContext *context); GMainContext* g_main_context_default (void); gboolean g_main_context_iteration (GMainContext *context, gboolean may_block); #define g_main_iteration (may_block) gboolean g_main_context_pending (GMainContext *context); #define g_main_pending () GSource* g_main_context_find_source_by_id (GMainContext *context, guint source_id); GSource* g_main_context_find_source_by_user_data (GMainContext *context, gpointer user_data); GSource* g_main_context_find_source_by_funcs_user_data (GMainContext *context, GSourceFuncs *funcs, gpointer user_data); void g_main_context_wakeup (GMainContext *context); gboolean g_main_context_acquire (GMainContext *context); void g_main_context_release (GMainContext *context); gboolean g_main_context_is_owner (GMainContext *context); gboolean g_main_context_wait (GMainContext *context, GCond *cond, GMutex *mutex); gboolean g_main_context_prepare (GMainContext *context, gint *priority); gint g_main_context_query (GMainContext *context, gint max_priority, gint *timeout_, GPollFD *fds, gint n_fds); gint g_main_context_check (GMainContext *context, gint max_priority, GPollFD *fds, gint n_fds); void g_main_context_dispatch (GMainContext *context); void g_main_context_set_poll_func (GMainContext *context, GPollFunc func); GPollFunc g_main_context_get_poll_func (GMainContext *context); gint (*GPollFunc) (GPollFD *ufds, guint nfsd, gint timeout_); void g_main_context_add_poll (GMainContext *context, GPollFD *fd, gint priority); void g_main_context_remove_poll (GMainContext *context, GPollFD *fd); gint g_main_depth (void); GSource* g_main_current_source (void); #define g_main_set_poll_func (func) GSource* g_timeout_source_new (guint interval); GSource* g_timeout_source_new_seconds (guint interval); guint g_timeout_add (guint interval, GSourceFunc function, gpointer data); guint g_timeout_add_full (gint priority, guint interval, GSourceFunc function, gpointer data, GDestroyNotify notify); guint g_timeout_add_seconds (guint interval, GSourceFunc function, gpointer data); GSource* g_idle_source_new (void); guint g_idle_add (GSourceFunc function, gpointer data); guint g_idle_add_full (gint priority, GSourceFunc function, gpointer data, GDestroyNotify notify); gboolean g_idle_remove_by_data (gpointer data); typedef GPid; void (*GChildWatchFunc) (GPid pid, gint status, gpointer data); GSource* g_child_watch_source_new (GPid pid); guint g_child_watch_add (GPid pid, GChildWatchFunc function, gpointer data); guint g_child_watch_add_full (gint priority, GPid pid, GChildWatchFunc function, gpointer data, GDestroyNotify notify); GPollFD; GSource; void (*GSourceDummyMarshal) (void); GSourceFuncs; GSourceCallbackFuncs; GSource* g_source_new (GSourceFuncs *source_funcs, guint struct_size); GSource* g_source_ref (GSource *source); void g_source_unref (GSource *source); void g_source_set_funcs (GSource *source, GSourceFuncs *funcs); guint g_source_attach (GSource *source, GMainContext *context); void g_source_destroy (GSource *source); gboolean g_source_is_destroyed (GSource *source); void g_source_set_priority (GSource *source, gint priority); gint g_source_get_priority (GSource *source); void g_source_set_can_recurse (GSource *source, gboolean can_recurse); gboolean g_source_get_can_recurse (GSource *source); guint g_source_get_id (GSource *source); GMainContext* g_source_get_context (GSource *source); void g_source_set_callback (GSource *source, GSourceFunc func, gpointer data, GDestroyNotify notify); gboolean (*GSourceFunc) (gpointer data); void g_source_set_callback_indirect (GSource *source, gpointer callback_data, GSourceCallbackFuncs *callback_funcs); void g_source_add_poll (GSource *source, GPollFD *fd); void g_source_remove_poll (GSource *source, GPollFD *fd); void g_source_get_current_time (GSource *source, GTimeVal *timeval); gboolean g_source_remove (guint tag); gboolean g_source_remove_by_funcs_user_data (GSourceFuncs *funcs, gpointer user_data); gboolean g_source_remove_by_user_data (gpointer user_data);

Описание

Основной цикл событий управляет всеми возможными источниками событий для GLib и GTK+ приложений. Эти события могут исходить из любого числа различных типов источников таких как файловые дескрипторы (простые файлы, каналы или сокеты) и таймауты. Новые типы источников событий также могут быть добавлены используя g_source_attach().

Чтобы разрешить обработку множества независимых наборов источников в различных потоках (threads), каждый источник ассоциируется с GMainContext. GMainContext может выполняться только в единственном потоке, но источники могут добавляться в него и удаляться из него из других потоков.

Каждому источнику события назначается приоритет. Приоритет по умолчанию, G_PRIORITY_DEFAULT, равен 0. Значения меньше чем 0 обозначают более высокие приоритеты. Значения больше чем 0 обозначают более низкие приоритеты. События из источников с высоким приоритетом всегда выполняются перед событиями из источников с более низким приоритетом.

Бездействующие (Idle) функции могут быть также добавлены с присвоением приоритета. Они выполняются всякий раз когда события с более высоким приоритетом не готовы к выполнению.

Тип данных GMainLoop представляет основной цикл события. GMainLoop создаётся с помощью g_main_loop_new(). После добавления исходных источников событий, вызывается g_main_loop_run(). Это непрерывно проверяет новые события из каждого источника событий и отправляет их на обработку. Наконец, обработка события из одного из источников приводит к вызову g_main_loop_quit() для выхода из основного цикла, а g_main_loop_run() завершает работу.

Это позволяет создавать новые экземпляры GMainLoop рекурсивно. Часто используется в GTK+ приложениях при показе модальных диалоговых окон. Помните что источники события связаны со специфичным GMainContext, и будут проверены и посланы для всех основных циклов связанных с этим GMainContext.

GTK+ содержит оболочки некоторых из этих функций, например gtk_main(), gtk_main_quit() и gtk_events_pending().

Создание новых типов источников

Одна из необычных особенностей функциональности основного цикла GTK+ в том, что могут создаваться новые типы источников событий в дополнение к встроенным типам источников событий. Новый тип источника событий используется для обработки GDK событий. Новый тип источника создаётся с помощью наследования из GSource структуры. Наследуемый тип источника представляется структурой которая имеет в качестве первого элемента структуру GSource, а также другие элементы специфичные для нового типа источника. Для создания экземпляра нового типа источника, вызывается g_source_new() помещая размер наследуемой структуры и таблицы функций. Эти GSourceFuncs определяют поведение нового типа источника.

Новые типы источников в основном взаимодействуют с основным контекстом двумя способами. Они подготавливают функцию в GSourceFuncs способную установить тайм аут для определения максимального промежутка времени бездействия основного цикла перед повторной проверкой. Кроме того, или в дополнение, источник может добавить файловый дескриптор для установки проверки основного контекста используя g_source_add_poll().


Настройка основной итерации цикла

Одиночная итерация GMainContext может быть выполнена с помощью g_main_context_iteration(). В некоторых случаях, вместо этого желательно более точное управление деталями работы основного цикла, например объединяя GMainLoop с внешним основным циклом. В этом случае, вы можете вызвать непосредственно составные функции g_main_context_iteration(). Этими функциями являются g_main_context_prepare(), g_main_context_query(), g_main_context_check() и g_main_context_dispatch().

Операции этих функций могут быть лучше рассмотрены в терминах диаграммы состояния, как показано на Рисунке 1, “Состояния основного контекста”.

Рисунок 1. Состояния основного контекста

States of a Main Context

Детали

GMainLoop

typedef struct _GMainLoop GMainLoop;

Структура GMainLoop непрозрачный тип данных представляющий основной цикл события GLib или GTK+ приложений.


g_main_loop_new ()

GMainLoop* g_main_loop_new (GMainContext *context, gboolean is_running);

Создаёт новую структуру GMainLoop.

context : GMainContext (если NULL, используется контекст по умолчанию).
is_running : устанавливается в TRUE указывая на то, что цикл выполняется. Это не очень важно с момента вызова g_main_loop_run() который установит это значение в TRUE в любом случае.
Возвращает : новый GMainLoop.

g_main_loop_ref ()

GMainLoop* g_main_loop_ref (GMainLoop *loop);

Увеличивает счёт ссылок объекта GMainLoop на одну.

loop : GMainLoop
Возвращает : loop

g_main_loop_unref ()

void g_main_loop_unref (GMainLoop *loop);

Уменьшает количество ссылок на объект GMainLoop на одну. Если результат ноль, освобождает цикл и всю связанную с ним память.

loop : GMainLoop

g_main_loop_run ()

void g_main_loop_run (GMainLoop *loop);

Выполняет основной цикл до тех пор пока не вызвана g_main_loop_quit(). Если вызвана для потока (thread) GMainContext циклов, то выполняет событие из цикла, или просто ждёт.

loop : GMainLoop

g_main_loop_quit ()

void g_main_loop_quit (GMainLoop *loop);

Останавливает выполнение GMainLoop. Любые вызовы g_main_loop_run() для цикла будут возвращены.

loop : GMainLoop

g_main_loop_is_running ()

gboolean g_main_loop_is_running (GMainLoop *loop);

Выясняет выполняется ли в данный момент основной цикл через g_main_loop_run().

loop : GMainLoop.
Возвращает : TRUE если основной цикл в текущий момент выполняется.

g_main_loop_get_context ()

GMainContext* g_main_loop_get_context (GMainLoop *loop);

Возвращает GMainContext цикла (loop).

loop : GMainLoop.
Возвращает : GMainContext цикла loop

g_main_new()

#define g_main_new(is_running)

Внимание

g_main_new устарела начиная с версии 2.2 и не должна использоваться во вновь создаваемом коде. Используйте g_main_loop_new() вместо неё.

Создаёт новый GMainLoop для основного цикла по умолчанию.

is_running : устанавливается в значение TRUE указывая что основной цикл выполняется. Это не очень полезно с момента вызова g_main_run() которая установит TRUE в любом случае.
Возвращает : новый GMainLoop.

g_main_destroy()

#define g_main_destroy(loop)

Внимание

g_main_destroy устарела начиная с версии 2.2 и не должна использоваться во вновь создаваемом коде. Используйте g_main_loop_unref() вместо неё.

Освобождает память распределённую для GMainLoop.

loop : GMainLoop.

g_main_run()

#define g_main_run(loop)

Внимание

g_main_run устарела начиная с версии 2.2 и не должна использоваться во вновь создаваемом коде. Используйте g_main_loop_run() вместо неё.

Выполняет основной цикл до остановки.

loop : GMainLoop.

g_main_quit()

#define g_main_quit(loop)

Внимание

g_main_quit устарела начиная с версии 2.2 и не должна использоваться во вновь создаваемом коде. Используйте g_main_loop_quit() вместо неё.

Останавливает GMainLoop. Если g_main_run() был вызван для выполнения GMainLoop, он будет возвращен.

loop : GMainLoop.

g_main_is_running()

#define g_main_is_running(loop)

Внимание

g_main_is_running устарела начиная с версии 2.2 и не должна использоваться во вновь создаваемом коде. Используйте g_main_loop_is_running() вместо неё.

Проверяет выполняется ли основной цикл.

loop : GMainLoop.
Возвращает : TRUE если основной цикл выполняется.

G_PRIORITY_HIGH

#define G_PRIORITY_HIGH -100

Используется для повышения приоритета источников событий. Не используется внутри GLib или GTK+.


G_PRIORITY_DEFAULT

#define G_PRIORITY_DEFAULT 0

Используется для приоритета по умолчанию для источника события. В GLib этот приоритет используется когда добавляется функция-таймаут с помощью g_timeout_add(). В GDK этот приоритет используется для событий из X server.


G_PRIORITY_HIGH_IDLE

#define G_PRIORITY_HIGH_IDLE 100

Используется для повышения приоритета idle функций. GTK+ используется G_PRIORITY_HIGH_IDLE + 10 для операций изменения размера, а G_PRIORITY_HIGH_IDLE + 20 операций перерисовки. (Это выполняется для гарантии что любое изменение размера обрабатывается перед любой перерисовкой, чтобы виджеты не перерисовывались лишний раз.)


G_PRIORITY_DEFAULT_IDLE

#define G_PRIORITY_DEFAULT_IDLE 200

Используется для приоритета idle функций по умолчанию. В GLib этот приоритет используется когда добавляются idle функции с помощью g_idle_add().


G_PRIORITY_LOW

#define G_PRIORITY_LOW 300

Этот очень медленный приоритет используется для фоновых задач. Не используется внутри GLib или GTK+.


GMainContext

typedef struct _GMainContext GMainContext;

Структура GMainContext это непрозрачный тип данных представляющий наборы источников для обработки в основном цикле.


g_main_context_new ()

GMainContext* g_main_context_new (void);

Создаёт новую GMainContext структуру.

Возвращает : новая GMainContext

g_main_context_ref ()

GMainContext* g_main_context_ref (GMainContext *context);

Увеличивает число ссылок на GMainContext объект на одну.

context : GMainContext
Возвращает : помещённый context (Начиная с версии 2.6)

g_main_context_unref ()

void g_main_context_unref (GMainContext *context);

Уменьшает количество ссылок на GMainContext объект на одну. Если результат ноль, освобождает контекст и всю связанную с ним память.

context : GMainContext

g_main_context_default ()

GMainContext* g_main_context_default (void);

Возвращает основной контекст по умолчанию. Основной контекст используется для функции основного цикла, когда основной цикл явно не определён.

Возвращает : основной контекст по умолчанию.

g_main_context_iteration ()

gboolean g_main_context_iteration (GMainContext *context, gboolean may_block);

Выполняет единственную итерацию для данного основного цикла. Это включает проверку готовы ли любые источники событий к обработке, если нет готовых источников событий и may_block равен TRUE, ждёт подготовки источника, затем отсылает самый высокий приоритет источнику событий который уже готов. Помните, что даже когда may_block равен TRUE, фукция g_main_context_iteration() всё же может вернуть FALSE, так как ожидание может быть прервано не только когда будет готов источник событий, но и по другим причинам.

context : GMainContext (если NULL, используется контекст по умолчанию)
may_block : можно ли заблокировать вызов.
Возвращает : TRUE если события были отправлены.

g_main_iteration()

#define g_main_iteration(may_block)

Внимание

g_main_iteration устарела начиная с версии 2.2 и не должна использоваться во вновь создаваемом коде. Используйте g_main_context_iteration() вместо неё.

Выполняет единственную итерацию для GMainContext по умолчанию.

may_block : устанавливается в значение TRUE если нужна блокировка (то есть ожидание) пока источник события не будет готов. Возвращается после обработки источника. Если установлено в FALSE возвращается немедленно если нет источника для обработки.
Возвращает : TRUE если ещё есть события на рассмотрении.

g_main_context_pending ()

gboolean g_main_context_pending (GMainContext *context);

Проверяет имеют ли источники ожидающие обработки события для данного контекста.

context : GMainContext (если NULL, используется контекст по умолчанию)
Возвращает : TRUE если есть события на рассмотрении.

g_main_pending()

#define g_main_pending()

Внимание

g_main_pending устарела начиная с версии 2.2 и не должна использоваться во вновь создаваемом коде. Используйте g_main_context_pending() вместо неё.

Проверяет есть ли события ожидающие обработки для GMainContext по умолчанию.

Возвращает : TRUE если есть события ожидающие обработки.

g_main_context_find_source_by_id ()

GSource* g_main_context_find_source_by_id (GMainContext *context, guint source_id);

Находит GSource данной пары контекста и ID.

context : GMainContext (если NULL, используется контекст по умолчанию)
source_id : ID источника, который возвращает g_source_get_id().
Возвращает : GSource если найден, иначе NULL

g_main_context_find_source_by_user_data ()

GSource* g_main_context_find_source_by_user_data (GMainContext *context, gpointer user_data);

Находит источник с полученными пользовательскими данными для callback-функции. Если существует множество источников с такими пользовательскими данными, будет возвращён первый найденный.

context : GMainContext
user_data : user_data для callback-функции.
Возвращает : источник, если найден, иначе NULL

g_main_context_find_source_by_funcs_user_data ()

GSource* g_main_context_find_source_by_funcs_user_data (GMainContext *context, GSourceFuncs *funcs, gpointer user_data);

Находит источник с данной исходной функцией и пользовательскими данными. Если существует множество источников с такими же функциями и данными, возвращается первый найденный.

context : GMainContext (если NULL, используется контекст по умолчанию).
funcs : source_funcs помещаемая в g_source_new().
user_data : пользовательские данные из callback-функции.
Возвращает : источник, если был найден, иначе NULL

g_main_context_wakeup ()

void g_main_context_wakeup (GMainContext *context);

Если context в настоящее время ожидает в poll(), прерывает poll(), и продолжает интерактивный процесс.

context : GMainContext

g_main_context_acquire ()

gboolean g_main_context_acquire (GMainContext *context);

Попытается стать владельцем указанного контекста. Если кто то другой владеет контекстом, немедленно возвращает FALSE. Владение является правильной рекурсией: владелец может запросить владение снова и отменить владение когда g_main_context_release() вызывается столько же раз сколько g_main_context_acquire().

Вы должны быть владельцем контекста прежде чем вы сможете вызвать g_main_context_prepare(), g_main_context_query(), g_main_context_check(), g_main_context_dispatch().

context : GMainContext
Возвращает : TRUE если операция выполнена и поток теперь владеет данным context.

g_main_context_release ()

void g_main_context_release (GMainContext *context);

Отменяет владение контекстом предварительно полученное потоком с помощью g_main_context_acquire(). Если контекст был получен множество раз, отменяет владение только когда g_main_context_release() вызван соответствующее количество раз.

context : GMainContext

g_main_context_is_owner ()

gboolean g_main_context_is_owner (GMainContext *context);

Определяет владеет ли этот поток (рекурсивно) GMaincontext. Это полезно знать перед ожиданием в другом потоке который может быть блокирован для получения владения данным context.

context : GMainContext
Возвращает : TRUE если текущий поток владеет context.

Начиная с версии 2.10


g_main_context_wait ()

gboolean g_main_context_wait (GMainContext *context, GCond *cond, GMutex *mutex);

Пытается получить владение определенным контекстом, так же как с помощью g_main_context_acquire(). Но если другой поток владеет контекстом, автоматически сбрасывается в mutex и ждёт в cond пока этот владелец освободит владение или пока cond просигнализирует попытаться снова стать владельцем.

context : GMainContext
cond : переменное условие
mutex : взаимное исключение, имеющееся в настоящий момент
Возвращает : TRUE если операция выполнена, и данный поток теперь владеет context.

g_main_context_prepare ()

gboolean g_main_context_prepare (GMainContext *context, gint *priority);

Подготавливает для опроса источник внутри основного цикла. Результирующая информация для опроса определяется с помощью вызова g_main_context_query().

context : GMainContext
priority : расположение для хранения приоритета готового источника с высоким приоритетом.
Возвращает : TRUE если некоторый источник готов для предварительной отправки опроса.

g_main_context_query ()

gint g_main_context_query (GMainContext *context, gint max_priority, gint *timeout_, GPollFD *fds, gint n_fds);

Определяет информацию необходимую для опроса этого основного цикла.

context : GMainContext
max_priority : максимальный приоритет источника для проверки
timeout_ : расположение для хранения пауз используемых в опросах
fds : расположение для хранения GPollFD отчётов опросов.
n_fds : длина fds.
Возвращает : количество отчётов фактически сохрнённых в fds, или, если больше чем n_fds отчётов для хранения, количество отчётов которое необходимо сохранить.

g_main_context_check ()

gint g_main_context_check (GMainContext *context, gint max_priority, GPollFD *fds, gint n_fds);

Помещает результат опроса обратно в основной цикл.

context : GMainContext
max_priority : максимальное число приоритета источника для проверки
fds : массив GPollFD's которые были помещены в последний вызов g_main_context_query()
n_fds : значение возвращаемое функцией g_main_context_query()
Возвращает : TRUE если некоторый источник готов для отправки.

g_main_context_dispatch ()

void g_main_context_dispatch (GMainContext *context);

Отправляет все ожидающие обработки источники.

context : GMainContext

g_main_context_set_poll_func ()

void g_main_context_set_poll_func (GMainContext *context, GPollFunc func);

Устанавливает функцию используемую для обработки опроса дескриптора файла. Используется вместо poll() системой вызовов (или функцией замены GLib's, которая используется когда poll() не доступен).

Эта функция может использоваться для интеграции GLib цикла события с внешним циклом события.

context : GMainContext
func : функция для вызова опроса всех дескрипторов файла

g_main_context_get_poll_func ()

GPollFunc g_main_context_get_poll_func (GMainContext *context);

Получает функцию опроса установленную с помощью g_main_context_set_poll_func().

context : GMainContext
Возвращает : функция опроса

GPollFunc ()

gint (*GPollFunc) (GPollFD *ufds, guint nfsd, gint timeout_);

Определяет тип функции помещаемой в g_main_context_set_poll_func(). Семантика функции должна соответствовать системному вызову poll().

ufds : массив GPollFD элементов.
nfsd : количество элементов в ufds.
timeout_ : максимальное время ожидания события дескриптора файла. Отрицательное значение указывает на бесконечное время ожидания.
Возвращает : количество GPollFD элементов которые имеют события или сообщения об ошибках, или -1 если произошла ошибка.

g_main_context_add_poll ()

void g_main_context_add_poll (GMainContext *context, GPollFD *fd, gint priority);

Добавляет дескриптор файла в набор дескрипторов файлов опрашиваемых для данного контекста. Это очень редко используется непосредственно. Вместо этого обычно источник события использует g_source_add_poll().

context : GMainContext (или NULL для контекста по умолчанию)
fd : GPollFD структура содержащая информацию о дескрипторах файла для просмотра.
priority : приоритет для этого дескриптора файла должен быть таким же как приоритет используемый для g_source_attach() чтобы убедиться что дескриптор файла будет опрошен всякий раз когда может понадобиться результат.

g_main_context_remove_poll ()

void g_main_context_remove_poll (GMainContext *context, GPollFD *fd);

Удаляет дескриптор файла из набора дескрипторов файла опрашиваемых для определенного контекста.

context : GMainContext
fd : GPollFD предварительно добавленный с помощью g_main_context_add_poll()

g_main_depth ()

gint g_main_depth (void);

Возвращает значение основного цикла рекурсии в текущем потоке

Возвращает : глубину стека вызовов для g_main_context_dispatch() в любом GMainContext текущего потока. Таким образом, когда вызов из верхнего уровня, она выдаёт 0. Когда вызов изнутри callback-функции g_main_context_iteration() (или g_main_loop_run(), и т.д.) она возвращает 1. Когда вызов изнутри callback-функции для рекурсивного вызова g_main_context_iterate(), она возвращает 2. И так далее. Эта функция полезна в ситуациях описанных ниже: Представьте чрезвычайно простую систему "сборки мусора".

Пример 1.  static GList *free_list; gpointer allocate_memory (gsize size) { gpointer result = g_malloc (size); free_list = g_list_prepend (free_list, result); return result; } void free_allocated_memory (void) { GList *l; for (l = free_list; l; l = l->next); g_free (l->data); g_list_free (free_list); free_list = NULL; } [...] while (TRUE); { g_main_context_iteration (NULL, TRUE); free_allocated_memory(); }

Это работает в приложении, однако, если вы захотите сделать тоже самое в библиотеке, возникнет много проблем, так как вы не можете больше контролировать основной цикл. Вы можете подумать, что можно просто использовать idle функцию создав вызов для free_allocated_memory(), но это не работает, так как idle функция вызывается из рекурсивной callback-функции. Это может быть исправлено при помощи g_main_depth()

Пример 2.  gpointer allocate_memory (gsize size) { FreeListBlock *block = g_new (FreeListBlock, 1);\ block->mem = g_malloc (size); block->depth = g_main_depth(); free_list = g_list_prepend (free_list, block); return block->mem; } void free_allocated_memory (void) { GList *l; int depth = g_main_depth(); for (l = free_list; l; ); { GList *next = l->next; FreeListBlock *block = l->data; if (block->depth > depth) { g_free (block->mem); g_free (block); free_list = g_list_delete_link (free_list, l); } l = next; } }

Есть искушение использовать g_main_depth() для решения проблем с повторными входами (reentrancy). Например, во время ожидания данных получаемых из сети в ответ на пункт меню, пункт меню мог бы быть выбран снова. Может показаться, что можно было бы сделать немедленное возвращение callback-функции пункта меню и ничего не делать если g_main_depth() возвращает значение больше 1. Однако, этого нужно избегать, так как пользователь выбрав меню ничего не делает. Кроме того, вам пришлось бы добавлять эти проверки на протяжении всего кода, так как несомненно пользователь мог сделать разные вещи. Вместо этого вы можете использовать следующие методы:

  1. Использовать gtk_widget_set_sensitive() или модальные диалоги, чтобы запретить пользователю взаимодействовать с элементами во время выполнения рекурсии основного цикла.

  2. Запретить рекурсию основного цикла в ситуациях когда вы не можете обрабатывать произвольные callback-функции. Вместо этого, структурируйте ваш код так, чтобы вы просто возвращались в основной цикл и затем получали вызов снова когда есть ещё работа для выполнения.


g_main_current_source ()

GSource* g_main_current_source (void);

Возвращает текущий источник для этого потока.

Возвращает : текущий источник или NULL.

Начиная с версии 2.12


g_main_set_poll_func()

#define g_main_set_poll_func(func)

Внимание

g_main_set_poll_func устарела начиная с версии 2.2 и не должна использоваться во вновь создаваемом коде. Используйте g_main_context_set_poll_func() вместо неё.

Устанавливает функцию используемую для обработки опроса дескрипторов файла основного контекста по умолчанию.

func : функция для вызова опроса всех дескрипторов файла.

g_timeout_source_new ()

GSource* g_timeout_source_new (guint interval);

Создаёт новый источник пауз.

Источник первоначально не связан ни с каким GMainContext и должен быть добавлен с помощью g_source_attach() перед выполнением этой функции.

interval : интервал времени ожидания в милесекундах.
Возвращает : вновь созданный источник времени ожидания

g_timeout_source_new_seconds ()

GSource* g_timeout_source_new_seconds (guint interval);

Создаёт новый источник времени ожидания.

Первоначально не связан ни с каким GMainContext и должен быть добавлен с помощью g_source_attach() перед выполнением. Точность данного источника времени ожидания измеряется в секундах.

interval : интервал времени ожидания в секундах
Возвращает : вновь созданный источник времени ожидания

Начиная с версии 2.14


g_timeout_add ()

guint g_timeout_add (guint interval, GSourceFunc function, gpointer data);

Заставляет вызывать функцию с равномерными интервалами, с приоритетом по умолчанию G_PRIORITY_DEFAULT. Функция вызывается до тех пор пока не возвращено FALSE, в этой точке время ожидания автоматически уничтожается и функция больше не вызывается. Первый вызов функции выполняется в конце первого interval.

Помните что функции паузы могут быть отсрочены, из-за обработки других событий источника. Таким образом нельзя рассчитывать на точную синхронизацию. После каждого вызова функции паузы, время следующей паузы пересчитывается исходя из текущего времени и данного интервала (это не учитывает время потерянное во время задержек).

Если вы хотите иметь таймер в "секундах" и не беспокоиться о точном времени первого вызова таймера, используйте функцию g_timeout_add_seconds(); она позволяет большую оптимизацию и более эффективное использование мощностей системы.

interval : время между вызовами функции, в миллисекундах (1/1000 секунды)
function : вызываемая функция
data : данные помещаемые в function
Возвращает : ID (больше чем 0) источника события.

g_timeout_add_full ()

guint g_timeout_add_full (gint priority, guint interval, GSourceFunc function, gpointer data, GDestroyNotify notify);

Заставляет вызывать функцию с регулярными интервалами, с данным приоритетом. Функция вызывается до тех пор пока возвращено значение FALSE, в этой точке время ожидания автоматически уничтожается и функция больше не вызывается. Функция notify вызывается когда пауза уничтожена. Первый вызов функции происходит в конце первого interval.

Помните что функции паузы могут быть отсрочены, из-за обработки других событий источника. Таким образом нельзя рассчитывать на точную синхронизацию. После каждого вызова функции паузы, время следующей паузы пересчитывается исходя из текущего времени и данного интервала (это не учитывает время потерянное во время задержек).

priority : приоритет idle источника. Обычно в диапазоне между G_PRIORITY_DEFAULT_IDLE и G_PRIORITY_HIGH_IDLE.
interval : время между вызовами функций, в миллисекундах (1/1000 секунды)
function : вызываемая функция
data : данные помещаемые в function
notify : функция вызываемая когда интервал удалён, или NULL
Возвращает : ID (больше 0) источника события.

g_timeout_add_seconds ()

guint g_timeout_add_seconds (guint interval, GSourceFunc function, gpointer data);

Вызывает функцию через равномерные интервалы, с приоритетом по умолчанию, G_PRIORITY_DEFAULT. Функция вызывается до тех пор пока не возвращено значение FALSE, в этой точке интервал автоматически уничтожается и функция больше не вызывается.

В отличии от g_timeout_add(), эта функция оперирует секундной точностью. Начальная точка таймера определяется реализацией и реализация как ожидается соберёт множество таймеров в группу, чтобы они все запускались в одно время. Чтобы позволить эту группировку, interval для первого таймера округляется и может отклониться на одну секунду от указанного интервала. Последующие итерации таймера будут в общем выполняться в указанном интервале.

Помните что тайм аут функции могут быть отсрочены, из-за обработки других источников событий. Таким образом на них нельзя рассчитывать при точной синхронизации. После каждого вызова тайм аут функции, время следующей паузы пересчитывается исходя из текущего времени и полученного интервала interval

Если вам нужны более точные расчеты нежели секунды, используйте вместо этой функции g_timeout_add().

Группирование таймеров для старта в одно и тоже время приводит к более эффективному использованию CPU, поэтому если ваш таймер в секундах и находится в множестве однотипных и вам не требуется запуск первого таймера с точностью до 1 секунды, использование g_timeout_add_second() предпочтительней чем g_timeout_add().

interval : время между запусками функций, в секундах
function : функция для вызова
data : данные для помещения в function
Возвращает : ID (больше чем 0) источника события.

Начиная с версии 2.14


g_idle_source_new ()

GSource* g_idle_source_new (void);

Создаёт новый пустой (idle) источник.

Источник первоначально не связан ни с каким GMainContext и должен быть добавлен в него с помощью g_source_attach() перед выполнением. Помните что приоритетом по умолчанию idle источника является G_PRIORITY_DEFAULT_IDLE, тогда как другие источники по умолчанию имеют приоритет G_PRIORITY_DEFAULT.

Возвращает : вновь созданный пустой (idle) источник

g_idle_add ()

guint g_idle_add (GSourceFunc function, gpointer data);

Добавляет функцию которая вызывается каждый раз когда нет обрабатываемого события с более высоким приоритетом в основном цикле по умолчанию. Функция получает по умолчанию idle приоритет, G_PRIORITY_DEFAULT_IDLE. Если функция возвращает FALSE она автоматически удаляется из списка источника событий и больше не вызывается.

function : функция для вызова
data : данные для помещения в function.
Возвращает : ID (больше 0) источника события.

g_idle_add_full ()

guint g_idle_add_full (gint priority, GSourceFunc function, gpointer data, GDestroyNotify notify);

Добавляет функцию для вызова когда нет события с более высоким приоритетом на рассмотрении. Если функция возвращает FALSE, то автоматически удаляется из списка источника событий и больше не вызывается.

priority : приоритет idle источника. Обычно в диапазоне между G_PRIORITY_DEFAULT_IDLE и G_PRIORITY_HIGH_IDLE.
function : функция для вызова
data : данные помещаемые в function
notify : функция вызываемая при удалении idle функции, или NULL
Возвращает : ID (больше 0) источника события.

g_idle_remove_by_data ()

gboolean g_idle_remove_by_data (gpointer data);

Удаляет idle функцию с полученными данными.

data : данные для idle источников callback-функций.
Возвращает : TRUE если idle источник найден и удалён.

GPid

typedef int GPid;

Тип содержащий идентификатор процесса. В Unix, процессы идентифицируются с помощью process id (целочисленное), в то время как в Windows используются маркеры процесса (которые являются указателями).


GChildWatchFunc ()

void (*GChildWatchFunc) (GPid pid, gint status, gpointer data);

Тип функций для вызова при существовании дочерних процессов.

pid : id дочернего процесса
status : Информация состояния дочернего процесса, более подробную информацию об этом поле смотрите в waitpid(2)
data : пользовательские данные помещаемые в g_child_watch_add()

g_child_watch_source_new ()

GSource* g_child_watch_source_new (GPid pid);

Создаёт новый child_watch источник.

Первоначально источник не связан ни с каким GMainContext и должен быть добавлен в него с помощью g_source_attach() перед использованием.

Помните, что дочерний процесс наблюдения может использоваться только совместно с g_spawn... когда используется флаг G_SPAWN_DO_NOT_REAP_CHILD.

Помните, что на платформах где GPid должен быть явно закрыт (смотрите g_spawn_close_pid()) pid не должен закрываться пока источник активен. Обычно, вам нужно вызывать g_spawn_close_pid() в callback-функции для источника.

Помните также что использование g_child_watch_source_new() не совместимо с вызовом waitpid(-1) в приложении. Вызов waitpid() для индивидуального pids будет прекрасно работать.

pid : process id дочернего процесса для наблюдения. В Windows, МАРКЕР (HANDLE) для процесса наблюдения (который фактически не является дочерним).
Возвращает : вновь созданный дочерний процесс наблюдения

Начиная с версии 2.4


g_child_watch_add ()

guint g_child_watch_add (GPid pid, GChildWatchFunc function, gpointer data);

Устанавливает функцию для вызова при существовании дочернего процесса указанного с помощью pid, с приоритетом по умолчанию G_PRIORITY_DEFAULT.

Помните что на платформах где GPid должен быть явно закрыт (смотрите g_spawn_close_pid()) pid не должен закрываться пока источник активен. Обычно, вам потребуется вызвать g_spawn_close_pid() в callback-функции для источника.

GLib поддерживает только один вызов callback-функции через process id.

pid : process id дочернего процесса для наблюдения
function : функция для вызова
data : данные помещаемые в function
Возвращает : ID (больше 0) источника события.

Начиная с версии 2.4


g_child_watch_add_full ()

guint g_child_watch_add_full (gint priority, GPid pid, GChildWatchFunc function, gpointer data, GDestroyNotify notify);

Устанавливает функцию вызываемую когда дочерний процесс указанный с помощью pid существует, с приоритетом по умолчанию G_PRIORITY_DEFAULT.

Помните что на платформах где GPid должен быть закрыт явно (смотрите g_spawn_close_pid()) pid не должен закрываться пока источник активен. Обычно, вам необходимо вызвать g_spawn_close_pid() в callback-функции для источника.

GLib поддерживает только единственный вызов callback-функции через process id.

priority : приоритет idle источника. Обычно в диапазоне между G_PRIORITY_DEFAULT_IDLE и G_PRIORITY_HIGH_IDLE.
pid : process id дочернего процесса для наблюдения
function : вызываемая функция
data : данные помещаемые в function
notify : функция вызываемая при удалении idle функции, или NULL
Возвращает : ID (больше 0) источника события.

Начиная с версии 2.4


GPollFD

typedef struct { gint fd; gushort events; gushort revents; } GPollFD;

gint fd; дескриптор файла для опроса (или МАРКЕР (HANDLE) на Win32 платформах).
gushort events; поразарядная комбинация флажков из GIOCondition, определяющая события для опроса. Обычно для чтения из дескриптора файла вы должны использовать G_IO_IN | G_IO_HUP | G_IO_ERR, а для записи вы должны использовать G_IO_OUT | G_IO_ERR.
gushort revents; поразрядная комбинация флажков из GIOCondition, возвращаемая из функции poll() указывая какие события произошли.


GSource

typedef struct { } GSource;

Структура GSource непрозрачного типа данных представляющих источник события.


GSourceDummyMarshal ()

void (*GSourceDummyMarshal) (void);

Это просто метка для GClosureMarshal, которая не используется по причине зависимостей.


GSourceFuncs

typedef struct { gboolean (*prepare) (GSource *source, gint *timeout_); gboolean (*check) (GSource *source); gboolean (*dispatch) (GSource *source, GSourceFunc callback, gpointer user_data); void (*finalize) (GSource *source); /* Может быть NULL */ /* Для использования g_source_set_closure */ GSourceFunc closure_callback; GSourceDummyMarshal closure_marshal; /* Фактически тип GClosureMarshal */ } GSourceFuncs;

Структура GSourceFuncs содержит таблицу функций используемых для обработки источника события основным способом.

prepare Вызывается перед опросом всех дескрипторов файла. Если источник может определить что он готов (не ждет результата вызова poll()) он должен вернуть TRUE. Он также может вернуть значение timeout_ которое должно быть максимальным временем ожидания (в миллесекундах) помещаемым в вызов poll(). Фактический используемый тайм аут будет равен -1 если все источники вернут -1, или он будет меньше всех возвращённых значений timeout_ которые были >= 0.
check Вызывается после опроса всех дескрипторов файла. Источник должен вернуть TRUE если он готов для отправки. Помните что пройдёт некоторое время так как была вызвана предварительно подготовленная функция, поэтому источник должен проверяться снова.
dispatch Вызывается после отправки источника события, после того как он возвратил TRUE или в prepare или check функции. Функция dispatch помещает callback-функцию и данные. callback-функция может быть NULL если источник никогда не связывается с callback-функцией используя g_source_set_callback(). Функция dispatch должна вызывать callback-функцию с user_data и независимо от дополнительных параметров необходимых для этого типа источника события.
finalize Вызывается когда источник окончательно реализован (finalized).

Для idle источников, функции prepare и check всегда возвращают TRUE указывая что источник всегда готов к обработке. Функция prepare также возвращает значение тайм аута равное 0, чтобы гарантировать что вызов poll() не заблокируется (так как это было бы впустую потраченным временем которое можно потратить на idle функцию).

Для источников, обе функции prepare и check возвращают TRUE если интервал тайм аута истек. Функция prepare также возвращает значение таймаута, чтобы гарантировать что вызов poll() не блокируется слишком долго и не пропустит следующий таймаут.

Для источников дескриптора файлов, функция prepare обычно возвращает FALSE, так как нужно ждать пока poll() будет вызвана перед определением нужно ли обрабатывать какое нибудь событие. Это установит возвращённый тайм аут в значение -1 указывая что не знает как долго блокирован вызов poll(). В функции check, проверяет результат вызова poll() чтобы видеть встречалось ли необходимое условие, и возвращает TRUE.


GSourceCallbackFuncs

typedef struct { void (*ref) (gpointer cb_data); void (*unref) (gpointer cb_data); void (*get) (gpointer cb_data, GSource *source, GSourceFunc *func, gpointer *data); } GSourceCallbackFuncs;

Структура GSourceCallbackFuncs содержит функции для управления callback-объектами.

ref () Вызывается при добавлении ссылки на callback-объект.
unref () Вызывается при сбросе ссылки на callback-объект.
get () Вызывается для извлечения callback-функции и данных из callback-объекта.

g_source_new ()

GSource* g_source_new (GSourceFuncs *source_funcs, guint struct_size);

Содаёт новую структуру GSource. Размер определяется для создания структур полученных из GSource который содержит дополнительные данные. Помещаемый размер должен быть как минимум sizeof (GSource).

Первоначально источник не связан ни с каким GMainContext и должен быть добавлен в него с помощью g_source_attach() перед использованием.

source_funcs : структура содержащая функции которые реализуют поведение источников.
struct_size : размер структуры GSource для создания.
Возвращает : вновь созданный GSource.

g_source_ref ()

GSource* g_source_ref (GSource *source);

Увеличивает количество ссылок источника на одну.

source : GSource
Возвращает : source

g_source_unref ()

void g_source_unref (GSource *source);

Уменьшает количество ссылок источника на одну. Если в результате получается ноль, источник и связанная с ним память освобождаются.

source : GSource

g_source_set_funcs ()

void g_source_set_funcs (GSource *source, GSourceFuncs *funcs);

Отсоединяет функции от источника (может использоваться для отмены выполнения по умолчанию).

source : GSource
funcs : новый GSourceFuncs

Начиная с версии 2.12


g_source_attach ()

guint g_source_attach (GSource *source, GMainContext *context);

Добавляет GSource в context так чтобы он выполнялся внутри контекста.

source : GSource
context : GMainContext (если NULL, используется контекст по умолчанию)
Возвращает : ID (больше 0) для источника внутри GMainContext.

g_source_destroy ()

void g_source_destroy (GSource *source);

Удаляет источник из его GMainContext, если есть, и маркирует его как уничтоженный. Источник не может в последствии добавляться в другой контекст.

source : GSource

g_source_is_destroyed ()

gboolean g_source_is_destroyed (GSource *source);

Определяет уничтожен ли source.

Это важно когда вы оперируете с вашими объектами внутри idle обработчиков, но при этом возможно освободили объект перед отправкой вашего idle обработчика.

static gboolean idle_callback (gpointer data) { SomeWidget *self = data; GDK_THREADS_ENTER (); /* заполняется самостоятельно */ self->idle_id = 0; GDK_THREADS_LEAVE (); return FALSE; } static void some_widget_do_stuff_later (SomeWidget *self) { self->idle_id = g_idle_add (idle_callback, self); } static void some_widget_finalize (GObject *object) { SomeWidget *self = SOME_WIDGET (object); if (self->idle_id) g_source_remove (self->idle_id); G_OBJECT_CLASS (parent_class)->finalize (object); }

Этот пример завершится неудачей в много-потоковом приложении если виджет уничтожен перед запуском idle обработчика из-за использования после освобождения в обратном вызове. Решение этой специфической проблемы в том, чтобы проверить уничтожен ли уже источник в обратном вызове.

static gboolean idle_callback (gpointer data) { SomeWidget *self = data; GDK_THREADS_ENTER(); if (!g_source_is_destroyed (g_main_current_source())) { /* заполняется самостоятельно */ } GDK_THREADS_LEAVE(); return FALSE; }

source : GSource
Возвращает : TRUE если источник уничтожен

Начиная с версии 2.12


g_source_set_priority ()

void g_source_set_priority (GSource *source, gint priority);

Устанавливает приоритет источника. Во время выполнения основного цикла, источник отправляется если готов и нет готовых источников с более высоким приоритетом (с меньшим номером).

source : GSource
priority : новый приоритет.

g_source_get_priority ()

gint g_source_get_priority (GSource *source);

Определяет приоритет источника.

source : GSource
Возвращает : приоритет источника

g_source_set_can_recurse ()

void g_source_set_can_recurse (GSource *source, gboolean can_recurse);

Устанавливает может ли источник вызываться рекурсивно. Если параметр can_recurse равен TRUE, то во время отправки источник обрабатывается обычно. Иначе, все процессы источника блокируются до возвращения функции отправки.

source : GSource
can_recurse : разрешена ли рекурсия для данного источника

g_source_get_can_recurse ()

gboolean g_source_get_can_recurse (GSource *source);

Проверяет разрешено ли источнику вызываться рекурсивно. (смотрите g_source_set_can_recurse()).

source : GSource
Возвращает : разрешена ли рекурсия.

g_source_get_id ()

guint g_source_get_id (GSource *source);

Возвращает число ID для специального источника. ID источника это положительное целое которое является уникальным внутри определённого контекста основного цикла. Обратное преобразование из ID в источник выполняется с помощью g_main_context_find_source_by_id().

source : GSource
Возвращает : ID (больше 0) для источника

g_source_get_context ()

GMainContext* g_source_get_context (GSource *source);

Определяет GMainContext с которым связан источник. Вызов этой функции для уничтоженного источника недопустим.

source : GSource
Возвращает : GMainContext с которым связан источник, или NULL если контекст не имеет добавленного источника.

g_source_set_callback ()

void g_source_set_callback (GSource *source, GSourceFunc func, gpointer data, GDestroyNotify notify);

Устанавливает callback-функцию для источника. callback-функция для источника вызывается из dispatch функции источников.

Точный тип func зависит от типа источника; то есть вы не должны рассчитывать на func вызванную с data как её первый параметр.

Обычно вам не нужно использовать эту функцию. Вместо неё используйте функции определённого типа для используемого вами типа источника.

source : источник
func : callback-функция
data : данные помещаемые в callback-функцию
notify : функция вызываемая когда data больше не используются, или NULL.

GSourceFunc ()

gboolean (*GSourceFunc) (gpointer data);

Конкретизирует тип функции помещаемой в g_timeout_add(), g_timeout_add_full(), g_idle_add() и g_idle_add_full().

data : данные помещаемые в функцию, устанавливаются когда источник создаётся одной из упомянутых выше функцией.
Возвращает : должна вернуть FALSE если источник должен быть удалён.

g_source_set_callback_indirect ()

void g_source_set_callback_indirect (GSource *source, gpointer callback_data, GSourceCallbackFuncs *callback_funcs);

Устанавливает callback-функцию хранения данных как refcounted callback "object". Это используется внутренне. Помните что вызов g_source_set_callback_indirect() предполагает, что начат подсчёт ссылок на callback_data, и поэтому callback_funcs->unref будет в конечном счёте вызван больше чем callback_funcs->ref.

source : источник
callback_data : указатель для данных callback-объекта "object"
callback_funcs : функция для подсчёта ссылок callback_data и получения callback-функции и данных

g_source_add_poll ()

void g_source_add_poll (GSource *source, GPollFD *fd);

Добавляет дескриптор в набор опрашиваемых дескрипторов файла для данного источника. Это полезно комбинировать с g_source_new() для добавления источника события. Функция проверки источников события обычно проверяет поле revents в GPollFD структуре и возвращает TRUE если события должны быть обработаны.

source : GSource
fd : GPollFD структура содержащая информацию о дескрипторе файла для наблюдения.

g_source_remove_poll ()

void g_source_remove_poll (GSource *source, GPollFD *fd);

Удаляет дескриптор файла из набора опрашиваемых дескрипторов файла для данного источника.

source : GSource
fd : GPollFD структура предварительно помещённая в g_source_add_poll().

g_source_get_current_time ()

void g_source_get_current_time (GSource *source, GTimeVal *timeval);

Определяет "текущее время" для использования при проверки источника. Преимущество вызова этой функции перед вызовом g_get_current_time() заключается в проверке множества источников, GLib может кэшировать единственное значение вместо необходимости неоднократного получения системного времени.

source : GSource
timeval : GTimeVal структура в которой хранится текущее время.

g_source_remove ()

gboolean g_source_remove (guint tag);

Удаляет источник с полученным id из основного контекста по умолчанию. Идентификатор (id) GSource получается при помощи g_source_get_id(), или возвращается функциями g_source_attach(), g_idle_add(), g_idle_add_full(), g_timeout_add(), g_timeout_add_full(), g_child_watch_add(), g_child_watch_add_full(), g_io_add_watch() и g_io_add_watch_full().

Смотрите также g_source_destroy().

tag : ID удаляемого источника.
Возвращает : TRUE если источник найден и удалён.

g_source_remove_by_funcs_user_data ()

gboolean g_source_remove_by_funcs_user_data (GSourceFuncs *funcs, gpointer user_data);

Удаляет источник из контекста основного цикла по умолчанию с данными функциями источника и пользовательскими данными. Если существует множество источников с одинаковыми функциями источника и пользовательскими данными, будет удалён только один.

funcs : source_funcs помещаемые в g_source_new()
user_data : пользовательские данные для callback-функции
Возвращает : TRUE если источник найден и удалён.

g_source_remove_by_user_data ()

gboolean g_source_remove_by_user_data (gpointer user_data);

Удаляет источник из контекста основного цикла по умолчанию с полученными пользовательскими данными для callback-функции. Если существует множество одинаковых источников с такими же пользовательскими данными, удаляется только один.

user_data : user_data для callback-функции.
Возвращает : TRUE если источник найден и удалён.