Fijate que lo único que cambiaría de la interfaz sería agregarle el Heap a la estructura y los prototipos de Queue_create() y Queue_destroy(). Ésto es para reservar/liberar la memoria para la estructura tipo Queue. La implementación, modificando un poco el tad Queue que expuse durante la C Talk III, sería así:
Queue *Queue_create(HANDLE callingProcessHeap){
Queue* q = (Queue*) HeapAlloc(callingProcessHeap, HEAP_NO_SERIALIZE, sizeof(t_queue));
q->head = NULL;
q->tail = NULL;
q->elem_count = 0;
if ((q->mutex = (HANDLE) CreateMutex(NULL, FALSE, NULL)) == NULL){
HeapFree(callingProcessHeap, HEAP_NO_SERIALIZE, q);
return NULL;
}
if ((q->heap = (HANDLE) HeapCreate(HEAP_NO_SERIALIZE, 1024*1024, 0)) == NULL) {
CloseHandle(q->mutex);
HeapFree(callingProcessHeap, HEAP_NO_SERIALIZE, q);
return NULL;
}
return q;
}
void Queue_push(Queue *q, void *data){
WaitForSingleObject(q->mutex, INFINITE);
if( data != NULL ){
LinkElement *auxElement = (LinkElement*) HeapAlloc(q->heap, HEAP_NO_SERIALIZE, sizeof(LinkElement));
auxElement->data = data;
auxElement->next = NULL;
if( q->tail != NULL ){
q->tail->next = auxElement;
q->tail = q->tail->next;
}else{
q->head = auxElement;
q->tail = auxElement;
}
q->elem_count++;
}
ReleaseMutex(q->mutex);
}
void *Queue_pop(Queue *q){
void *data = NULL;
WaitForSingleObject(q->mutex, INFINITE);
if( q->head != NULL ){
LinkElement *element = q->head;
q->head = q->head->next;
if( q->head == NULL ){
q->tail = NULL;
}
data = element->data;
HeapFree(q->heap, HEAP_NO_SERIALIZE, element);
q->elem_count--;
}
ReleaseMutex(q->mutex);
return data;
}
void Queue_destroy(HANDLE callingProcessHeap, Queue *q){
CloseHandle(q->mutex);
HeapDestroy(q->heap);
HeapFree(callingProcessHeap, HEAP_NO_SERIALIZE, q);
}
Como ves, inevitablemente tendrías que hacer una primer reserva al Heap pasado como argumento en la función Queue_create(). Este Heap es únicamente para reservar memoria para la estructura. Dado que varios Threads comparten la misma Queue, sería el Heap del Proceso, previamente creado. Lo mismo ocurre con Queue_destroy(): se destruye la Queue en el Proceso, no en los Threads.
Y dentro de Queue_push() y Queue_pop(), se reserva/libera del Heap de la Queue.