]> arthur.barton.de Git - netatalk.git/blob - libatalk/tevent/tevent_queue.c
Add lib tevent from Samba
[netatalk.git] / libatalk / tevent / tevent_queue.c
1 /*
2    Unix SMB/CIFS implementation.
3    Infrastructure for async requests
4    Copyright (C) Volker Lendecke 2008
5    Copyright (C) Stefan Metzmacher 2009
6
7      ** NOTE! The following LGPL license applies to the tevent
8      ** library. This does NOT imply that all of Samba is released
9      ** under the LGPL
10
11    This library is free software; you can redistribute it and/or
12    modify it under the terms of the GNU Lesser General Public
13    License as published by the Free Software Foundation; either
14    version 3 of the License, or (at your option) any later version.
15
16    This library is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    Lesser General Public License for more details.
20
21    You should have received a copy of the GNU Lesser General Public
22    License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include <atalk/tevent.h>
26 #include "tevent_internal.h"
27 #include "tevent_util.h"
28
29 struct tevent_queue_entry {
30         struct tevent_queue_entry *prev, *next;
31         struct tevent_queue *queue;
32
33         bool triggered;
34
35         struct tevent_req *req;
36         struct tevent_context *ev;
37
38         tevent_queue_trigger_fn_t trigger;
39         void *private_data;
40 };
41
42 struct tevent_queue {
43         const char *name;
44         const char *location;
45
46         bool running;
47         struct tevent_immediate *immediate;
48
49         size_t length;
50         struct tevent_queue_entry *list;
51 };
52
53 static void tevent_queue_immediate_trigger(struct tevent_context *ev,
54                                            struct tevent_immediate *im,
55                                            void *private_data);
56
57 static int tevent_queue_entry_destructor(struct tevent_queue_entry *e)
58 {
59         struct tevent_queue *q = e->queue;
60
61         if (!q) {
62                 return 0;
63         }
64
65         DLIST_REMOVE(q->list, e);
66         q->length--;
67
68         if (!q->running) {
69                 return 0;
70         }
71
72         if (!q->list) {
73                 return 0;
74         }
75
76         if (q->list->triggered) {
77                 return 0;
78         }
79
80         tevent_schedule_immediate(q->immediate,
81                                   q->list->ev,
82                                   tevent_queue_immediate_trigger,
83                                   q);
84
85         return 0;
86 }
87
88 static int tevent_queue_destructor(struct tevent_queue *q)
89 {
90         q->running = false;
91
92         while (q->list) {
93                 struct tevent_queue_entry *e = q->list;
94                 talloc_free(e);
95         }
96
97         return 0;
98 }
99
100 struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx,
101                                           const char *name,
102                                           const char *location)
103 {
104         struct tevent_queue *queue;
105
106         queue = talloc_zero(mem_ctx, struct tevent_queue);
107         if (!queue) {
108                 return NULL;
109         }
110
111         queue->name = talloc_strdup(queue, name);
112         if (!queue->name) {
113                 talloc_free(queue);
114                 return NULL;
115         }
116         queue->immediate = tevent_create_immediate(queue);
117         if (!queue->immediate) {
118                 talloc_free(queue);
119                 return NULL;
120         }
121
122         queue->location = location;
123
124         /* queue is running by default */
125         queue->running = true;
126
127         talloc_set_destructor(queue, tevent_queue_destructor);
128         return queue;
129 }
130
131 static void tevent_queue_immediate_trigger(struct tevent_context *ev,
132                                            struct tevent_immediate *im,
133                                            void *private_data)
134 {
135         struct tevent_queue *q = talloc_get_type(private_data,
136                                   struct tevent_queue);
137
138         if (!q->running) {
139                 return;
140         }
141
142         q->list->triggered = true;
143         q->list->trigger(q->list->req, q->list->private_data);
144 }
145
146 bool tevent_queue_add(struct tevent_queue *queue,
147                       struct tevent_context *ev,
148                       struct tevent_req *req,
149                       tevent_queue_trigger_fn_t trigger,
150                       void *private_data)
151 {
152         struct tevent_queue_entry *e;
153
154         e = talloc_zero(req, struct tevent_queue_entry);
155         if (e == NULL) {
156                 return false;
157         }
158
159         e->queue = queue;
160         e->req = req;
161         e->ev = ev;
162         e->trigger = trigger;
163         e->private_data = private_data;
164
165         DLIST_ADD_END(queue->list, e, struct tevent_queue_entry *);
166         queue->length++;
167         talloc_set_destructor(e, tevent_queue_entry_destructor);
168
169         if (!queue->running) {
170                 return true;
171         }
172
173         if (queue->list->triggered) {
174                 return true;
175         }
176
177         tevent_schedule_immediate(queue->immediate,
178                                   queue->list->ev,
179                                   tevent_queue_immediate_trigger,
180                                   queue);
181
182         return true;
183 }
184
185 void tevent_queue_start(struct tevent_queue *queue)
186 {
187         if (queue->running) {
188                 /* already started */
189                 return;
190         }
191
192         queue->running = true;
193
194         if (!queue->list) {
195                 return;
196         }
197
198         if (queue->list->triggered) {
199                 return;
200         }
201
202         tevent_schedule_immediate(queue->immediate,
203                                   queue->list->ev,
204                                   tevent_queue_immediate_trigger,
205                                   queue);
206 }
207
208 void tevent_queue_stop(struct tevent_queue *queue)
209 {
210         queue->running = false;
211 }
212
213 size_t tevent_queue_length(struct tevent_queue *queue)
214 {
215         return queue->length;
216 }