![]() |
Helixis 1.0
Task Programming API
|
00001 /* 00002 ** Copyright 2009-2011, helixis.org 00003 ** All rights reserved. 00004 ** 00005 ** Redistribution and use in source and binary forms, with or without modification, are permitted provided 00006 ** that the following conditions are met: 00007 ** 00008 ** Redistributions of source code must retain the above copyright notice, this list of conditions and the 00009 ** following disclaimer. 00010 ** 00011 ** Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 00012 ** the following disclaimer in the documentation and/or other materials provided with the distribution. 00013 ** 00014 ** Neither the name of the helixis.org nor the names of its contributors may be used to endorse or promote 00015 ** products derived from this software without specific prior written permission. 00016 ** 00017 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 00018 ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00019 ** PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00020 ** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00021 ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00022 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00023 ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00024 ** POSSIBILITY OF SUCH DAMAGE. 00025 */ 00026 00027 /* 00028 ** INCLUDES 00029 */ 00030 00031 #include "hlx/core.h" 00032 #include "helixis_internal.h" 00033 00034 #if defined(HLX_BUILD_WITH_PARALLEL_THREADING) 00035 00036 #ifdef __cplusplus 00037 extern "C" { 00038 #endif 00039 00040 /* 00041 ** EXTERNALS 00042 */ 00043 00044 extern hlx_api gl_api; 00045 00046 /* 00047 ** GLOBALS 00048 */ 00049 00050 hlx_scheduler gl_scheduler; 00051 00052 /* 00053 ** PROTOTYPES 00054 */ 00055 00056 hlx_group* hlx_sheduler_find_lighter_group(void); 00057 hlx_task* hlx_scheduler_init_task(hlx_task_func task_func, void* data, hlx_group* group, hlx_task_callback callback); 00058 void hlx_scheduler_schedule(void); 00059 int hlx_scheduler_schedule_group(hlx_group*); 00060 void hlx_core_add_task_in_group_callback2(hlx_task_func task_func, void* data, hlx_group_id group_id, hlx_task_callback callback); 00061 00062 /* 00063 ** FUNCTIONS 00064 */ 00065 00066 void hlx_core_add_task_in_group_callback(hlx_task_func task_func, void* data, hlx_group_id group_id, hlx_group_id self_group_id, hlx_task_callback callback) 00067 { 00068 hlx_task* task; 00069 hlx_group* group; 00070 00071 group = (hlx_group* )group_id; 00072 if (group_id == self_group_id) 00073 { 00074 hlx_core_add_task_in_group_callback2(task_func, data, group_id, callback); 00075 return ; 00076 } 00077 task = hlx_scheduler_init_task(task_func, data, group, callback); 00078 if (!task) 00079 return; 00080 hlx_group_bufferize_task(group, task); 00081 gl_api.thread_api.thread_resume(&(group->thread)); 00082 } 00083 00084 void hlx_core_add_task_callback(hlx_task_func task_func, void* data, hlx_group_id self_group_id, hlx_task_callback callback) 00085 { 00086 hlx_group* best; 00087 00088 best = hlx_sheduler_find_lighter_group(); 00089 if (best->id == self_group_id) 00090 { 00091 hlx_core_add_task_in_group_callback2(task_func, data, best->id, callback); 00092 return; 00093 } 00094 hlx_core_add_task_in_group_callback(task_func, data, best->id, self_group_id, callback); 00095 } 00096 00097 void hlx_core_add_task_in_group_callback2(hlx_task_func task_func, void* data, hlx_group_id group_id, hlx_task_callback callback) 00098 { 00099 hlx_task* task; 00100 hlx_group* group; 00101 00102 group = (hlx_group*)group_id; 00103 task = hlx_scheduler_init_task(task_func, data, group, callback); 00104 if (!task) 00105 return; 00106 if (gl_scheduler.launched) 00107 hlx_group_bufferize_task(group, task); 00108 else 00109 hlx_group_add_task(group, task); 00110 gl_api.thread_api.thread_resume(&(group->thread)); 00111 } 00112 00113 void hlx_sheduler_end_all_threads() 00114 { 00115 hlx_list_node* it; 00116 hlx_group* group; 00117 00118 gl_scheduler.loop = 0; 00119 for (it = gl_scheduler.groups.first; it; it = it->next) 00120 { 00121 group = it->data; 00122 gl_api.thread_api.thread_resume(&(group->thread)); 00123 } 00124 } 00125 00126 static void hlx_scheduler_schedule_group_threaded(hlx_thread* thread, void* data) 00127 { 00128 int ret; 00129 hlx_list_node* it; 00130 hlx_list_node* tmp; 00131 hlx_task* task; 00132 hlx_group* group; 00133 hlx_group* tmp_group; 00134 00135 group = (hlx_group*)data; 00136 tmp_group = (hlx_group*)data; 00137 while (gl_scheduler.loop == 1) 00138 { 00139 thread->status = HLX_THREAD_LOCKED; 00140 hlx_group_flush_task_buffer(group); 00141 if (!group->active_count) 00142 { 00143 ret = 0; 00144 for (it = gl_scheduler.groups.first; it; it = it->next) 00145 { 00146 tmp_group = it->data; 00147 if (tmp_group != group && tmp_group->active_count) 00148 { 00149 ret = 1; 00150 break; 00151 } 00152 } 00153 if (ret) 00154 gl_api.thread_api.thread_suspend(thread); 00155 else if (thread->status == HLX_THREAD_LOCKED) 00156 { 00157 hlx_sheduler_end_all_threads(); 00158 return; 00159 } 00160 } 00161 gl_api.thread_api.thread_pause_if_needed(thread); 00162 thread->status = HLX_THREAD_RUNNING; 00163 it = group->tasks.first; 00164 while (it) 00165 { 00166 task = it->data; 00167 if (task->status != HLX_TASK_STATUS_RUN) 00168 { 00169 it = it->next; 00170 continue; 00171 } 00172 ret = task->task_func(&(task->ctx), task->group_id, &(task->stack), task->data); 00173 if (ret == HLX_ENDED || ret == HLX_EXITED || ret == HLX_MEMORY_EXHAUSTED) 00174 { 00175 if (task->callback != 0) 00176 task->callback(task->data, task->group_id, ret); 00177 gl_api.atomic_decr_entry(&group->active_count); 00178 if (task->stack != 0) 00179 gl_api.free_entry(task->stack); 00180 gl_api.free_entry(task); 00181 tmp = it->next; 00182 hlx_list_erase(&group->tasks, it); 00183 it = tmp; 00184 } 00185 else 00186 it = it->next; 00187 } 00188 } 00189 } 00190 00191 void hlx_scheduler_schedule(void) 00192 { 00193 hlx_list_node* it; 00194 hlx_group* g; 00195 00196 gl_scheduler.loop = 1; 00197 gl_scheduler.launched = 1; 00198 for (it = gl_scheduler.groups.first; it != 0; it = it->next) 00199 { 00200 g = it->data; 00201 gl_api.thread_api.thread_execute(&g->thread, hlx_scheduler_schedule_group_threaded, g); 00202 } 00203 for (it = gl_scheduler.groups.first; it != 0; it = it->next) 00204 { 00205 g = it->data; 00206 gl_api.thread_api.thread_wait_for(&(g->thread)); 00207 } 00208 gl_scheduler.launched = 0; 00209 } 00210 00211 #endif /* !HLX_BUILD_WITH_PARALLEL_THREADING */ 00212 00213 #ifdef __cplusplus 00214 } 00215 #endif 00216 00217 /* 00218 ** END OF FILE 00219 */