1 /*
2 The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3 Copyright (C) 2001-2020 Aymeric MOIZARD amoizard@antisip.com
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #include <osip2/internal.h>
21
22 #include <osipparser2/osip_port.h>
23 #include <osip2/osip_fifo.h>
24
25 /* always use this method to initiate osip_fifo_t.
26 */
osip_fifo_init(osip_fifo_t * ff)27 void osip_fifo_init(osip_fifo_t *ff) {
28 #ifndef OSIP_MONOTHREAD
29 ff->qislocked = osip_mutex_init();
30 /*INIT SEMA TO BLOCK ON GET() WHEN QUEUE IS EMPTY */
31 ff->qisempty = osip_sem_init(0);
32 #endif
33 osip_list_init(&ff->queue);
34 /* ff->nb_elt = 0; */
35 ff->state = osip_empty;
36 }
37
osip_fifo_add(osip_fifo_t * ff,void * el)38 int osip_fifo_add(osip_fifo_t *ff, void *el) {
39 #ifndef OSIP_MONOTHREAD
40 osip_mutex_lock(ff->qislocked);
41 #endif
42
43 osip_list_add(&ff->queue, el, -1); /* insert at end of queue */
44 ff->state = osip_ok;
45
46 #ifndef OSIP_MONOTHREAD
47 osip_sem_post(ff->qisempty);
48 osip_mutex_unlock(ff->qislocked);
49 #endif
50 return OSIP_SUCCESS;
51 }
52
osip_fifo_insert(osip_fifo_t * ff,void * el)53 int osip_fifo_insert(osip_fifo_t *ff, void *el) {
54 #ifndef OSIP_MONOTHREAD
55 osip_mutex_lock(ff->qislocked);
56 #endif
57
58 osip_list_add(&ff->queue, el, 0); /* insert at end of queue */
59 ff->state = osip_ok;
60
61 #ifndef OSIP_MONOTHREAD
62 osip_sem_post(ff->qisempty);
63 osip_mutex_unlock(ff->qislocked);
64 #endif
65 return OSIP_SUCCESS;
66 }
67
osip_fifo_size(osip_fifo_t * ff)68 int osip_fifo_size(osip_fifo_t *ff) {
69 int i;
70
71 #ifndef OSIP_MONOTHREAD
72 osip_mutex_lock(ff->qislocked);
73 #endif
74
75 i = osip_list_size(&ff->queue);
76 #ifndef OSIP_MONOTHREAD
77 osip_mutex_unlock(ff->qislocked);
78 #endif
79 return i;
80 }
81
osip_fifo_get(osip_fifo_t * ff)82 void *osip_fifo_get(osip_fifo_t *ff) {
83 void *el = NULL;
84
85 #ifndef OSIP_MONOTHREAD
86 int i = osip_sem_wait(ff->qisempty);
87
88 if (i != 0)
89 return NULL;
90
91 osip_mutex_lock(ff->qislocked);
92 #endif
93
94 if (ff->state != osip_empty) {
95 el = osip_list_get(&ff->queue, 0);
96 osip_list_remove(&ff->queue, 0);
97 /* ff->nb_elt--; */
98
99 } else {
100 OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_ERROR, NULL, "no element in fifo.\n"));
101 #ifndef OSIP_MONOTHREAD
102 osip_mutex_unlock(ff->qislocked);
103 #endif
104 return OSIP_SUCCESS; /* pile vide */
105 }
106
107 /* if (ff->nb_elt <= 0) */
108 if (osip_list_size(&ff->queue) <= 0)
109 ff->state = osip_empty;
110
111 else
112 ff->state = osip_ok;
113
114 #ifndef OSIP_MONOTHREAD
115 osip_mutex_unlock(ff->qislocked);
116 #endif
117 return el;
118 }
119
osip_fifo_tryget(osip_fifo_t * ff)120 void *osip_fifo_tryget(osip_fifo_t *ff) {
121 void *el = NULL;
122
123 #ifndef OSIP_MONOTHREAD
124
125 if (0 != osip_sem_trywait(ff->qisempty)) { /* no elements... */
126 return NULL;
127 }
128
129 osip_mutex_lock(ff->qislocked);
130 #else
131
132 if (ff->state == osip_empty)
133 return NULL;
134
135 #endif
136
137 if (ff->state != osip_empty) {
138 el = osip_list_get(&ff->queue, 0);
139 osip_list_remove(&ff->queue, 0);
140 /* ff->nb_elt--; */
141 }
142
143 #ifndef OSIP_MONOTHREAD
144
145 else { /* this case MUST never happen... */
146 OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO4, NULL, "no element in fifo.\n"));
147 osip_mutex_unlock(ff->qislocked);
148 return OSIP_SUCCESS;
149 }
150
151 #endif
152
153 /* if (ff->nb_elt <= 0) */
154 if (osip_list_size(&ff->queue) <= 0)
155 ff->state = osip_empty;
156
157 else
158 ff->state = osip_ok;
159
160 #ifndef OSIP_MONOTHREAD
161 osip_mutex_unlock(ff->qislocked);
162 #endif
163 return el;
164 }
165
osip_fifo_free(osip_fifo_t * ff)166 void osip_fifo_free(osip_fifo_t *ff) {
167 if (ff == NULL)
168 return;
169
170 #ifndef OSIP_MONOTHREAD
171 osip_mutex_destroy(ff->qislocked);
172 /* seems that pthread_mutex_destroy does not free space by itself */
173 osip_sem_destroy(ff->qisempty);
174 #endif
175 osip_free(ff);
176 }
177