diff --git a/include/freerdp/utils/thread.h b/include/freerdp/utils/thread.h index 82f6192c2..8dab3bd86 100644 --- a/include/freerdp/utils/thread.h +++ b/include/freerdp/utils/thread.h @@ -20,22 +20,34 @@ #ifndef __THREAD_UTILS_H #define __THREAD_UTILS_H -#ifdef _WIN32 - -#define freerdp_thread_create(_proc, _arg) do { \ - DWORD thread; \ - CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)_proc, _arg, 0, &thread); \ - while (0) - -#else - +#include +#include +#include +#ifndef _WIN32 #include -#define freerdp_thread_create(_proc, _arg) do { \ - pthread_t thread; \ - pthread_create(&thread, 0, _proc, _arg); \ - pthread_detach(thread); \ - } while (0) - #endif +typedef struct _freerdp_thread freerdp_thread; +struct _freerdp_thread +{ + freerdp_mutex* mutex; + + struct wait_obj* signals[5]; + int num_signals; + + int status; +}; + +freerdp_thread* freerdp_thread_new(void); +void freerdp_thread_start(freerdp_thread* thread, void* func, void* arg); +void freerdp_thread_stop(freerdp_thread* thread); + +#define freerdp_thread_wait(_t) wait_obj_select(_t->signals, _t->num_signals, -1) +#define freerdp_thread_is_stopped(_t) wait_obj_is_set(_t->signals[0]) +#define freerdp_thread_quit(_t) _t->status = -1 +#define freerdp_thread_signal(_t) wait_obj_set(_t->signals[1]) +#define freerdp_thread_reset(_t) wait_obj_clear(_t->signals[1]) +#define freerdp_thread_lock(_t) freerdp_mutex_lock(_t->mutex) +#define freerdp_thread_unlock(_t) freerdp_mutex_unlock(_t->mutex) + #endif /* __THREAD_UTILS_H */ diff --git a/libfreerdp-utils/CMakeLists.txt b/libfreerdp-utils/CMakeLists.txt index 0a0b619e0..1cd5c6cb2 100644 --- a/libfreerdp-utils/CMakeLists.txt +++ b/libfreerdp-utils/CMakeLists.txt @@ -32,6 +32,7 @@ set(FREERDP_UTILS_SRCS semaphore.c stream.c svc_plugin.c + thread.c unicode.c wait_obj.c) diff --git a/libfreerdp-utils/svc_plugin.c b/libfreerdp-utils/svc_plugin.c index 5aee54e1c..3cdb69a84 100644 --- a/libfreerdp-utils/svc_plugin.c +++ b/libfreerdp-utils/svc_plugin.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -30,7 +29,6 @@ #include #include #include -#include #include #include @@ -77,12 +75,7 @@ struct rdp_svc_plugin_private STREAM* data_in; LIST* data_in_list; - freerdp_mutex* data_in_mutex; - - struct wait_obj* signals[5]; - int num_signals; - - int thread_status; + freerdp_thread* thread; }; static rdpSvcPlugin* svc_plugin_find_by_init_handle(void* init_handle) @@ -176,11 +169,11 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, uint3 item = xnew(svc_data_in_item); item->data_in = data_in; - freerdp_mutex_lock(plugin->priv->data_in_mutex); + freerdp_thread_lock(plugin->priv->thread); list_enqueue(plugin->priv->data_in_list, item); - freerdp_mutex_unlock(plugin->priv->data_in_mutex); + freerdp_thread_unlock(plugin->priv->thread); - wait_obj_set(plugin->priv->signals[1]); + freerdp_thread_signal(plugin->priv->thread); } } @@ -191,11 +184,11 @@ static void svc_plugin_process_event(rdpSvcPlugin* plugin, FRDP_EVENT* event_in) item = xnew(svc_data_in_item); item->event_in = event_in; - freerdp_mutex_lock(plugin->priv->data_in_mutex); + freerdp_thread_lock(plugin->priv->thread); list_enqueue(plugin->priv->data_in_list, item); - freerdp_mutex_unlock(plugin->priv->data_in_mutex); + freerdp_thread_unlock(plugin->priv->thread); - wait_obj_set(plugin->priv->signals[1]); + freerdp_thread_signal(plugin->priv->thread); } static void svc_plugin_open_event(uint32 openHandle, uint32 event, void* pData, uint32 dataLength, @@ -233,12 +226,12 @@ static void svc_plugin_process_data_in(rdpSvcPlugin* plugin) while (1) { /* terminate signal */ - if (wait_obj_is_set(plugin->priv->signals[0])) + if (freerdp_thread_is_stopped(plugin->priv->thread)) break; - freerdp_mutex_lock(plugin->priv->data_in_mutex); + freerdp_thread_lock(plugin->priv->thread); item = list_dequeue(plugin->priv->data_in_list); - freerdp_mutex_unlock(plugin->priv->data_in_mutex); + freerdp_thread_unlock(plugin->priv->thread); if (item != NULL) { @@ -264,22 +257,16 @@ static void* svc_plugin_thread_func(void* arg) while (1) { - wait_obj_select(plugin->priv->signals, plugin->priv->num_signals, -1); + freerdp_thread_wait(plugin->priv->thread); - /* terminate signal */ - if (wait_obj_is_set(plugin->priv->signals[0])) + if (freerdp_thread_is_stopped(plugin->priv->thread)) break; - /* data_in signal */ - if (wait_obj_is_set(plugin->priv->signals[1])) - { - wait_obj_clear(plugin->priv->signals[1]); - /* process data in */ - svc_plugin_process_data_in(plugin); - } + freerdp_thread_reset(plugin->priv->thread); + svc_plugin_process_data_in(plugin); } - plugin->priv->thread_status = -1; + freerdp_thread_quit(plugin->priv->thread); DEBUG_SVC("out"); @@ -299,45 +286,22 @@ static void svc_plugin_process_connected(rdpSvcPlugin* plugin, void* pData, uint } plugin->priv->data_in_list = list_new(); - plugin->priv->data_in_mutex = freerdp_mutex_new(); + plugin->priv->thread = freerdp_thread_new(); - /* terminate signal */ - plugin->priv->signals[plugin->priv->num_signals++] = wait_obj_new(); - /* data_in signal */ - plugin->priv->signals[plugin->priv->num_signals++] = wait_obj_new(); - - plugin->priv->thread_status = 1; - - freerdp_thread_create(svc_plugin_thread_func, plugin); + freerdp_thread_start(plugin->priv->thread, svc_plugin_thread_func, plugin); } static void svc_plugin_process_terminated(rdpSvcPlugin* plugin) { svc_data_in_item* item; - struct timespec ts; - int i; - wait_obj_set(plugin->priv->signals[0]); - i = 0; - ts.tv_sec = 0; - ts.tv_nsec = 10000000; - while (plugin->priv->thread_status > 0 && i < 1000) - { - i++; - nanosleep(&ts, NULL); - } + freerdp_thread_stop(plugin->priv->thread); plugin->channel_entry_points.pVirtualChannelClose(plugin->priv->open_handle); xfree(plugin->channel_entry_points.pExtendedData); svc_plugin_remove(plugin); - for (i = 0; i < plugin->priv->num_signals; i++) - wait_obj_free(plugin->priv->signals[i]); - plugin->priv->num_signals = 0; - - freerdp_mutex_free(plugin->priv->data_in_mutex); - while ((item = list_dequeue(plugin->priv->data_in_list)) != NULL) svc_data_in_item_free(item); list_free(plugin->priv->data_in_list); diff --git a/libfreerdp-utils/thread.c b/libfreerdp-utils/thread.c new file mode 100644 index 000000000..f6b838004 --- /dev/null +++ b/libfreerdp-utils/thread.c @@ -0,0 +1,81 @@ +/** + * FreeRDP: A Remote Desktop Protocol client. + * Thread Utils + * + * Copyright 2011 Vic Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +freerdp_thread* freerdp_thread_new(void) +{ + freerdp_thread* thread; + + thread = xnew(freerdp_thread); + thread->mutex = freerdp_mutex_new(); + thread->signals[0] = wait_obj_new(); + thread->signals[1] = wait_obj_new(); + thread->num_signals = 2; + + return thread; +} + +void freerdp_thread_start(freerdp_thread* thread, void* func, void* arg) +{ + thread->status = 1; + +#ifdef _WIN32 + { + DWORD th; + CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func, arg, 0, &th); + } +#else + { + pthread_t th; + pthread_create(&th, 0, func, arg); + pthread_detach(th); + } +#endif +} + +void freerdp_thread_stop(freerdp_thread* thread) +{ + struct timespec ts; + int i; + + wait_obj_set(thread->signals[0]); + i = 0; + ts.tv_sec = 0; + ts.tv_nsec = 10000000; + while (thread->status > 0 && i < 1000) + { + i++; + nanosleep(&ts, NULL); + } + + for (i = 0; i < thread->num_signals; i++) + wait_obj_free(thread->signals[i]); + thread->num_signals = 0; + + freerdp_mutex_free(thread->mutex); + thread->mutex = NULL; + + xfree(thread); +}