summaryrefslogtreecommitdiff
path: root/tacplus-daemon/queue.c
blob: fae583f97aada9695ca16e82273f9376ca13c35e (plain)
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
	TACACS+ D-Bus Daemon code

	Copyright (c) 2018 AT&T Intellectual Property.
	Copyright (c) 2015-2016 Brocade Communications Systems, Inc.

	SPDX-License-Identifier: GPL-2.0-only
*/

#include "queue.h"

Queue * create_queue(void (*free_element)(void *))
{
	Queue *q;
	q = malloc(sizeof(*q));

	if (q == NULL) {
		syslog(LOG_ERR, "Failed to allocate queue");
	}
	else {
		q->front = NULL;
		q->rear = NULL;
		q->free_element = free_element;
		pthread_mutex_init(&(q->lock), NULL);
		pthread_cond_init(&(q->empty), NULL);
	}
	return q;
}

void enqueue(Queue *q, void *e)
{
	Node *n;

	if (q == NULL || e == NULL)
		return;

	pthread_mutex_lock(&(q->lock));

	n = malloc(sizeof(*n));
	n->element = e;
	n->next = NULL;

	if (is_queue_empty(q)) {
		q->front = n;
		q->rear = n;
	}
	else {
		q->rear->next = n;
		q->rear = n;
	}
	pthread_cond_broadcast(&(q->empty));
	pthread_mutex_unlock(&(q->lock));
}

void re_enqueue(Queue *q, void *e)
{
	Node *n;

	if (q == NULL || e == NULL)
		return;

	pthread_mutex_lock(&(q->lock));

	n = malloc(sizeof(*n));
	n->element = e;
	n->next = q->front;

	if (is_queue_empty(q)) {
		q->front = n;
		q->rear = n;
	}
	else {
		q->front = n;
	}
	pthread_cond_broadcast(&(q->empty));
	pthread_mutex_unlock(&(q->lock));
}

void * dequeue(Queue *q)
{
	Node *n, *nextNode;
	void *data = NULL;

	pthread_mutex_lock(&(q->lock));

	if (!is_queue_empty(q)) {
		n = q->front;
		nextNode = q->front->next;
		if (q->front == q->rear) {
			q->rear = nextNode;
		}
		q->front = nextNode;
		data = n->element;
		free(n);
	}
	pthread_cond_broadcast(&(q->empty));
	pthread_mutex_unlock(&(q->lock));
	return data;
}

int is_queue_empty(Queue *q)
{
	return (q->front == NULL);
}

void destroy_queue(Queue **q)
{
	Node *n = NULL;
	Node *next_n;

	if (!q || !*q)
		return;

	for (n = (*q)->front; n != NULL ; n = next_n) {
		next_n = n->next;
		if((*q)->free_element)
			(*q)->free_element(n->element);
		free(n);
	}

	pthread_mutex_destroy(&((*q)->lock));
	pthread_cond_destroy(&((*q)->empty));

	free(*q);
	*q = NULL;
}