/*- * $Id: rr.c,v 1.22 2002/08/19 18:05:43 jonas Exp $ * * See the file LICENSE for redistribution information. * If you have not received a copy of the license, please contact CodeFactory * by email at info@codefactory.se, or on the web at http://www.codefactory.se/ * You may also write to: CodeFactory AB, SE-903 47, Umeå, Sweden. * * Copyright (c) 2002 Jonas Borgström * Copyright (c) 2002 Daniel Lundin * Copyright (c) 2002 CodeFactory AB. All rights reserved. */ #include #include #define RR_DEFAULT_MAX_WORK_THREADS 1 static gint rr_max_work_threads = RR_DEFAULT_MAX_WORK_THREADS; static RRWorkPool *rr_wp = NULL; static GMainLoop *rr_main_loop = NULL; static GMainContext *rr_main_context = NULL; static GThread *rr_bg_thread = NULL; GQuark rr_error_quark (void) { static GQuark quark; if (!quark) quark = g_quark_from_static_string ("rr_error"); return quark; } GQuark rr_beep_code_quark (void) { static GQuark quark; if (!quark) quark = g_quark_from_static_string ("rr_beep_code"); return quark; } static void gobject_bug_workaround (void) { GType type; RRGreeting *greeting; type = RR_TYPE_CHANNEL; type = RR_TYPE_CONNECTION; type = RR_TYPE_TCP_CONNECTION; type = RR_TYPE_TCP_LISTENER; type = RR_TYPE_FRAME; type = RR_TYPE_FRAME_SEQ; type = RR_TYPE_MESSAGE; type = RR_TYPE_GREETING; type = RR_TYPE_MESSAGE_START; type = RR_TYPE_MESSAGE_CLOSE; type = RR_TYPE_MESSAGE_ERROR; type = RR_TYPE_MESSAGE_STATIC; type = RR_TYPE_PROFILE_REGISTRY; greeting = rr_greeting_new (NULL, NULL, NULL); g_object_unref (G_OBJECT (greeting)); } static gpointer run_thread (gpointer data) { g_main_loop_run (rr_main_loop); return NULL; } /** * rr_init: * @argc: a pointer to argc or %NULL. * @argv: a pointer to argv or %NULL. * @error: location to return an error. * * Initializes RoadRunner and starts the event thread. * * Return value: TRUE on success, FALSE on failure. **/ gboolean rr_init (gint *argc, gchar ***argv, GError **error) { const gchar *str; if (!g_thread_supported ()) g_thread_init (NULL); rr_debug_init (); if ((str = getenv ("RR_MAX_WORK_THREADS"))) { gint num = atoi (str); if (num > 0) rr_max_work_threads = num; } rr_wp = rr_work_pool_new (rr_max_work_threads); gobject_bug_workaround (); rr_main_context = g_main_context_new (); rr_main_loop = g_main_loop_new (rr_main_context, FALSE); if ((rr_bg_thread = g_thread_create (run_thread, NULL, TRUE, error)) == NULL) return FALSE; else return TRUE; } /** * rr_main_work_pool_push: * @gid: a thread group id. * @func: a function to execute by one thread in the work pool. * @data: first argument to @func * @user_data: second argument to @func * * Inserts @func to the list of task to be executed by the roadrunner wide * work pool. The work pool guarantees that two or more tasks with the same * @gid will never be executed in parallel. **/ void rr_main_work_pool_push (RRWPGroup gid, GFunc func, gpointer data, gpointer user_data) { g_return_if_fail (rr_wp != NULL); rr_work_pool_push (rr_wp, gid, func, data, user_data); } /** * rr_main_work_pool_join: * @gid: a thread group id * * blocks until all tasks in the roadrunner global work pool of the given * @gid are executed. **/ void rr_main_work_pool_join (RRWPGroup gid) { g_return_if_fail (rr_wp != NULL); rr_work_pool_join (rr_wp, gid); } /** * rr_quit: * @error: location to return an error. * * Terminates the main loop. This will unblock rr_wait_until_done. * * Return value: %TRUE on success, %FALSE on failure. **/ gboolean rr_quit (GError **error) { if (rr_main_loop == NULL) { g_set_error (error, RR_ERROR, RR_ERROR_OTHER, "The main loop doesn't exist."); return FALSE; } g_main_loop_quit (rr_main_loop); return TRUE; } /** * rr_wait_until_done: * @error: location to return an error. * * Blocks until the RoadRunner event loop is done. * (when rr_quit is called). * * Return value: TRUE on success, FALSE on failure. **/ gboolean rr_wait_until_done (GError **error) { if (rr_bg_thread) { g_thread_join (rr_bg_thread); rr_bg_thread = NULL; } rr_work_pool_free (rr_wp); rr_wp = NULL; g_main_loop_unref (rr_main_loop); g_main_context_unref (rr_main_context); rr_main_loop = NULL; rr_main_context = NULL; rr_debug_exit (); return TRUE; } /** * rr_exit: * @error: location to return an error. * * Terminates the RoadRunner event thread and free the resources * allocated by #rr_init. * * Return value: TRUE on success, FALSE on failure. **/ gboolean rr_exit (GError **error) { if (!rr_quit (error)) return FALSE; if (!rr_wait_until_done (error)) return FALSE; return TRUE; } GMainContext * rr_get_main_context () { return rr_main_context; } /** * rr_set_max_work_threads: * @max: maximum number of threads. * * Sets the maximum number of threads roadrunner will use. This function * should be called before rr_init. **/ void rr_set_max_work_threads (int max) { rr_max_work_threads = max; } /** * rr_get_max_work_threads: * * Returns the maximum number of threads that roadrunner will use. * * Return value: the number of threads. **/ gint rr_get_max_work_threads (void) { return rr_max_work_threads; }