python:tests: Store keys as bytes rather than as lists of ints
[samba.git] / lib / tevent / tevent_immediate.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    common events code for immediate events
5
6    Copyright (C) Stefan Metzmacher 2009
7
8      ** NOTE! The following LGPL license applies to the tevent
9      ** library. This does NOT imply that all of Samba is released
10      ** under the LGPL
11
12    This library is free software; you can redistribute it and/or
13    modify it under the terms of the GNU Lesser General Public
14    License as published by the Free Software Foundation; either
15    version 3 of the License, or (at your option) any later version.
16
17    This library is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20    Lesser General Public License for more details.
21
22    You should have received a copy of the GNU Lesser General Public
23    License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "replace.h"
27 #include "tevent.h"
28 #include "tevent_internal.h"
29 #include "tevent_util.h"
30
31 static void tevent_common_immediate_cancel(struct tevent_immediate *im)
32 {
33         const char *create_location = im->create_location;
34         bool busy = im->busy;
35
36         if (im->destroyed) {
37                 tevent_abort(im->event_ctx, "tevent_immediate use after free");
38                 return;
39         }
40
41         if (!im->event_ctx) {
42                 return;
43         }
44
45         if (im->handler_name != NULL) {
46                 tevent_debug(im->event_ctx, TEVENT_DEBUG_TRACE,
47                              "Cancel immediate event %p \"%s\"\n",
48                              im, im->handler_name);
49         }
50
51         /* let the backend free im->additional_data */
52         if (im->cancel_fn) {
53                 im->cancel_fn(im);
54         }
55
56         DLIST_REMOVE(im->event_ctx->immediate_events, im);
57
58         *im = (struct tevent_immediate) {
59                 .create_location        = create_location,
60                 .busy                   = busy,
61         };
62
63         if (!busy) {
64                 talloc_set_destructor(im, NULL);
65         }
66 }
67
68 /*
69   destroy an immediate event
70 */
71 static int tevent_common_immediate_destructor(struct tevent_immediate *im)
72 {
73         if (im->destroyed) {
74                 tevent_common_check_double_free(im,
75                                                 "tevent_immediate double free");
76                 goto done;
77         }
78
79         tevent_common_immediate_cancel(im);
80
81         im->destroyed = true;
82
83 done:
84         if (im->busy) {
85                 return -1;
86         }
87
88         return 0;
89 }
90
91 /*
92  * schedule an immediate event on
93  */
94 void tevent_common_schedule_immediate(struct tevent_immediate *im,
95                                       struct tevent_context *ev,
96                                       tevent_immediate_handler_t handler,
97                                       void *private_data,
98                                       const char *handler_name,
99                                       const char *location)
100 {
101         const char *create_location = im->create_location;
102         bool busy = im->busy;
103         struct tevent_wrapper_glue *glue = im->wrapper;
104
105         tevent_common_immediate_cancel(im);
106
107         if (!handler) {
108                 return;
109         }
110
111         *im = (struct tevent_immediate) {
112                 .event_ctx              = ev,
113                 .wrapper                = glue,
114                 .handler                = handler,
115                 .private_data           = private_data,
116                 .handler_name           = handler_name,
117                 .create_location        = create_location,
118                 .schedule_location      = location,
119                 .busy                   = busy,
120         };
121
122         DLIST_ADD_END(ev->immediate_events, im);
123         talloc_set_destructor(im, tevent_common_immediate_destructor);
124
125         tevent_debug(ev, TEVENT_DEBUG_TRACE,
126                      "Schedule immediate event \"%s\": %p\n",
127                      handler_name, im);
128 }
129
130 int tevent_common_invoke_immediate_handler(struct tevent_immediate *im,
131                                            bool *removed)
132 {
133         struct tevent_context *handler_ev = im->event_ctx;
134         struct tevent_context *ev = im->event_ctx;
135         struct tevent_immediate cur = *im;
136
137         if (removed != NULL) {
138                 *removed = false;
139         }
140
141         tevent_debug(ev, TEVENT_DEBUG_TRACE,
142                      "Run immediate event \"%s\": %p\n",
143                      im->handler_name, im);
144
145         /*
146          * remember the handler and then clear the event
147          * the handler might reschedule the event
148          */
149
150         im->busy = true;
151         im->handler_name = NULL;
152         tevent_common_immediate_cancel(im);
153         if (cur.wrapper != NULL) {
154                 handler_ev = cur.wrapper->wrap_ev;
155
156                 tevent_wrapper_push_use_internal(handler_ev, cur.wrapper);
157                 cur.wrapper->ops->before_immediate_handler(
158                                         cur.wrapper->wrap_ev,
159                                         cur.wrapper->private_state,
160                                         cur.wrapper->main_ev,
161                                         im,
162                                         cur.handler_name,
163                                         cur.schedule_location);
164         }
165         cur.handler(handler_ev, im, cur.private_data);
166         if (cur.wrapper != NULL) {
167                 cur.wrapper->ops->after_immediate_handler(
168                                         cur.wrapper->wrap_ev,
169                                         cur.wrapper->private_state,
170                                         cur.wrapper->main_ev,
171                                         im,
172                                         cur.handler_name,
173                                         cur.schedule_location);
174                 tevent_wrapper_pop_use_internal(handler_ev, cur.wrapper);
175         }
176         im->busy = false;
177
178         if (im->destroyed) {
179                 talloc_set_destructor(im, NULL);
180                 TALLOC_FREE(im);
181                 if (removed != NULL) {
182                         *removed = true;
183                 }
184         }
185
186         return 0;
187 }
188
189 /*
190   trigger the first immediate event and return true
191   if no event was triggered return false
192 */
193 bool tevent_common_loop_immediate(struct tevent_context *ev)
194 {
195         struct tevent_immediate *im = ev->immediate_events;
196         int ret;
197
198         if (!im) {
199                 return false;
200         }
201
202         ret = tevent_common_invoke_immediate_handler(im, NULL);
203         if (ret != 0) {
204                 tevent_abort(ev, "tevent_common_invoke_immediate_handler() failed");
205         }
206
207         return true;
208 }
209