-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathqueue.h
More file actions
106 lines (84 loc) · 2.75 KB
/
queue.h
File metadata and controls
106 lines (84 loc) · 2.75 KB
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
103
104
105
106
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#define QUEUE_MAX 256
#define QUEUE_MSG_SIZE 512
#define MAX_COMMAND_LEN 50 // Support multi-word messages + NULL terminator
//added has_addr so that it works for client side and server side queues. Clients dont need from_addr
typedef struct {
char msg[QUEUE_MSG_SIZE];
struct sockaddr_in from_addr;
int has_addr;
} queue_node_t;
typedef struct {
queue_node_t data[QUEUE_MAX];
int head;
int tail;
int size;
pthread_mutex_t lock;
pthread_cond_t nonempty;
pthread_cond_t nonfull;
} Queue;
void queue_init(Queue *q){
q->head = 0;
q->tail = 0;
q->size = 0;
pthread_mutex_init(&q->lock, NULL);
pthread_cond_init(&q->nonempty, NULL);
pthread_cond_init(&q->nonfull, NULL);
}
void remove_dollar_sign(char* str){
char* p = strchr(str, '$');
if (!p) return;
memmove(p,p+1,strlen(p));
}
void get_and_tokenise(queue_node_t *node, char * args[]){
remove_dollar_sign(node->msg);
char *token = strtok(node->msg, " ");
int argsc = 0;
while (token != NULL && argsc < MAX_COMMAND_LEN - 1) // max 3 args, leave room for NULL
{
args[(argsc)++] = token;
token = strtok(NULL, " ");
}
args[argsc] = NULL; //args must be null terminated
}
//add to the thread and give nonempty signal under mutex
void q_append(Queue* q, char* msg, struct sockaddr_in* from_addr){
pthread_mutex_lock(&q->lock);
while ((q->tail + 1) % QUEUE_MAX == q->head) { // queue full
pthread_cond_wait(&q->nonfull, &q->lock);
}
queue_node_t *node = &q->data[q->tail];
strncpy(node->msg, msg, QUEUE_MSG_SIZE);
node->msg[QUEUE_MSG_SIZE - 1] = '\0';
if (from_addr != NULL){
node->from_addr = *from_addr;
node->has_addr = 1;
} else {
node->has_addr = 0;
}
q->tail = (q->tail + 1) % QUEUE_MAX;
q->size++;
pthread_cond_signal(&q->nonempty);
pthread_mutex_unlock(&q->lock);
}
//put the current thread to sleep based on if the queue is empty then store head tokenised elements in out arr
void q_pop(Queue * q, char * out[], struct sockaddr_in * sender){
pthread_mutex_lock(&q->lock);
while (q->head == q->tail){
pthread_cond_wait(&q->nonempty, &q->lock);
}
int idx = q->head;
queue_node_t *node = &q->data[idx];
get_and_tokenise(node, out);
if (sender != NULL) {
if (node->has_addr) *sender = node->from_addr;
else memset(sender, 0, sizeof(*sender));
}
q->head = (q->head + 1) % QUEUE_MAX;
q->size--;
pthread_cond_signal(&q->nonfull);
pthread_mutex_unlock(&q->lock);
}