forked from NeroReflex/ROGueENEMY
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathqueue.c
102 lines (75 loc) · 2.29 KB
/
queue.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include "queue.h"
int queue_init(queue_t* const q, size_t max_elements) {
q->front = q->rear = -1;
q->array_size = max_elements;
if (pthread_mutex_init(&q->mutex, NULL) != 0) {
perror("mutex");
return -1;
}
q->array = calloc(sizeof(void*), max_elements);
if (q->array == NULL) {
perror("calloc");
return -1;
}
sem_init(&q->empty, 0, q->array_size);
sem_init(&q->full, 0, 0);
return 0;
}
void queue_destroy(queue_t* q) {
free(q->array);
q->array = NULL;
}
int queue_push(queue_t* const q, void *in_item) {
sem_wait(&q->empty);
pthread_mutex_lock(&q->mutex);
q->rear = (q->rear + 1) % q->array_size;
q->array[q->rear] = in_item;
pthread_mutex_unlock(&q->mutex);
sem_post(&q->full);
return 0;
}
int queue_pop(queue_t* const q, void **out_item) {
sem_wait(&q->full);
pthread_mutex_lock(&q->mutex);
q->front = (q->front + 1) % q->array_size;
*out_item = q->array[q->front];
pthread_mutex_unlock(&q->mutex);
sem_post(&q->empty);
return 0;
}
int queue_push_timeout(queue_t* const q, void *in_item, int timeout_ms) {
struct timespec timeout;
if (clock_gettime(CLOCK_REALTIME, &timeout) == -1) {
// Handle clock_gettime error
return -1;
}
timeout.tv_sec += timeout_ms / 1000;
timeout.tv_nsec += (timeout_ms % 1000) * 1000000;
int result = sem_timedwait(&q->empty, &timeout);
if (result == 0) {
pthread_mutex_lock(&q->mutex);
q->rear = (q->rear + 1) % q->array_size;
q->array[q->rear] = in_item;
pthread_mutex_unlock(&q->mutex);
sem_post(&q->full);
}
return result;
}
int queue_pop_timeout(queue_t* const q, void **out_item, int timeout_ms) {
struct timespec timeout;
if (clock_gettime(CLOCK_MONOTONIC, &timeout) == -1) {
// Handle clock_gettime error
return -1;
}
timeout.tv_sec += timeout_ms / 1000;
timeout.tv_nsec += (timeout_ms % 1000) * 1000000;
int result = sem_timedwait(&q->full, &timeout);
if (result == 0) {
pthread_mutex_lock(&q->mutex);
q->front = (q->front + 1) % q->array_size;
*out_item = q->array[q->front];
pthread_mutex_unlock(&q->mutex);
sem_post(&q->empty);
}
return result;
}