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 "replace.h" 26#include "tevent.h" 27#include "tevent_internal.h" 28#include "tevent_util.h" 29 30struct tevent_queue_entry { 31 struct tevent_queue_entry *prev, *next; 32 struct tevent_queue *queue; 33 34 bool triggered; 35 36 struct tevent_req *req; 37 struct tevent_context *ev; 38 39 tevent_queue_trigger_fn_t trigger; 40 void *private_data; 41}; 42 43struct tevent_queue { 44 const char *name; 45 const char *location; 46 47 bool running; 48 struct tevent_immediate *immediate; 49 50 size_t length; 51 struct tevent_queue_entry *list; 52}; 53 54static void tevent_queue_immediate_trigger(struct tevent_context *ev, 55 struct tevent_immediate *im, 56 void *private_data); 57 58static int tevent_queue_entry_destructor(struct tevent_queue_entry *e) 59{ 60 struct tevent_queue *q = e->queue; 61 62 if (!q) { 63 return 0; 64 } 65 66 DLIST_REMOVE(q->list, e); 67 q->length--; 68 69 if (!q->running) { 70 return 0; 71 } 72 73 if (!q->list) { 74 return 0; 75 } 76 77 if (q->list->triggered) { 78 return 0; 79 } 80 81 tevent_schedule_immediate(q->immediate, 82 q->list->ev, 83 tevent_queue_immediate_trigger, 84 q); 85 86 return 0; 87} 88 89static int tevent_queue_destructor(struct tevent_queue *q) 90{ 91 q->running = false; 92 93 while (q->list) { 94 struct tevent_queue_entry *e = q->list; 95 talloc_free(e); 96 } 97 98 return 0; 99} 100 101struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx, 102 const char *name, 103 const char *location) 104{ 105 struct tevent_queue *queue; 106 107 queue = talloc_zero(mem_ctx, struct tevent_queue); 108 if (!queue) { 109 return NULL; 110 } 111 112 queue->name = talloc_strdup(queue, name); 113 if (!queue->name) { 114 talloc_free(queue); 115 return NULL; 116 } 117 queue->immediate = tevent_create_immediate(queue); 118 if (!queue->immediate) { 119 talloc_free(queue); 120 return NULL; 121 } 122 123 queue->location = location; 124 125 /* queue is running by default */ 126 queue->running = true; 127 128 talloc_set_destructor(queue, tevent_queue_destructor); 129 return queue; 130} 131 132static void tevent_queue_immediate_trigger(struct tevent_context *ev, 133 struct tevent_immediate *im, 134 void *private_data) 135{ 136 struct tevent_queue *q = talloc_get_type(private_data, 137 struct tevent_queue); 138 139 if (!q->running) { 140 return; 141 } 142 143 q->list->triggered = true; 144 q->list->trigger(q->list->req, q->list->private_data); 145} 146 147bool tevent_queue_add(struct tevent_queue *queue, 148 struct tevent_context *ev, 149 struct tevent_req *req, 150 tevent_queue_trigger_fn_t trigger, 151 void *private_data) 152{ 153 struct tevent_queue_entry *e; 154 155 e = talloc_zero(req, struct tevent_queue_entry); 156 if (e == NULL) { 157 return false; 158 } 159 160 e->queue = queue; 161 e->req = req; 162 e->ev = ev; 163 e->trigger = trigger; 164 e->private_data = private_data; 165 166 DLIST_ADD_END(queue->list, e, struct tevent_queue_entry *); 167 queue->length++; 168 talloc_set_destructor(e, tevent_queue_entry_destructor); 169 170 if (!queue->running) { 171 return true; 172 } 173 174 if (queue->list->triggered) { 175 return true; 176 } 177 178 tevent_schedule_immediate(queue->immediate, 179 queue->list->ev, 180 tevent_queue_immediate_trigger, 181 queue); 182 183 return true; 184} 185 186void tevent_queue_start(struct tevent_queue *queue) 187{ 188 if (queue->running) { 189 /* already started */ 190 return; 191 } 192 193 queue->running = true; 194 195 if (!queue->list) { 196 return; 197 } 198 199 if (queue->list->triggered) { 200 return; 201 } 202 203 tevent_schedule_immediate(queue->immediate, 204 queue->list->ev, 205 tevent_queue_immediate_trigger, 206 queue); 207} 208 209void tevent_queue_stop(struct tevent_queue *queue) 210{ 211 queue->running = false; 212} 213 214size_t tevent_queue_length(struct tevent_queue *queue) 215{ 216 return queue->length; 217} 218