Thread Pools

Thread Pools — Пулы потоков для одновременного выполнения работы.

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

#include <glib.h> GThreadPool; GThreadPool* g_thread_pool_new (GFunc func, gpointer user_data, gint max_threads, gboolean exclusive, GError **error); void g_thread_pool_push (GThreadPool *pool, gpointer data, GError **error); void g_thread_pool_set_max_threads (GThreadPool *pool, gint max_threads, GError **error); gint g_thread_pool_get_max_threads (GThreadPool *pool); guint g_thread_pool_get_num_threads (GThreadPool *pool); guint g_thread_pool_unprocessed (GThreadPool *pool); void g_thread_pool_free (GThreadPool *pool, gboolean immediate, gboolean wait); void g_thread_pool_set_max_unused_threads (gint max_threads); gint g_thread_pool_get_max_unused_threads (void); guint g_thread_pool_get_num_unused_threads (void); void g_thread_pool_stop_unused_threads (void); void g_thread_pool_set_sort_function (GThreadPool *pool, GCompareDataFunc func, gpointer user_data); void g_thread_pool_set_max_idle_time (guint interval); guint g_thread_pool_get_max_idle_time (void);

Описание

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

Поэтому для вашего удобства GLib обеспечивает пулы потоков. Дополнительное преимущество в том, что потоки могут использоваться совместно разными подсистемами вашей программы, когда используется GLib.

Для создания нового пула потоков используется g_thread_pool_new(). Освобождается созданный пул потоков с помощью g_thread_pool_free().

Если вам нужно выполнить определённую задачу внутри потокового пула, вызовите g_thread_pool_push().

Для получения текущего количества выполняемых потоков используйте g_thread_pool_get_num_threads(). Для получения количества ещё не обработанных задач используйте g_thread_pool_unprocessed(). Для управления максимальным количеством потоков пула, используйте g_thread_pool_get_max_threads() и g_thread_pool_set_max_threads().

Наконец вы можете контролировать количество неиспользуемых потоков, которые поддерживаются GLib для использования в будущем. Текущее количество может быть выбрано с помощью g_thread_pool_get_num_unused_threads(). Максимальное количество может контролироваться с помощью g_thread_pool_get_max_unused_threads() и g_thread_pool_set_max_unused_threads(). Все текущие неиспользуемые потоки могут быть остановлены при помощи g_thread_pool_stop_unused_threads().

Детали

GThreadPool

typedef struct { GFunc func; gpointer user_data; gboolean exclusive; } GThreadPool;

Структура GThreadPool представляет потоковый пул. Она имеет шесть общих доступных только для чтения элементов, но скрытая структура больше, поэтому вы не должны копировать эту структуру.

GFunc func; Функция выполняемая в потоках этого пула
gpointer user_data; пользовательские данные для потоков этого пула
gboolean exclusive; все исключительные потоки этого пула

g_thread_pool_new ()

GThreadPool* g_thread_pool_new (GFunc func, gpointer user_data, gint max_threads, gboolean exclusive, GError **error);

Эта функция создаёт новый потоковый пул.

Каждый раз при вызове g_thread_pool_push(), или создаётся новый поток или повторно используется один из неиспользуемых. Большинство max_threads потоков выполняются параллельно для этого потокового пула. max_threads = -1 позволяет безлимитное создание потоков для этого пула. Вновь созданный или повторно используемый поток выполняет функцию func с двумя аргументами. Первый для g_thread_pool_push() а второй user_data.

Параметр exclusive определяет, владеет ли всеми исключительными потоками пул, или потоки доступны глобально. Если exclusive равен TRUE, max_threads потоки начинаются немедленно и они будут выполняться исключительно для этого пула пока он не разрушен g_thread_pool_free(). Если exclusive равен FALSE, потоки создаются когда необходимы и доступны всем не исключительным потоковым пулам. Это подразумевает что max_threads может не быть -1 для исключительных потоковых пулов.

error может быть NULL для игнорирования ошибок, или не-NULL для сообщения об ошибках. Ошибка может произойти только когда exclusive установлен в TRUE и не все max_threads могут быть созданы.

func : функция выполняемая в потоке нового потокового пула
user_data : пользовательские данные передаваемые в функцию func при каждом вызове
max_threads : максимальное количество потоков для параллельного выполнения в новом потоковом пуле, -1 означает отсутствие лимита
exclusive : должен ли этот пул быть исключительным?
error : расположение возвращаемой ошибки
Возвращает : новую GThreadPool

g_thread_pool_push ()

void g_thread_pool_push (GThreadPool *pool, gpointer data, GError **error);

Вставляет data в список задач для выполнения пулом pool. Когда количество выполняемых потоков меньше чем максимально допустимое, новый поток запускается (или повторно выполняется) с параметрами полученными в g_thread_pool_new(). Иначе data остаются в очереди пока поток в этом пуле не завершит предыдущие задачи и не начнет обрабатывать data.

error может быть NULL для игнорирования ошибок, или не-NULL для сообщения об ошибках. Ошибка может произойти только когда новый поток не может быть создан. В этом случае data просто вставляются в начало очереди для выполнения.

pool : GThreadPool
data : новая задача для pool
error : расположение для возвращаемой ошибки

g_thread_pool_set_max_threads ()

void g_thread_pool_set_max_threads (GThreadPool *pool, gint max_threads, GError **error);

Устанавливает максимально допустимое число потоков для pool. Значение -1 означает безлимитное количество потоков.

Установка max_threads в значение 0 означает полную остановку работы pool. Пул замораживается до тех пор пока значение max_threads не будет установлено в не-нулевое значение.

Поток никогда не завершается во время выполнения вызова func, которая поставляется g_thread_pool_new(). Вместо этого максимальное число потоков имеет эффект только для распределения новых потоков в g_thread_pool_push(). Новый поток распределяется каждый раз, когда текущее количество выполняемых потоков в пуле меньше pool меньше чем максимальное число.

error может быть NULL для игнорирования ошибок, или не-NULL для сообщения об ошибках. Ошибка происходит только когда новый поток не может быть создан.

pool : GThreadPool
max_threads : новое максимальное число потоков для pool
error : расположение возвращаемой ошибки

g_thread_pool_get_max_threads ()

gint g_thread_pool_get_max_threads (GThreadPool *pool);

Возвращает максимальное число потоков для pool.

pool : GThreadPool
Возвращает : максимальное число потоков

g_thread_pool_get_num_threads ()

guint g_thread_pool_get_num_threads (GThreadPool *pool);

Возвращает текущее количество выполняемых потоков в pool.

pool : GThreadPool
Возвращает : текущее количество выполняемых потоков

g_thread_pool_unprocessed ()

guint g_thread_pool_unprocessed (GThreadPool *pool);

Возвращает количество задач остающихся не обработанными в pool.

pool : GThreadPool
Возвращает : количество не обработанных задач

g_thread_pool_free ()

void g_thread_pool_free (GThreadPool *pool, gboolean immediate, gboolean wait);

Освобождает все ресурсы распределённые для pool.

Если immediate равен TRUE, нет новых задач обрабатываемых в pool. Иначе pool не освободиться до тех пор пока последняя задача не обработана. Однако помните, поток не прерывается в пуле пока выполняет задачу. Все потоки выполняющие свои задачи завершают их перед тем как pool будет освобождён.

Если wait равен TRUE, функции не возвращают прежде чем все обрабатываемые задачи (зависит от immediate, все или только выполняемые в текущий момент) будут готовы. Иначе функции возвращаются немедленно.

После вызова этой функции pool не должен больше использоваться.

pool : GThreadPool
immediate : должен ли пул pool завершиться немедленно?
wait : должна ли функция ждать завершения всех задач?

g_thread_pool_set_max_unused_threads ()

void g_thread_pool_set_max_unused_threads (gint max_threads);

Устанавливает максимальное количество неиспользуемых потоков в max_threads. Если max_threads равен -1, количество неиспользуемых потоков не лимитировано.

max_threads : максимальное число неиспользуемых потоков

g_thread_pool_get_max_unused_threads ()

gint g_thread_pool_get_max_unused_threads (void);

Возвращает максимально допустимое число неиспользуемых потоков.

Возвращает : максимальное число неиспользуемых потоков

g_thread_pool_get_num_unused_threads ()

guint g_thread_pool_get_num_unused_threads (void);

Возвращает текущее количество неиспользуемых потоков.

Возвращает : текущее число неиспользуемых потоков

g_thread_pool_stop_unused_threads ()

void g_thread_pool_stop_unused_threads (void);

Останавливает все текущие неиспользуемые потоки. Это не меняет максимальное число неиспользуемых потоков. Эта функция может использоваться для регулярной остановки всех неиспользуемых потоков например из g_timeout_add().


g_thread_pool_set_sort_function ()

void g_thread_pool_set_sort_function (GThreadPool *pool, GCompareDataFunc func, gpointer user_data);

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

Помните, если максимальное количество потоков больше 1, порядок выполнения потоков не может быть гарантирован на 100%. Потоки планируются операционной системой и выполняются в случайном порядке. Не предполагайте что потоки выполняются в порядке их создания.

pool : GThreadPool
func : GCompareDataFunc используемая для сортировки списка задач. При передаче в функцию две задачи, она должна возвращать 0 если порядок в котором обрабатываются задачи не важен, отрицательное значение если первая задача должна быть обработана перед второй или положительное если вторая задача должна обрабатываться перед первой.
user_data : пользовательские данные помещаемые в func.

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


g_thread_pool_set_max_idle_time ()

void g_thread_pool_set_max_idle_time (guint interval);

Эта функция устанавливает максимальный interval ожидания потоком новых задач в пуле перед остановкой. Эта функция похожа на вызов g_thread_pool_stop_unused_threads() с регулярным таймаутом, но выполняется на основании потока.

Установка interval в 0, не останавливает бездействующие потоки. Эта функция создаёт g_async_queue_timed_pop() используя interval.

interval : максимальный interval (1/1000 секунды) бездействия потока.

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


g_thread_pool_get_max_idle_time ()

guint g_thread_pool_get_max_idle_time (void);

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

Если функция вернула 0, потоки ожидающие новые задачи в пуле не останавливаются.

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

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

Смотрите также

GThread

система потока GLib.