botan: Add support for Ed25519 keys
[strongswan.git] / src / libstrongswan / collections / blocking_queue.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Copyright (C) 2012 Giuliano Grassi
4 * Copyright (C) 2012 Ralf Sager
5 * HSR Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include "blocking_queue.h"
19
20 #include <threading/mutex.h>
21 #include <threading/thread.h>
22 #include <threading/condvar.h>
23 #include <collections/linked_list.h>
24
25 typedef struct private_blocking_queue_t private_blocking_queue_t;
26
27 /**
28 * Private data of a blocking_queue_t object.
29 */
30 struct private_blocking_queue_t {
31
32 /**
33 * Public part
34 */
35 blocking_queue_t public;
36
37 /**
38 * Linked list containing all items in the queue
39 */
40 linked_list_t *list;
41
42 /**
43 * Mutex used to synchronize access to the queue
44 */
45 mutex_t *mutex;
46
47 /**
48 * Condvar used to wait for items
49 */
50 condvar_t *condvar;
51
52 };
53
54 METHOD(blocking_queue_t, enqueue, void,
55 private_blocking_queue_t *this, void *item)
56 {
57 this->mutex->lock(this->mutex);
58 this->list->insert_first(this->list, item);
59 this->condvar->signal(this->condvar);
60 this->mutex->unlock(this->mutex);
61 }
62
63 METHOD(blocking_queue_t, dequeue, void*,
64 private_blocking_queue_t *this)
65 {
66 bool oldstate;
67 void *item;
68
69
70 this->mutex->lock(this->mutex);
71 thread_cleanup_push((thread_cleanup_t)this->mutex->unlock, this->mutex);
72 /* ensure that a canceled thread does not dequeue any items */
73 thread_cancellation_point();
74 while (this->list->remove_last(this->list, &item) != SUCCESS)
75 {
76 oldstate = thread_cancelability(TRUE);
77 this->condvar->wait(this->condvar, this->mutex);
78 thread_cancelability(oldstate);
79 }
80 thread_cleanup_pop(TRUE);
81 return item;
82 }
83
84 METHOD(blocking_queue_t, destroy, void,
85 private_blocking_queue_t *this)
86 {
87 this->list->destroy(this->list);
88 this->condvar->destroy(this->condvar);
89 this->mutex->destroy(this->mutex);
90 free(this);
91 }
92
93 METHOD(blocking_queue_t, destroy_offset, void,
94 private_blocking_queue_t *this, size_t offset)
95 {
96 this->list->invoke_offset(this->list, offset);
97 destroy(this);
98 }
99
100 METHOD(blocking_queue_t, destroy_function, void,
101 private_blocking_queue_t *this, void (*fn)(void*))
102 {
103 this->list->invoke_function(this->list, (linked_list_invoke_t)fn);
104 destroy(this);
105 }
106
107 /*
108 * Described in header.
109 */
110 blocking_queue_t *blocking_queue_create()
111 {
112 private_blocking_queue_t *this;
113
114 INIT(this,
115 .public = {
116 .enqueue = _enqueue,
117 .dequeue = _dequeue,
118 .destroy = _destroy,
119 .destroy_offset = _destroy_offset,
120 .destroy_function = _destroy_function,
121 },
122 .list = linked_list_create(),
123 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
124 .condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
125 );
126
127 return &this->public;
128 }
129