ble_gatt_client
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
queue.c
Go to the documentation of this file.
1 
10 /*
11  *
12  * BlueZ - Bluetooth protocol stack for Linux
13  *
14  * Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
15  *
16  *
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  *
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25  * Lesser General Public License for more details.
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30  *
31  */
32 
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36 
37 #include "util.h"
38 #include "queue.h"
39 
40 struct queue {
41  int ref_count;
42  struct queue_entry *head;
43  struct queue_entry *tail;
44  unsigned int entries;
45 };
46 
53 static struct queue *queue_ref(struct queue *queue)
54 {
55  if (!queue)
56  return NULL;
57 
58  __sync_fetch_and_add(&queue->ref_count, 1);
59 
60  return queue;
61 }
62 
68 static void queue_unref(struct queue *queue)
69 {
70  if (__sync_sub_and_fetch(&queue->ref_count, 1))
71  return;
72 
73  free(queue);
74 }
75 
81 struct queue *queue_new(void)
82 {
83  struct queue *queue;
84 
85  queue = new0(struct queue, 1);
86  if (!queue)
87  return NULL;
88 
89  queue->head = NULL;
90  queue->tail = NULL;
91  queue->entries = 0;
92 
93  return queue_ref(queue);
94 }
95 
103 {
104  if (!queue)
105  return;
106 
107  queue_remove_all(queue, NULL, NULL, destroy);
108 
109  queue_unref(queue);
110 }
111 
118 static struct queue_entry *queue_entry_ref(struct queue_entry *entry)
119 {
120  if (!entry)
121  return NULL;
122 
123  __sync_fetch_and_add(&entry->ref_count, 1);
124 
125  return entry;
126 }
127 
133 static void queue_entry_unref(struct queue_entry *entry)
134 {
135  if (__sync_sub_and_fetch(&entry->ref_count, 1))
136  return;
137 
138  free(entry);
139 }
140 
147 static struct queue_entry *queue_entry_new(void *data)
148 {
149  struct queue_entry *entry;
150 
151  entry = new0(struct queue_entry, 1);
152  if (!entry)
153  return NULL;
154 
155  entry->data = data;
156 
157  return queue_entry_ref(entry);
158 }
159 
167 bool queue_push_tail(struct queue *queue, void *data)
168 {
169  struct queue_entry *entry;
170 
171  if (!queue)
172  return false;
173 
174  entry = queue_entry_new(data);
175  if (!entry)
176  return false;
177 
178  if (queue->tail)
179  queue->tail->next = entry;
180 
181  queue->tail = entry;
182 
183  if (!queue->head)
184  queue->head = entry;
185 
186  queue->entries++;
187 
188  return true;
189 }
190 
198 bool queue_push_head(struct queue *queue, void *data)
199 {
200  struct queue_entry *entry;
201 
202  if (!queue)
203  return false;
204 
205  entry = queue_entry_new(data);
206  if (!entry)
207  return false;
208 
209  entry->next = queue->head;
210 
211  queue->head = entry;
212 
213  if (!queue->tail)
214  queue->tail = entry;
215 
216  queue->entries++;
217 
218  return true;
219 }
220 
229 bool queue_push_after(struct queue *queue, void *entry, void *data)
230 {
231  struct queue_entry *qentry, *tmp, *new_entry;
232 
233  qentry = NULL;
234 
235  if (!queue)
236  return false;
237 
238  for (tmp = queue->head; tmp; tmp = tmp->next) {
239  if (tmp->data == entry) {
240  qentry = tmp;
241  break;
242  }
243  }
244 
245  if (!qentry)
246  return false;
247 
248  new_entry = queue_entry_new(data);
249  if (!new_entry)
250  return false;
251 
252  new_entry->next = qentry->next;
253 
254  if (!qentry->next)
255  queue->tail = new_entry;
256 
257  qentry->next = new_entry;
258  queue->entries++;
259 
260  return true;
261 }
262 
268 void *queue_pop_head(struct queue *queue)
269 {
270  struct queue_entry *entry;
271  void *data;
272 
273  if (!queue || !queue->head)
274  return NULL;
275 
276  entry = queue->head;
277 
278  if (!queue->head->next) {
279  queue->head = NULL;
280  queue->tail = NULL;
281  } else
282  queue->head = queue->head->next;
283 
284  data = entry->data;
285 
286  queue_entry_unref(entry);
287  queue->entries--;
288 
289  return data;
290 }
291 
298 {
299  if (!queue || !queue->head)
300  return NULL;
301 
302  return queue->head->data;
303 }
304 
311 {
312  if (!queue || !queue->tail)
313  return NULL;
314 
315  return queue->tail->data;
316 }
317 
326  void *user_data)
327 {
328  struct queue_entry *entry;
329 
330  if (!queue || !function)
331  return;
332 
333  entry = queue->head;
334  if (!entry)
335  return;
336 
337  queue_ref(queue);
338  while (entry && queue->head && queue->ref_count > 1) {
339  struct queue_entry *next;
340 
341  queue_entry_ref(entry);
342 
343  function(entry->data, user_data);
344 
345  next = entry->next;
346 
347  queue_entry_unref(entry);
348 
349  entry = next;
350  }
351  queue_unref(queue);
352 }
353 
362 static bool direct_match(const void *a, const void *b)
363 {
364  return a == b;
365 }
366 
376 void *queue_find(struct queue *queue, queue_match_func_t function,
377  const void *match_data)
378 {
379  struct queue_entry *entry;
380 
381  if (!queue)
382  return NULL;
383 
384  if (!function)
385  function = direct_match;
386 
387  for (entry = queue->head; entry; entry = entry->next)
388  if (function(entry->data, match_data))
389  return entry->data;
390 
391  return NULL;
392 }
393 
402 bool queue_remove(struct queue *queue, void *data)
403 {
404  struct queue_entry *entry, *prev;
405 
406  if (!queue)
407  return false;
408 
409  for (entry = queue->head, prev = NULL; entry;
410  prev = entry, entry = entry->next) {
411  if (entry->data != data)
412  continue;
413 
414  if (prev)
415  prev->next = entry->next;
416  else
417  queue->head = entry->next;
418 
419  if (!entry->next)
420  queue->tail = prev;
421 
422  queue_entry_unref(entry);
423  queue->entries--;
424 
425  return true;
426  }
427 
428  return false;
429 }
430 
441  void *user_data)
442 {
443  struct queue_entry *entry, *prev = NULL;
444 
445  if (!queue || !function)
446  return NULL;
447 
448  entry = queue->head;
449 
450  while (entry) {
451  if (function(entry->data, user_data)) {
452  void *data;
453 
454  if (prev)
455  prev->next = entry->next;
456  else
457  queue->head = entry->next;
458 
459  if (!entry->next)
460  queue->tail = prev;
461 
462  data = entry->data;
463 
464  queue_entry_unref(entry);
465  queue->entries--;
466 
467  return data;
468  } else {
469  prev = entry;
470  entry = entry->next;
471  }
472  }
473 
474  return NULL;
475 }
476 
487 unsigned int queue_remove_all(struct queue *queue, queue_match_func_t function,
488  void *user_data, queue_destroy_func_t destroy)
489 {
490  struct queue_entry *entry;
491  unsigned int count = 0;
492 
493  if (!queue)
494  return 0;
495 
496  entry = queue->head;
497 
498  if (function) {
499  while (entry) {
500  void *data;
501  unsigned int entries = queue->entries;
502 
503  data = queue_remove_if(queue, function, user_data);
504  if (entries == queue->entries)
505  break;
506 
507  if (destroy)
508  destroy(data);
509 
510  count++;
511  }
512  } else {
513  queue->head = NULL;
514  queue->tail = NULL;
515  queue->entries = 0;
516 
517  while (entry) {
518  struct queue_entry *tmp = entry;
519 
520  entry = entry->next;
521 
522  if (destroy)
523  destroy(tmp->data);
524 
525  queue_entry_unref(tmp);
526  count++;
527  }
528  }
529 
530  return count;
531 }
532 
540 const struct queue_entry *queue_get_entries(struct queue *queue)
541 {
542  if (!queue)
543  return NULL;
544 
545  return queue->head;
546 }
547 
555 unsigned int queue_length(struct queue *queue)
556 {
557  if (!queue)
558  return 0;
559 
560  return queue->entries;
561 }
562 
569 bool queue_isempty(struct queue *queue)
570 {
571  if (!queue)
572  return true;
573 
574  return queue->entries == 0;
575 }
unsigned int entries
Definition: queue.c:44
void * queue_find(struct queue *queue, queue_match_func_t function, const void *match_data)
Definition: queue.c:376
void queue_foreach(struct queue *queue, queue_foreach_func_t function, void *user_data)
Definition: queue.c:325
const struct queue_entry * queue_get_entries(struct queue *queue)
Definition: queue.c:540
static struct queue_entry * queue_entry_new(void *data)
Definition: queue.c:147
static bool direct_match(const void *a, const void *b)
Definition: queue.c:362
void(* queue_destroy_func_t)(void *data)
Definition: queue.h:26
void * data
Definition: queue.h:32
int ref_count
Definition: queue.c:41
bool queue_push_after(struct queue *queue, void *entry, void *data)
Definition: queue.c:229
void * queue_pop_head(struct queue *queue)
Definition: queue.c:268
unsigned int queue_length(struct queue *queue)
Definition: queue.c:555
Definition: queue.h:30
struct queue_entry * head
Definition: queue.c:42
static struct queue * queue_ref(struct queue *queue)
Definition: queue.c:53
Definition: queue.c:40
bool queue_isempty(struct queue *queue)
Definition: queue.c:569
void queue_destroy(struct queue *queue, queue_destroy_func_t destroy)
Definition: queue.c:102
void * queue_peek_head(struct queue *queue)
Definition: queue.c:297
bool queue_push_tail(struct queue *queue, void *data)
Definition: queue.c:167
int ref_count
Definition: queue.h:31
struct queue * queue_new(void)
Definition: queue.c:81
bool queue_remove(struct queue *queue, void *data)
Definition: queue.c:402
unsigned int queue_remove_all(struct queue *queue, queue_match_func_t function, void *user_data, queue_destroy_func_t destroy)
Definition: queue.c:487
static void queue_entry_unref(struct queue_entry *entry)
Definition: queue.c:133
void(* queue_foreach_func_t)(void *data, void *user_data)
Definition: queue.h:46
void * queue_peek_tail(struct queue *queue)
Definition: queue.c:310
struct queue_entry * tail
Definition: queue.c:43
void * queue_remove_if(struct queue *queue, queue_match_func_t function, void *user_data)
Definition: queue.c:440
bool(* queue_match_func_t)(const void *data, const void *match_data)
Definition: queue.h:51
struct queue_entry * next
Definition: queue.h:33
static void queue_unref(struct queue *queue)
Definition: queue.c:68
#define new0(t, n)
Definition: util.h:82
static struct queue_entry * queue_entry_ref(struct queue_entry *entry)
Definition: queue.c:118
bool queue_push_head(struct queue *queue, void *data)
Definition: queue.c:198