]>
Commit | Line | Data |
---|---|---|
ddd639f6 JH |
1 | /** |
2 | * @file send_queue.c | |
79538669 | 3 | * |
d048df5c | 4 | * @brief Implementation of send_queue_t. |
79538669 | 5 | * |
ddd639f6 JH |
6 | */ |
7 | ||
8 | /* | |
9 | * Copyright (C) 2005 Jan Hutter, Martin Willi | |
10 | * Hochschule fuer Technik Rapperswil | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify it | |
13 | * under the terms of the GNU General Public License as published by the | |
14 | * Free Software Foundation; either version 2 of the License, or (at your | |
15 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, but | |
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
19 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
20 | * for more details. | |
21 | */ | |
79538669 | 22 | |
89e0f219 | 23 | #include <pthread.h> |
79538669 | 24 | |
b85d20d1 MW |
25 | #include "send_queue.h" |
26 | ||
8080fccb | 27 | #include <utils/linked_list.h> |
79538669 | 28 | |
95c61cb9 JH |
29 | |
30 | typedef struct private_send_queue_t private_send_queue_t; | |
31 | ||
a6cbf648 | 32 | /** |
ddd639f6 | 33 | * @brief Private Variables and Functions of send_queue class |
79538669 | 34 | * |
ddd639f6 | 35 | */ |
95c61cb9 | 36 | struct private_send_queue_t { |
ddd639f6 JH |
37 | /** |
38 | * Public part of the send_queue_t object | |
39 | */ | |
40 | send_queue_t public; | |
79538669 | 41 | |
ddd639f6 JH |
42 | /** |
43 | * The packets are stored in a linked list | |
44 | */ | |
45 | linked_list_t *list; | |
79538669 | 46 | |
ddd639f6 JH |
47 | /** |
48 | * access to linked_list is locked through this mutex | |
49 | */ | |
50 | pthread_mutex_t mutex; | |
79538669 | 51 | |
ddd639f6 JH |
52 | /** |
53 | * If the queue is empty a thread has to wait | |
54 | * This condvar is used to wake up such a thread | |
55 | */ | |
79538669 | 56 | pthread_cond_t condvar; |
ddd639f6 | 57 | }; |
79538669 JH |
58 | |
59 | ||
ddd639f6 | 60 | /** |
d048df5c | 61 | * implements send_queue_t.get_count |
ddd639f6 | 62 | */ |
1061c878 | 63 | static int get_count(private_send_queue_t *this) |
ddd639f6 | 64 | { |
1061c878 | 65 | int count; |
ddd639f6 | 66 | pthread_mutex_lock(&(this->mutex)); |
1061c878 | 67 | count = this->list->get_count(this->list); |
ddd639f6 | 68 | pthread_mutex_unlock(&(this->mutex)); |
1061c878 | 69 | return count; |
ddd639f6 | 70 | } |
79538669 | 71 | |
a6cbf648 | 72 | /** |
d048df5c | 73 | * implements send_queue_t.get |
ddd639f6 | 74 | */ |
d048df5c | 75 | static packet_t *get(private_send_queue_t *this) |
ddd639f6 | 76 | { |
ddd639f6 | 77 | int oldstate; |
d048df5c | 78 | packet_t *packet; |
ddd639f6 JH |
79 | pthread_mutex_lock(&(this->mutex)); |
80 | /* go to wait while no packets available */ | |
1061c878 JH |
81 | |
82 | while(this->list->get_count(this->list) == 0) | |
ddd639f6 JH |
83 | { |
84 | /* add mutex unlock handler for cancellation, enable cancellation */ | |
85 | pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, (void*)&(this->mutex)); | |
86 | pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); | |
87 | pthread_cond_wait( &(this->condvar), &(this->mutex)); | |
79538669 | 88 | |
ddd639f6 JH |
89 | /* reset cancellation, remove mutex-unlock handler (without executing) */ |
90 | pthread_setcancelstate(oldstate, NULL); | |
91 | pthread_cleanup_pop(0); | |
ddd639f6 | 92 | } |
d048df5c | 93 | this->list->remove_first(this->list,(void **)&packet); |
ddd639f6 | 94 | pthread_mutex_unlock(&(this->mutex)); |
d048df5c | 95 | return packet; |
ddd639f6 | 96 | } |
79538669 | 97 | |
a6cbf648 | 98 | /** |
d048df5c | 99 | * implements send_queue_t.add |
ddd639f6 | 100 | */ |
d048df5c | 101 | static void add(private_send_queue_t *this, packet_t *packet) |
ddd639f6 JH |
102 | { |
103 | pthread_mutex_lock(&(this->mutex)); | |
104 | this->list->insert_last(this->list,packet); | |
105 | pthread_cond_signal( &(this->condvar)); | |
106 | pthread_mutex_unlock(&(this->mutex)); | |
ddd639f6 | 107 | } |
79538669 | 108 | |
a6cbf648 | 109 | /** |
d048df5c | 110 | * implements send_queue_t.destroy |
ddd639f6 | 111 | */ |
d048df5c | 112 | static void destroy (private_send_queue_t *this) |
ddd639f6 | 113 | { |
79538669 | 114 | |
ddd639f6 | 115 | /* destroy all packets in list before destroying list */ |
1061c878 | 116 | while (this->list->get_count(this->list) > 0) |
ddd639f6 JH |
117 | { |
118 | packet_t *packet; | |
119 | if (this->list->remove_first(this->list,(void *) &packet) != SUCCESS) | |
120 | { | |
121 | this->list->destroy(this->list); | |
122 | break; | |
123 | } | |
124 | packet->destroy(packet); | |
ddd639f6 JH |
125 | } |
126 | this->list->destroy(this->list); | |
79538669 | 127 | |
ddd639f6 | 128 | pthread_mutex_destroy(&(this->mutex)); |
79538669 | 129 | |
ddd639f6 | 130 | pthread_cond_destroy(&(this->condvar)); |
79538669 | 131 | |
5113680f | 132 | free(this); |
ddd639f6 | 133 | } |
79538669 | 134 | |
a6cbf648 | 135 | /* |
79538669 | 136 | * |
ddd639f6 JH |
137 | * Documented in header |
138 | */ | |
139 | send_queue_t *send_queue_create() | |
140 | { | |
5113680f | 141 | private_send_queue_t *this = malloc_thing(private_send_queue_t); |
d048df5c | 142 | |
1061c878 | 143 | this->public.get_count = (int(*)(send_queue_t*)) get_count; |
d048df5c MW |
144 | this->public.get = (packet_t*(*)(send_queue_t*)) get; |
145 | this->public.add = (void(*)(send_queue_t*, packet_t*)) add; | |
146 | this->public.destroy = (void(*)(send_queue_t*)) destroy; | |
79538669 | 147 | |
d048df5c | 148 | this->list = linked_list_create(); |
ddd639f6 JH |
149 | pthread_mutex_init(&(this->mutex), NULL); |
150 | pthread_cond_init(&(this->condvar), NULL); | |
79538669 | 151 | |
ddd639f6 JH |
152 | return (&this->public); |
153 | } |