/** * g_thread_pool_push: * @pool: a #GThreadPool * @data: a new task for @pool * @error: return location for error, or %NULL * * Inserts @data into the list of tasks to be executed by @pool. * * When the number of currently running threads is lower than the * maximal allowed number of threads, a new thread is started (or * reused) with the properties given to g_thread_pool_new(). * Otherwise, @data stays in the queue until a thread in this pool * finishes its previous task and processes @data. * * @error can be %NULL to ignore errors, or non-%NULL to report * errors. An error can only occur when a new thread couldn't be * created. In that case @data is simply appended to the queue of * work to do. * * Before version 2.32, this function did not return a success status. * * Returns: %TRUE on success, %FALSE if an error occurred */ gboolean g_thread_pool_push (GThreadPool *pool, gpointer data, GError **error) { GRealThreadPool *real; gboolean result; real = (GRealThreadPool*) pool; g_return_val_if_fail (real, FALSE); g_return_val_if_fail (real->running, FALSE); result = TRUE; g_async_queue_lock (real->queue); if (g_async_queue_length_unlocked (real->queue) >= 0) { /* No thread is waiting in the queue */ GError *local_error = NULL; if (!g_thread_pool_start_thread (real, &local_error)) { g_propagate_error (error, local_error); result = FALSE; } } g_thread_pool_queue_push_unlocked (real, data); g_async_queue_unlock (real->queue); return result; }
/** * g_thread_pool_new: * @func: a function to execute in the threads of the new thread pool * @user_data: user data that is handed over to @func every time it * is called * @max_threads: the maximal number of threads to execute concurrently * in the new thread pool, -1 means no limit * @exclusive: should this thread pool be exclusive? * @error: return location for error, or %NULL * * This function creates a new thread pool. * * Whenever you call g_thread_pool_push(), either a new thread is * created or an unused one is reused. At most @max_threads threads * are running concurrently for this thread pool. @max_threads = -1 * allows unlimited threads to be created for this thread pool. The * newly created or reused thread now executes the function @func * with the two arguments. The first one is the parameter to * g_thread_pool_push() and the second one is @user_data. * * The parameter @exclusive determines whether the thread pool owns * all threads exclusive or shares them with other thread pools. * If @exclusive is %TRUE, @max_threads threads are started * immediately and they will run exclusively for this thread pool * until it is destroyed by g_thread_pool_free(). If @exclusive is * %FALSE, threads are created when needed and shared between all * non-exclusive thread pools. This implies that @max_threads may * not be -1 for exclusive thread pools. Besides, exclusive thread * pools are not affected by g_thread_pool_set_max_idle_time() * since their threads are never considered idle and returned to the * global pool. * * @error can be %NULL to ignore errors, or non-%NULL to report * errors. An error can only occur when @exclusive is set to %TRUE * and not all @max_threads threads could be created. * See #GThreadError for possible errors that may occur. * Note, even in case of error a valid #GThreadPool is returned. * * Returns: the new #GThreadPool */ GThreadPool * g_thread_pool_new (GFunc func, gpointer user_data, gint max_threads, gboolean exclusive, GError **error) { GRealThreadPool *retval; G_LOCK_DEFINE_STATIC (init); g_return_val_if_fail (func, NULL); g_return_val_if_fail (!exclusive || max_threads != -1, NULL); g_return_val_if_fail (max_threads >= -1, NULL); retval = g_new (GRealThreadPool, 1); retval->pool.func = func; retval->pool.user_data = user_data; retval->pool.exclusive = exclusive; retval->queue = g_async_queue_new (); g_cond_init (&retval->cond); retval->max_threads = max_threads; retval->num_threads = 0; retval->running = TRUE; retval->immediate = FALSE; retval->waiting = FALSE; retval->sort_func = NULL; retval->sort_user_data = NULL; G_LOCK (init); if (!unused_thread_queue) unused_thread_queue = g_async_queue_new (); G_UNLOCK (init); if (retval->pool.exclusive) { g_async_queue_lock (retval->queue); while (retval->num_threads < retval->max_threads) { GError *local_error = NULL; if (!g_thread_pool_start_thread (retval, &local_error)) { g_propagate_error (error, local_error); break; } } g_async_queue_unlock (retval->queue); } return (GThreadPool*) retval; }
/** * g_thread_pool_set_max_threads: * @pool: a #GThreadPool * @max_threads: a new maximal number of threads for @pool, * or -1 for unlimited * @error: return location for error, or %NULL * * Sets the maximal allowed number of threads for @pool. * A value of -1 means that the maximal number of threads * is unlimited. If @pool is an exclusive thread pool, setting * the maximal number of threads to -1 is not allowed. * * Setting @max_threads to 0 means stopping all work for @pool. * It is effectively frozen until @max_threads is set to a non-zero * value again. * * A thread is never terminated while calling @func, as supplied by * g_thread_pool_new(). Instead the maximal number of threads only * has effect for the allocation of new threads in g_thread_pool_push(). * A new thread is allocated, whenever the number of currently * running threads in @pool is smaller than the maximal number. * * @error can be %NULL to ignore errors, or non-%NULL to report * errors. An error can only occur when a new thread couldn't be * created. * * Before version 2.32, this function did not return a success status. * * Returns: %TRUE on success, %FALSE if an error occurred */ gboolean g_thread_pool_set_max_threads (GThreadPool *pool, gint max_threads, GError **error) { GRealThreadPool *real; gint to_start; gboolean result; real = (GRealThreadPool*) pool; g_return_val_if_fail (real, FALSE); g_return_val_if_fail (real->running, FALSE); g_return_val_if_fail (!real->pool.exclusive || max_threads != -1, FALSE); g_return_val_if_fail (max_threads >= -1, FALSE); result = TRUE; g_async_queue_lock (real->queue); real->max_threads = max_threads; if (pool->exclusive) to_start = real->max_threads - real->num_threads; else to_start = g_async_queue_length_unlocked (real->queue); for ( ; to_start > 0; to_start--) { GError *local_error = NULL; if (!g_thread_pool_start_thread (real, &local_error)) { g_propagate_error (error, local_error); result = FALSE; break; } } g_async_queue_unlock (real->queue); return result; }
/** * g_thread_pool_push: * @pool: a #GThreadPool * @data: a new task for @pool * @error: return location for error * * Inserts @data into the list of tasks to be executed by @pool. When * the number of currently running threads is lower than the maximal * allowed number of threads, a new thread is started (or reused) with * the properties given to g_thread_pool_new (). Otherwise @data stays * in the queue until a thread in this pool finishes its previous task * and processes @data. * * @error can be %NULL to ignore errors, or non-%NULL to report * errors. An error can only occur when a new thread couldn't be * created. In that case @data is simply appended to the queue of work * to do. **/ void g_thread_pool_push (GThreadPool *pool, gpointer data, GError **error) { GRealThreadPool *real; real = (GRealThreadPool*) pool; g_return_if_fail (real); g_return_if_fail (real->running); g_async_queue_lock (real->queue); if (g_async_queue_length_unlocked (real->queue) >= 0) /* No thread is waiting in the queue */ g_thread_pool_start_thread (real, error); g_thread_pool_queue_push_unlocked (real, data); g_async_queue_unlock (real->queue); }