00001 #ifndef _CKTASKQUEUE_H
00002 #define _CKTASKQUEUE_H
00003 #define TaskQueueSize 1024
00004
00005 #define TaskQueueDebug(...) //CmiPrintf(__VA_ARGS__)
00006
00007
00008
00009 #ifdef _WIN32
00010 #define WIN32_LEAN_AND_MEAN
00011 #include <windows.h>
00012 typedef LONG taskq_idx;
00013 #else
00014 typedef int taskq_idx;
00015 #endif
00016 typedef struct TaskQueueStruct {
00017 taskq_idx head;
00018 taskq_idx tail;
00019 void *data[TaskQueueSize];
00020 } *TaskQueue;
00021
00022 inline static TaskQueue TaskQueueCreate() {
00023 TaskQueue t = (TaskQueue)malloc(sizeof(struct TaskQueueStruct));
00024 t->head = 0;
00025 t->tail = 0;
00026 return t;
00027 }
00028
00029 inline static void TaskQueuePush(TaskQueue Q, void *data) {
00030 Q->data[ Q->tail % TaskQueueSize] = data;
00031 CmiMemoryWriteFence();
00032 Q->tail +=1;
00033 }
00034
00035 inline static void* TaskQueuePop(TaskQueue Q) {
00036 TaskQueueDebug("[%d] TaskQueuePop head %d tail %d\n", CmiMyPe(), Q->head, Q->tail);
00037 taskq_idx h, t;
00038 t = Q->tail -1;
00039 Q->tail = t;
00040 CmiMemoryWriteFence();
00041 h = Q->head;
00042 if (t > h) {
00043 TaskQueueDebug("[%d] returning valid data\n", CmiMyPe());
00044 return Q->data[t % TaskQueueSize];
00045 }
00046
00047 if (t < h) {
00048 Q->tail = h;
00049 return NULL;
00050 }
00051
00052 Q->tail = h + 1;
00053 #ifdef _WIN32
00054 if (h != InterlockedCompareExchange(&(Q->head), h+1,h))
00055 #else
00056 if (!__sync_bool_compare_and_swap(&(Q->head), h, h+1))
00057 #endif
00058 return NULL;
00059 return Q->data[t % TaskQueueSize];
00060 }
00061
00062 inline static void* TaskQueueSteal(TaskQueue Q) {
00063 taskq_idx h, t;
00064 void *task;
00065 while (1) {
00066 h = Q->head;
00067 t = Q->tail;
00068 if (h >= t)
00069 return NULL;
00070 #ifdef _WIN32
00071 if (h != InterlockedCompareExchange(&(Q->head), h+1, h))
00072 #else
00073 if (!__sync_bool_compare_and_swap(&(Q->head), h, h+1))
00074 #endif
00075 continue;
00076 return Q->data[h % TaskQueueSize];
00077 }
00078 }
00079
00080 #endif