00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 #if defined _OPENMP && _OPENMP >= 200805
00032
00033
00034
00035
00036
00037 #include <cxlist.h>
00038 #include <cpl.h>
00039 #include <time.h>
00040 #include <omp.h>
00041
00042
00043
00044
00045
00046
00051
00052
00053
00054 typedef struct {
00055 int max_size;
00056 int size;
00057 cpl_error_code error;
00058 cx_list * queue;
00059 omp_lock_t lock;
00060 } visir_queue;
00061
00062
00063
00069
00070 visir_queue * visir_queue_init(const int max_size)
00071 {
00072 visir_queue * q = cpl_malloc(sizeof(visir_queue));
00073 q->max_size = max_size <= 0 ? INT_MAX : max_size;
00074 q->size = 0;
00075 q->error = CPL_ERROR_NONE;
00076 q->queue = cx_list_new();
00077 omp_init_lock(&(q->lock));
00078 return q;
00079 }
00080
00081
00082
00087
00088 void visir_queue_delete(visir_queue * q)
00089 {
00090 cx_list_delete(q->queue);
00091 omp_destroy_lock(&(q->lock));
00092 cpl_free(q);
00093 }
00094
00095
00096
00102
00103 void visir_queue_set_error(visir_queue * q, cpl_error_code error)
00104 {
00105 omp_set_lock(&(q->lock));
00106 q->error = error;
00107 omp_unset_lock(&(q->lock));
00108 }
00109
00110
00111
00122
00123 cpl_error_code visir_queue_put(visir_queue * q, void * data)
00124 {
00125
00126 #pragma omp flush
00127 while (q->size >= q->max_size && q->error == CPL_ERROR_NONE) {
00128
00129 struct timespec ts = { 0, 50 * 1000000 };
00130 nanosleep(&ts, NULL);
00131 #pragma omp taskyield
00132 #pragma omp flush
00133 }
00134
00135 omp_set_lock(&(q->lock));
00136 if (q->size >= q->max_size || q->error != CPL_ERROR_NONE) {
00137 omp_unset_lock(&(q->lock));
00138 return q->error;
00139 }
00140 cx_list_push_back(q->queue, data);
00141 q->size++;
00142 omp_unset_lock(&(q->lock));
00143
00144 return CPL_ERROR_NONE;
00145 }
00146
00147
00148
00158
00159 void * visir_queue_pop(visir_queue * q)
00160 {
00161 void * data = NULL;
00162
00163 while (1) {
00164 omp_set_lock(&(q->lock));
00165 if (q->size > 0 && q->error == CPL_ERROR_NONE) {
00166 data = cx_list_pop_front(q->queue);
00167 q->size--;
00168 omp_unset_lock(&(q->lock));
00169 break;
00170 }
00171 else {
00172 omp_unset_lock(&(q->lock));
00173
00174 struct timespec ts;
00175 ts.tv_sec = 0;
00176 ts.tv_nsec = 50 * 1000000;
00177 if (q->error != CPL_ERROR_NONE)
00178 return NULL;
00179 nanosleep(&ts, NULL);
00180 #pragma omp taskyield
00181 }
00182 }
00183 return data;
00184 }
00185
00186 #endif