/*-
* $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 <jonas@codefactory.se>
* Copyright (c) 2002 Daniel Lundin <daniel@codefactory.se>
* Copyright (c) 2002 CodeFactory AB. All rights reserved.
*/
#include <librr/rr.h>
#include <stdlib.h>
#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;
}
syntax highlighted by Code2HTML, v. 0.9.1