2 Unix SMB/CIFS implementation.
4 common events code for immediate events
6 Copyright (C) Stefan Metzmacher 2009
8 ** NOTE! The following LGPL license applies to the tevent
9 ** library. This does NOT imply that all of Samba is released
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.
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.
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/>.
27 #define TEVENT_DEPRECATED 1
29 #include "tevent_internal.h"
30 #include "tevent_util.h"
32 static void tevent_common_immediate_cancel(struct tevent_immediate
*im
)
34 const char *create_location
= im
->create_location
;
36 uint64_t tag
= im
->tag
;
37 struct tevent_context
*detach_ev_ctx
= NULL
;
40 tevent_abort(im
->event_ctx
, "tevent_immediate use after free");
44 if (im
->detach_ev_ctx
!= NULL
) {
45 detach_ev_ctx
= im
->detach_ev_ctx
;
46 im
->detach_ev_ctx
= NULL
;
47 tevent_trace_immediate_callback(detach_ev_ctx
,
49 TEVENT_EVENT_TRACE_DETACH
);
57 if (im
->handler_name
!= NULL
) {
58 TEVENT_DEBUG(im
->event_ctx
, TEVENT_DEBUG_TRACE
,
59 "Cancel immediate event %p \"%s\"\n",
60 im
, im
->handler_name
);
63 /* let the backend free im->additional_data */
68 if (busy
&& im
->handler_name
== NULL
) {
69 detach_ev_ctx
= im
->event_ctx
;
71 tevent_trace_immediate_callback(im
->event_ctx
,
73 TEVENT_EVENT_TRACE_DETACH
);
75 DLIST_REMOVE(im
->event_ctx
->immediate_events
, im
);
77 *im
= (struct tevent_immediate
) {
78 .create_location
= create_location
,
81 .detach_ev_ctx
= detach_ev_ctx
,
85 talloc_set_destructor(im
, NULL
);
90 destroy an immediate event
92 static int tevent_common_immediate_destructor(struct tevent_immediate
*im
)
95 tevent_common_check_double_free(im
,
96 "tevent_immediate double free");
100 tevent_common_immediate_cancel(im
);
102 im
->destroyed
= true;
113 * schedule an immediate event on
115 void tevent_common_schedule_immediate(struct tevent_immediate
*im
,
116 struct tevent_context
*ev
,
117 tevent_immediate_handler_t handler
,
119 const char *handler_name
,
120 const char *location
)
122 const char *create_location
= im
->create_location
;
123 bool busy
= im
->busy
;
124 uint64_t tag
= im
->tag
;
125 struct tevent_wrapper_glue
*glue
= im
->wrapper
;
127 tevent_common_immediate_cancel(im
);
133 *im
= (struct tevent_immediate
) {
137 .private_data
= private_data
,
138 .handler_name
= handler_name
,
139 .create_location
= create_location
,
140 .schedule_location
= location
,
145 tevent_trace_immediate_callback(im
->event_ctx
, im
, TEVENT_EVENT_TRACE_ATTACH
);
146 DLIST_ADD_END(ev
->immediate_events
, im
);
147 talloc_set_destructor(im
, tevent_common_immediate_destructor
);
149 TEVENT_DEBUG(ev
, TEVENT_DEBUG_TRACE
,
150 "Schedule immediate event \"%s\": %p\n",
154 int tevent_common_invoke_immediate_handler(struct tevent_immediate
*im
,
157 struct tevent_context
*handler_ev
= im
->event_ctx
;
158 struct tevent_context
*ev
= im
->event_ctx
;
159 struct tevent_immediate cur
= *im
;
161 if (removed
!= NULL
) {
165 TEVENT_DEBUG(ev
, TEVENT_DEBUG_TRACE
,
166 "Run immediate event \"%s\": %p\n",
167 im
->handler_name
, im
);
170 * remember the handler and then clear the event
171 * the handler might reschedule the event
175 im
->handler_name
= NULL
;
176 tevent_common_immediate_cancel(im
);
177 if (cur
.wrapper
!= NULL
) {
178 handler_ev
= cur
.wrapper
->wrap_ev
;
180 tevent_wrapper_push_use_internal(handler_ev
, cur
.wrapper
);
181 cur
.wrapper
->ops
->before_immediate_handler(
182 cur
.wrapper
->wrap_ev
,
183 cur
.wrapper
->private_state
,
184 cur
.wrapper
->main_ev
,
187 cur
.schedule_location
);
189 tevent_trace_immediate_callback(cur
.event_ctx
, im
, TEVENT_EVENT_TRACE_BEFORE_HANDLER
);
190 cur
.handler(handler_ev
, im
, cur
.private_data
);
191 if (cur
.wrapper
!= NULL
) {
192 cur
.wrapper
->ops
->after_immediate_handler(
193 cur
.wrapper
->wrap_ev
,
194 cur
.wrapper
->private_state
,
195 cur
.wrapper
->main_ev
,
198 cur
.schedule_location
);
199 tevent_wrapper_pop_use_internal(handler_ev
, cur
.wrapper
);
203 /* The event was removed in tevent_common_immediate_cancel(). */
204 if (im
->detach_ev_ctx
!= NULL
) {
205 struct tevent_context
*detach_ev_ctx
= im
->detach_ev_ctx
;
206 im
->detach_ev_ctx
= NULL
;
207 tevent_trace_immediate_callback(detach_ev_ctx
,
209 TEVENT_EVENT_TRACE_DETACH
);
213 talloc_set_destructor(im
, NULL
);
215 if (removed
!= NULL
) {
224 trigger the first immediate event and return true
225 if no event was triggered return false
227 bool tevent_common_loop_immediate(struct tevent_context
*ev
)
229 struct tevent_immediate
*im
= ev
->immediate_events
;
236 ret
= tevent_common_invoke_immediate_handler(im
, NULL
);
238 tevent_abort(ev
, "tevent_common_invoke_immediate_handler() failed");
245 void tevent_immediate_set_tag(struct tevent_immediate
*im
, uint64_t tag
)
254 uint64_t tevent_immediate_get_tag(const struct tevent_immediate
*im
)