00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "opensync.h"
00022 #include "opensync_internals.h"
00023
00024 #include "opensync_thread_private.h"
00025 #include "opensync_thread_internals.h"
00026
00027 static gboolean osyncThreadStopCallback(gpointer data)
00028 {
00029 OSyncThread *thread = data;
00030
00031 g_main_loop_quit(thread->loop);
00032
00033 return FALSE;
00034 }
00035
00036 static gboolean osyncThreadStartCallback(gpointer data)
00037 {
00038 OSyncThread *thread = data;
00039
00040 g_mutex_lock(thread->started_mutex);
00041 g_cond_signal(thread->started);
00042 g_mutex_unlock(thread->started_mutex);
00043
00044 return FALSE;
00045 }
00046
00047 OSyncThread *osync_thread_new(GMainContext *context, OSyncError **error)
00048 {
00049 OSyncThread *thread = NULL;
00050 osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, context, error);
00051
00052 thread = osync_try_malloc0(sizeof(OSyncThread), error);
00053 if (!thread)
00054 goto error;
00055 thread->ref_count = 1;
00056
00057 if (!g_thread_supported ()) g_thread_init (NULL);
00058
00059 thread->started_mutex = g_mutex_new();
00060 thread->started = g_cond_new();
00061 thread->context = context;
00062 if (thread->context)
00063 g_main_context_ref(thread->context);
00064 thread->loop = g_main_loop_new(thread->context, FALSE);
00065
00066 osync_trace(TRACE_EXIT, "%s: %p", __func__, thread);
00067 return thread;
00068
00069 error:
00070 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
00071 return NULL;
00072 }
00073
00074 OSyncThread *osync_thread_ref(OSyncThread *thread)
00075 {
00076 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, thread);
00077 osync_assert(thread);
00078
00079 g_atomic_int_inc(&(thread->ref_count));
00080
00081 osync_trace(TRACE_EXIT, "%s", __func__);
00082 return thread;
00083 }
00084
00085 void osync_thread_unref(OSyncThread *thread)
00086 {
00087 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, thread);
00088 osync_assert(thread);
00089
00090 if (g_atomic_int_dec_and_test(&(thread->ref_count))) {
00091 if (thread->started_mutex)
00092 g_mutex_free(thread->started_mutex);
00093
00094 if (thread->started)
00095 g_cond_free(thread->started);
00096
00097 if (thread->loop)
00098 g_main_loop_unref(thread->loop);
00099
00100 if (thread->context)
00101 g_main_context_unref(thread->context);
00102
00103 osync_free(thread);
00104 }
00105 osync_trace(TRACE_EXIT, "%s", __func__);
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 OSyncThread *osync_thread_create(GThreadFunc func, void *userdata, OSyncError **error)
00123 {
00124 GError *gerror;
00125 OSyncThread *thread;
00126
00127 osync_assert(func);
00128 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, func, userdata, error);
00129
00130 thread = osync_try_malloc0(sizeof(OSyncThread), error);
00131 if (!thread)
00132 goto error;
00133 thread->ref_count = 1;
00134
00135 if (!g_thread_supported ())
00136 g_thread_init (NULL);
00137
00138 thread->thread = g_thread_create(func, userdata, TRUE, &gerror);
00139
00140 if (!thread->thread) {
00141 osync_error_set(error, OSYNC_ERROR_GENERIC, "%s", gerror->message);
00142 g_error_free(gerror);
00143 goto error_free_thread;
00144 }
00145
00146 osync_trace(TRACE_EXIT, "%s", __func__);
00147 return thread;
00148
00149 error_free_thread:
00150 osync_free(thread);
00151 error:
00152 osync_trace(TRACE_EXIT_ERROR, "%s", __func__, osync_error_print(error));
00153 return NULL;
00154 }
00155
00156 void osync_thread_start(OSyncThread *thread)
00157 {
00158 GSource *idle = NULL;
00159 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, thread);
00160
00161 g_mutex_lock(thread->started_mutex);
00162 idle = g_idle_source_new();
00163 g_source_set_callback(idle, osyncThreadStartCallback, thread, NULL);
00164 g_source_attach(idle, thread->context);
00165 thread->thread = g_thread_create ((GThreadFunc)g_main_loop_run, thread->loop, TRUE, NULL);
00166 g_cond_wait(thread->started, thread->started_mutex);
00167 g_mutex_unlock(thread->started_mutex);
00168
00169 osync_trace(TRACE_EXIT, "%s", __func__);
00170 }
00171
00172 void osync_thread_stop(OSyncThread *thread)
00173 {
00174 GSource *source = NULL;
00175 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, thread);
00176 osync_assert(thread);
00177
00178 source = g_idle_source_new();
00179 g_source_set_callback(source, osyncThreadStopCallback, thread, NULL);
00180 g_source_attach(source, thread->context);
00181
00182 g_thread_join(thread->thread);
00183 thread->thread = NULL;
00184
00185 g_source_unref(source);
00186
00187 osync_trace(TRACE_EXIT, "%s", __func__);
00188 }
00189
00190 void osync_thread_exit(OSyncThread *thread, int retval)
00191 {
00192 GSource *source = NULL;
00193 osync_trace(TRACE_ENTRY, "%s(%p, %i)", __func__, thread, retval);
00194 osync_assert(thread);
00195
00196 source = g_idle_source_new();
00197 g_source_set_callback(source, osyncThreadStopCallback, thread, NULL);
00198 g_source_attach(source, thread->context);
00199 g_source_unref(source);
00200 thread->thread = NULL;
00201
00202 g_thread_exit(GINT_TO_POINTER(retval));
00203
00204 osync_trace(TRACE_EXIT, "%s", __func__);
00205 }
00206