Changeset 745 for trunk/server/lib/tevent
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 14 deleted
- 16 edited
- 14 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/lib/tevent/libtevent.m4
r414 r745 31 31 TEVENT_OBJ="$TEVENT_OBJ tevent_req.o tevent_wakeup.o tevent_queue.o" 32 32 TEVENT_OBJ="$TEVENT_OBJ tevent_standard.o tevent_select.o" 33 TEVENT_OBJ="$TEVENT_OBJ tevent_poll.o" 33 34 34 35 AC_CHECK_HEADERS(sys/epoll.h) -
trunk/server/lib/tevent/testsuite.c
r620 r745 149 149 struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx) 150 150 { 151 struct torture_suite *suite = torture_suite_create(mem_ctx, " EVENT");151 struct torture_suite *suite = torture_suite_create(mem_ctx, "event"); 152 152 const char **list = event_backend_list(suite); 153 153 int i; -
trunk/server/lib/tevent/tevent.c
r429 r745 89 89 } 90 90 91 e = talloc( talloc_autofree_context(), struct tevent_ops_list);91 e = talloc(NULL, struct tevent_ops_list); 92 92 if (e == NULL) return false; 93 93 … … 105 105 { 106 106 talloc_free(tevent_default_backend); 107 tevent_default_backend = talloc_strdup(talloc_autofree_context(), 108 backend); 107 tevent_default_backend = talloc_strdup(NULL, backend); 109 108 } 110 109 … … 115 114 { 116 115 tevent_select_init(); 116 tevent_poll_init(); 117 117 tevent_standard_init(); 118 118 #ifdef HAVE_EPOLL … … 263 263 add a fd based event 264 264 return NULL on failure (memory allocation error) 265 266 if flags contains TEVENT_FD_AUTOCLOSE then the fd will be closed when267 the returned fd_event context is freed268 265 */ 269 266 struct tevent_fd *_tevent_add_fd(struct tevent_context *ev, … … 617 614 return ev->ops->loop_wait(ev, location); 618 615 } 616 617 618 /* 619 re-initialise a tevent context. This leaves you with the same 620 event context, but all events are wiped and the structure is 621 re-initialised. This is most useful after a fork() 622 623 zero is returned on success, non-zero on failure 624 */ 625 int tevent_re_initialise(struct tevent_context *ev) 626 { 627 tevent_common_context_destructor(ev); 628 629 return ev->ops->context_init(ev); 630 } -
trunk/server/lib/tevent/tevent.h
r414 r745 41 41 struct tevent_signal; 42 42 43 /** 44 * @defgroup tevent The tevent API 45 * 46 * The tevent low-level API 47 * 48 * This API provides the public interface to manage events in the tevent 49 * mainloop. Functions are provided for managing low-level events such 50 * as timer events, fd events and signal handling. 51 * 52 * @{ 53 */ 54 43 55 /* event handler types */ 56 /** 57 * Called when a file descriptor monitored by tevent has 58 * data to be read or written on it. 59 */ 44 60 typedef void (*tevent_fd_handler_t)(struct tevent_context *ev, 45 61 struct tevent_fd *fde, 46 62 uint16_t flags, 47 63 void *private_data); 64 65 /** 66 * Called when tevent is ceasing the monitoring of a file descriptor. 67 */ 48 68 typedef void (*tevent_fd_close_fn_t)(struct tevent_context *ev, 49 69 struct tevent_fd *fde, 50 70 int fd, 51 71 void *private_data); 72 73 /** 74 * Called when a tevent timer has fired. 75 */ 52 76 typedef void (*tevent_timer_handler_t)(struct tevent_context *ev, 53 77 struct tevent_timer *te, 54 78 struct timeval current_time, 55 79 void *private_data); 80 81 /** 82 * Called when a tevent immediate event is invoked. 83 */ 56 84 typedef void (*tevent_immediate_handler_t)(struct tevent_context *ctx, 57 85 struct tevent_immediate *im, 58 86 void *private_data); 87 88 /** 89 * Called after tevent detects the specified signal. 90 */ 59 91 typedef void (*tevent_signal_handler_t)(struct tevent_context *ev, 60 92 struct tevent_signal *se, … … 64 96 void *private_data); 65 97 98 /** 99 * @brief Create a event_context structure. 100 * 101 * This must be the first events call, and all subsequent calls pass this 102 * event_context as the first element. Event handlers also receive this as 103 * their first argument. 104 * 105 * @param[in] mem_ctx The memory context to use. 106 * 107 * @return An allocated tevent context, NULL on error. 108 * 109 * @see tevent_context_init() 110 */ 66 111 struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx); 112 113 /** 114 * @brief Create a event_context structure and name it. 115 * 116 * This must be the first events call, and all subsequent calls pass this 117 * event_context as the first element. Event handlers also receive this as 118 * their first argument. 119 * 120 * @param[in] mem_ctx The memory context to use. 121 * 122 * @param[in] name The name for the tevent context. 123 * 124 * @return An allocated tevent context, NULL on error. 125 */ 67 126 struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx, const char *name); 127 128 /** 129 * @brief List available backends. 130 * 131 * @param[in] mem_ctx The memory context to use. 132 * 133 * @return A string vector with a terminating NULL element, NULL 134 * on error. 135 */ 68 136 const char **tevent_backend_list(TALLOC_CTX *mem_ctx); 137 138 /** 139 * @brief Set the default tevent backent. 140 * 141 * @param[in] backend The name of the backend to set. 142 */ 69 143 void tevent_set_default_backend(const char *backend); 70 144 145 #ifdef DOXYGEN 146 /** 147 * @brief Add a file descriptor based event. 148 * 149 * @param[in] ev The event context to work on. 150 * 151 * @param[in] mem_ctx The talloc memory context to use. 152 * 153 * @param[in] fd The file descriptor to base the event on. 154 * 155 * @param[in] flags #TEVENT_FD_READ or #TEVENT_FD_WRITE 156 * 157 * @param[in] handler The callback handler for the event. 158 * 159 * @param[in] private_data The private data passed to the callback handler. 160 * 161 * @return The file descriptor based event, NULL on error. 162 * 163 * @note To cancel the monitoring of a file descriptor, call talloc_free() 164 * on the object returned by this function. 165 */ 166 struct tevent_fd *tevent_add_fd(struct tevent_context *ev, 167 TALLOC_CTX *mem_ctx, 168 int fd, 169 uint16_t flags, 170 tevent_fd_handler_t handler, 171 void *private_data); 172 #else 71 173 struct tevent_fd *_tevent_add_fd(struct tevent_context *ev, 72 174 TALLOC_CTX *mem_ctx, … … 80 182 _tevent_add_fd(ev, mem_ctx, fd, flags, handler, private_data, \ 81 183 #handler, __location__) 82 184 #endif 185 186 #ifdef DOXYGEN 187 /** 188 * @brief Add a timed event 189 * 190 * @param[in] ev The event context to work on. 191 * 192 * @param[in] mem_ctx The talloc memory context to use. 193 * 194 * @param[in] next_event Timeval specifying the absolute time to fire this 195 * event. This is not an offset. 196 * 197 * @param[in] handler The callback handler for the event. 198 * 199 * @param[in] private_data The private data passed to the callback handler. 200 * 201 * @return The newly-created timer event, or NULL on error. 202 * 203 * @note To cancel a timer event before it fires, call talloc_free() on the 204 * event returned from this function. This event is automatically 205 * talloc_free()-ed after its event handler files, if it hasn't been freed yet. 206 * 207 * @note Unlike some mainloops, tevent timers are one-time events. To set up 208 * a recurring event, it is necessary to call tevent_add_timer() again during 209 * the handler processing. 210 * 211 * @note Due to the internal mainloop processing, a timer set to run 212 * immediately will do so after any other pending timers fire, but before 213 * any further file descriptor or signal handling events fire. Callers should 214 * not rely on this behavior! 215 */ 216 struct tevent_timer *tevent_add_timer(struct tevent_context *ev, 217 TALLOC_CTX *mem_ctx, 218 struct timeval next_event, 219 tevent_timer_handler_t handler, 220 void *private_data); 221 #else 83 222 struct tevent_timer *_tevent_add_timer(struct tevent_context *ev, 84 223 TALLOC_CTX *mem_ctx, … … 91 230 _tevent_add_timer(ev, mem_ctx, next_event, handler, private_data, \ 92 231 #handler, __location__) 93 232 #endif 233 234 #ifdef DOXYGEN 235 /** 236 * Initialize an immediate event object 237 * 238 * This object can be used to trigger an event to occur immediately after 239 * returning from the current event (before any other event occurs) 240 * 241 * @param[in] mem_ctx The talloc memory context to use as the parent 242 * 243 * @return An empty tevent_immediate object. Use tevent_schedule_immediate 244 * to populate and use it. 245 * 246 * @note Available as of tevent 0.9.8 247 */ 248 struct tevent_immediate *tevent_create_immediate(TALLOC_CTX *mem_ctx); 249 #else 94 250 struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx, 95 251 const char *location); 96 252 #define tevent_create_immediate(mem_ctx) \ 97 253 _tevent_create_immediate(mem_ctx, __location__) 98 254 #endif 255 256 #ifdef DOXYGEN 257 258 /** 259 * Schedule an event for immediate execution. This event will occur 260 * immediately after returning from the current event (before any other 261 * event occurs) 262 * 263 * @param[in] im The tevent_immediate object to populate and use 264 * @param[in] ctx The tevent_context to run this event 265 * @param[in] handler The event handler to run when this event fires 266 * @param[in] private_data Data to pass to the event handler 267 */ 268 void tevent_schedule_immediate(struct tevent_immediate *im, 269 struct tevent_context *ctx, 270 tevent_immediate_handler_t handler, 271 void *private_data); 272 #else 99 273 void _tevent_schedule_immediate(struct tevent_immediate *im, 100 274 struct tevent_context *ctx, … … 106 280 _tevent_schedule_immediate(im, ctx, handler, private_data, \ 107 281 #handler, __location__); 108 282 #endif 283 284 #ifdef DOXYGEN 285 /** 286 * @brief Add a tevent signal handler 287 * 288 * tevent_add_signal() creates a new event for handling a signal the next 289 * time through the mainloop. It implements a very simple traditional signal 290 * handler whose only purpose is to add the handler event into the mainloop. 291 * 292 * @param[in] ev The event context to work on. 293 * 294 * @param[in] mem_ctx The talloc memory context to use. 295 * 296 * @param[in] signum The signal to trap 297 * 298 * @param[in] handler The callback handler for the signal. 299 * 300 * @param[in] sa_flags sigaction flags for this signal handler. 301 * 302 * @param[in] private_data The private data passed to the callback handler. 303 * 304 * @return The newly-created signal handler event, or NULL on error. 305 * 306 * @note To cancel a signal handler, call talloc_free() on the event returned 307 * from this function. 308 */ 309 struct tevent_signal *tevent_add_signal(struct tevent_context *ev, 310 TALLOC_CTX *mem_ctx, 311 int signum, 312 int sa_flags, 313 tevent_signal_handler_t handler, 314 void *private_data); 315 #else 109 316 struct tevent_signal *_tevent_add_signal(struct tevent_context *ev, 110 317 TALLOC_CTX *mem_ctx, … … 118 325 _tevent_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data, \ 119 326 #handler, __location__) 120 327 #endif 328 329 #ifdef DOXYGEN 330 /** 331 * @brief Pass a single time through the mainloop 332 * 333 * This will process any appropriate signal, immediate, fd and timer events 334 * 335 * @param[in] ev The event context to process 336 * 337 * @return Zero on success, nonzero if an internal error occurred 338 */ 339 int tevent_loop_once(struct tevent_context *ev); 340 #else 121 341 int _tevent_loop_once(struct tevent_context *ev, const char *location); 122 342 #define tevent_loop_once(ev) \ 123 _tevent_loop_once(ev, __location__) \ 124 343 _tevent_loop_once(ev, __location__) 344 #endif 345 346 #ifdef DOXYGEN 347 /** 348 * @brief Run the mainloop 349 * 350 * The mainloop will run until there are no events remaining to be processed 351 * 352 * @param[in] ev The event context to process 353 * 354 * @return Zero if all events have been processed. Nonzero if an internal 355 * error occurred. 356 */ 357 int tevent_loop_wait(struct tevent_context *ev); 358 #else 125 359 int _tevent_loop_wait(struct tevent_context *ev, const char *location); 126 360 #define tevent_loop_wait(ev) \ 127 _tevent_loop_wait(ev, __location__) \ 128 361 _tevent_loop_wait(ev, __location__) 362 #endif 363 364 365 /** 366 * Assign a function to run when a tevent_fd is freed 367 * 368 * This function is a destructor for the tevent_fd. It does not automatically 369 * close the file descriptor. If this is the desired behavior, then it must be 370 * performed by the close_fn. 371 * 372 * @param[in] fde File descriptor event on which to set the destructor 373 * @param[in] close_fn Destructor to execute when fde is freed 374 */ 129 375 void tevent_fd_set_close_fn(struct tevent_fd *fde, 130 376 tevent_fd_close_fn_t close_fn); 377 378 /** 379 * Automatically close the file descriptor when the tevent_fd is freed 380 * 381 * This function calls close(fd) internally. 382 * 383 * @param[in] fde File descriptor event to auto-close 384 */ 131 385 void tevent_fd_set_auto_close(struct tevent_fd *fde); 386 387 /** 388 * Return the flags set on this file descriptor event 389 * 390 * @param[in] fde File descriptor event to query 391 * 392 * @return The flags set on the event. See #TEVENT_FD_READ and 393 * #TEVENT_FD_WRITE 394 */ 132 395 uint16_t tevent_fd_get_flags(struct tevent_fd *fde); 396 397 /** 398 * Set flags on a file descriptor event 399 * 400 * @param[in] fde File descriptor event to set 401 * @param[in] flags Flags to set on the event. See #TEVENT_FD_READ and 402 * #TEVENT_FD_WRITE 403 */ 133 404 void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags); 134 405 406 /** 407 * Query whether tevent supports signal handling 408 * 409 * @param[in] ev An initialized tevent context 410 * 411 * @return True if this platform and tevent context support signal handling 412 */ 135 413 bool tevent_signal_support(struct tevent_context *ev); 136 414 … … 138 416 139 417 /* bits for file descriptor event flags */ 418 419 /** 420 * Monitor a file descriptor for write availability 421 */ 140 422 #define TEVENT_FD_READ 1 423 /** 424 * Monitor a file descriptor for data to be read 425 */ 141 426 #define TEVENT_FD_WRITE 2 142 427 428 /** 429 * Convenience function for declaring a tevent_fd writable 430 */ 143 431 #define TEVENT_FD_WRITEABLE(fde) \ 144 432 tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) | TEVENT_FD_WRITE) 433 434 /** 435 * Convenience function for declaring a tevent_fd readable 436 */ 145 437 #define TEVENT_FD_READABLE(fde) \ 146 438 tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) | TEVENT_FD_READ) 147 439 440 /** 441 * Convenience function for declaring a tevent_fd non-writable 442 */ 148 443 #define TEVENT_FD_NOT_WRITEABLE(fde) \ 149 444 tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) & ~TEVENT_FD_WRITE) 445 446 /** 447 * Convenience function for declaring a tevent_fd non-readable 448 */ 150 449 #define TEVENT_FD_NOT_READABLE(fde) \ 151 450 tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) & ~TEVENT_FD_READ) 152 451 153 /* DEBUG */ 452 /** 453 * Debug level of tevent 454 */ 154 455 enum tevent_debug_level { 155 456 TEVENT_DEBUG_FATAL, … … 159 460 }; 160 461 462 /** 463 * @brief The tevent debug callbac. 464 * 465 * @param[in] context The memory context to use. 466 * 467 * @param[in] level The debug level. 468 * 469 * @param[in] fmt The format string. 470 * 471 * @param[in] ap The arguments for the format string. 472 */ 473 typedef void (*tevent_debug_fn)(void *context, 474 enum tevent_debug_level level, 475 const char *fmt, 476 va_list ap) PRINTF_ATTRIBUTE(3,0); 477 478 /** 479 * Set destination for tevent debug messages 480 * 481 * @param[in] ev Event context to debug 482 * @param[in] debug Function to handle output printing 483 * @param[in] context The context to pass to the debug function. 484 * 485 * @return Always returns 0 as of version 0.9.8 486 * 487 * @note Default is to emit no debug messages 488 */ 161 489 int tevent_set_debug(struct tevent_context *ev, 162 void (*debug)(void *context, 163 enum tevent_debug_level level, 164 const char *fmt, 165 va_list ap) PRINTF_ATTRIBUTE(3,0), 490 tevent_debug_fn debug, 166 491 void *context); 492 493 /** 494 * Designate stderr for debug message output 495 * 496 * @param[in] ev Event context to debug 497 * 498 * @note This function will only output TEVENT_DEBUG_FATAL, TEVENT_DEBUG_ERROR 499 * and TEVENT_DEBUG_WARNING messages. For TEVENT_DEBUG_TRACE, please define a 500 * function for tevent_set_debug() 501 */ 167 502 int tevent_set_debug_stderr(struct tevent_context *ev); 168 503 169 504 /** 170 * An async request moves between the following 4 states: 505 * @} 506 */ 507 508 /** 509 * @defgroup tevent_request The tevent request functions. 510 * @ingroup tevent 511 * 512 * A tevent_req represents an asynchronous computation. 513 * 514 * The tevent_req group of API calls is the recommended way of 515 * programming async computations within tevent. In particular the 516 * file descriptor (tevent_add_fd) and timer (tevent_add_timed) events 517 * are considered too low-level to be used in larger computations. To 518 * read and write from and to sockets, Samba provides two calls on top 519 * of tevent_add_fd: read_packet_send/recv and writev_send/recv. These 520 * requests are much easier to compose than the low-level event 521 * handlers called from tevent_add_fd. 522 * 523 * A lot of the simplicity tevent_req has brought to the notoriously 524 * hairy async programming came via a set of conventions that every 525 * async computation programmed should follow. One central piece of 526 * these conventions is the naming of routines and variables. 527 * 528 * Every async computation needs a name (sensibly called "computation" 529 * down from here). From this name quite a few naming conventions are 530 * derived. 531 * 532 * Every computation that requires local state needs a 533 * @code 534 * struct computation_state { 535 * int local_var; 536 * }; 537 * @endcode 538 * Even if no local variables are required, such a state struct should 539 * be created containing a dummy variable. Quite a few helper 540 * functions and macros (for example tevent_req_create()) assume such 541 * a state struct. 542 * 543 * An async computation is started by a computation_send 544 * function. When it is finished, its result can be received by a 545 * computation_recv function. For an example how to set up an async 546 * computation, see the code example in the documentation for 547 * tevent_req_create() and tevent_req_post(). The prototypes for _send 548 * and _recv functions should follow some conventions: 549 * 550 * @code 551 * struct tevent_req *computation_send(TALLOC_CTX *mem_ctx, 552 * struct tevent_req *ev, 553 * ... further args); 554 * int computation_recv(struct tevent_req *req, ... further output args); 555 * @endcode 556 * 557 * The "int" result of computation_recv() depends on the result the 558 * sync version of the function would have, "int" is just an example 559 * here. 560 * 561 * Another important piece of the conventions is that the program flow 562 * is interrupted as little as possible. Because a blocking 563 * sub-computation requires that the flow needs to continue in a 564 * separate function that is the logical sequel of some computation, 565 * it should lexically follow sending off the blocking 566 * sub-computation. Setting the callback function via 567 * tevent_req_set_callback() requires referencing a function lexically 568 * below the call to tevent_req_set_callback(), forward declarations 569 * are required. A lot of the async computations thus begin with a 570 * sequence of declarations such as 571 * 572 * @code 573 * static void computation_step1_done(struct tevent_req *subreq); 574 * static void computation_step2_done(struct tevent_req *subreq); 575 * static void computation_step3_done(struct tevent_req *subreq); 576 * @endcode 577 * 578 * It really helps readability a lot to do these forward declarations, 579 * because the lexically sequential program flow makes the async 580 * computations almost as clear to read as a normal, sync program 581 * flow. 582 * 583 * It is up to the user of the async computation to talloc_free it 584 * after it has finished. If an async computation should be aborted, 585 * the tevent_req structure can be talloc_free'ed. After it has 586 * finished, it should talloc_free'ed by the API user. 587 * 588 * @{ 589 */ 590 591 /** 592 * An async request moves from TEVENT_REQ_INIT to 593 * TEVENT_REQ_IN_PROGRESS. All other states are valid after a request 594 * has finished. 171 595 */ 172 596 enum tevent_req_state { 173 597 /** 174 * we are creating the request598 * We are creating the request 175 599 */ 176 600 TEVENT_REQ_INIT, 177 601 /** 178 * we are waiting the request to complete602 * We are waiting the request to complete 179 603 */ 180 604 TEVENT_REQ_IN_PROGRESS, 181 605 /** 182 * the request is finished606 * The request is finished successfully 183 607 */ 184 608 TEVENT_REQ_DONE, 185 609 /** 186 * A user error has occured 610 * A user error has occurred. The user error has been 611 * indicated by tevent_req_error(), it can be retrieved via 612 * tevent_req_is_error(). 187 613 */ 188 614 TEVENT_REQ_USER_ERROR, 189 615 /** 190 * Request timed out 616 * Request timed out after the timeout set by tevent_req_set_endtime. 191 617 */ 192 618 TEVENT_REQ_TIMED_OUT, 193 619 /** 194 * No memory in between 620 * An internal allocation has failed, or tevent_req_nomem has 621 * been given a NULL pointer as the first argument. 195 622 */ 196 623 TEVENT_REQ_NO_MEMORY, 197 624 /** 198 * the request is already received by the caller 625 * The request has been received by the caller. No further 626 * action is valid. 199 627 */ 200 628 TEVENT_REQ_RECEIVED … … 203 631 /** 204 632 * @brief An async request 205 * 206 * This represents an async request being processed by callbacks via an event 207 * context. A user can issue for example a write request to a socket, giving 208 * an implementation function the fd, the buffer and the number of bytes to 209 * transfer. The function issuing the request will immediately return without 210 * blocking most likely without having sent anything. The API user then fills 211 * in req->async.fn and req->async.private_data, functions that are called 212 * when the request is finished. 213 * 214 * It is up to the user of the async request to talloc_free it after it has 215 * finished. This can happen while the completion function is called. 216 */ 217 633 */ 218 634 struct tevent_req; 219 635 220 typedef void (*tevent_req_fn)(struct tevent_req *); 221 636 /** 637 * @brief A tevent request callback function. 638 * 639 * @param[in] req The tevent async request which executed this callback. 640 */ 641 typedef void (*tevent_req_fn)(struct tevent_req *req); 642 643 /** 644 * @brief Set an async request callback. 645 * 646 * See the documentation of tevent_req_post() for an example how this 647 * is supposed to be used. 648 * 649 * @param[in] req The async request to set the callback. 650 * 651 * @param[in] fn The callback function to set. 652 * 653 * @param[in] pvt A pointer to private data to pass to the async request 654 * callback. 655 */ 222 656 void tevent_req_set_callback(struct tevent_req *req, tevent_req_fn fn, void *pvt); 657 658 #ifdef DOXYGEN 659 /** 660 * @brief Get the private data cast to the given type for a callback from 661 * a tevent request structure. 662 * 663 * @code 664 * static void computation_done(struct tevent_req *subreq) { 665 * struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); 666 * struct computation_state *state = tevent_req_data(req, struct computation_state); 667 * .... more things, eventually maybe call tevent_req_done(req); 668 * } 669 * @endcode 670 * 671 * @param[in] req The structure to get the callback data from. 672 * 673 * @param[in] type The type of the private callback data to get. 674 * 675 * @return The type casted private data set NULL if not set. 676 */ 677 void *tevent_req_callback_data(struct tevent_req *req, #type); 678 #else 223 679 void *_tevent_req_callback_data(struct tevent_req *req); 224 void *_tevent_req_data(struct tevent_req *req);225 226 680 #define tevent_req_callback_data(_req, _type) \ 227 681 talloc_get_type_abort(_tevent_req_callback_data(_req), _type) 682 #endif 683 684 #ifdef DOXYGEN 685 /** 686 * @brief Get the private data for a callback from a tevent request structure. 687 * 688 * @param[in] req The structure to get the callback data from. 689 * 690 * @param[in] req The structure to get the data from. 691 * 692 * @return The private data or NULL if not set. 693 */ 694 void *tevent_req_callback_data_void(struct tevent_req *req); 695 #else 228 696 #define tevent_req_callback_data_void(_req) \ 229 697 _tevent_req_callback_data(_req) 698 #endif 699 700 #ifdef DOXYGEN 701 /** 702 * @brief Get the private data from a tevent request structure. 703 * 704 * When the tevent_req has been created by tevent_req_create, the 705 * result of tevent_req_data() is the state variable created by 706 * tevent_req_create() as a child of the req. 707 * 708 * @param[in] req The structure to get the private data from. 709 * 710 * @param[in] type The type of the private data 711 * 712 * @return The private data or NULL if not set. 713 */ 714 void *tevent_req_data(struct tevent_req *req, #type); 715 #else 716 void *_tevent_req_data(struct tevent_req *req); 230 717 #define tevent_req_data(_req, _type) \ 231 718 talloc_get_type_abort(_tevent_req_data(_req), _type) 232 233 typedef char *(*tevent_req_print_fn)(struct tevent_req *, TALLOC_CTX *); 234 719 #endif 720 721 /** 722 * @brief The print function which can be set for a tevent async request. 723 * 724 * @param[in] req The tevent async request. 725 * 726 * @param[in] ctx A talloc memory context which can be uses to allocate 727 * memory. 728 * 729 * @return An allocated string buffer to print. 730 * 731 * Example: 732 * @code 733 * static char *my_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) 734 * { 735 * struct my_data *data = tevent_req_data(req, struct my_data); 736 * char *result; 737 * 738 * result = tevent_req_default_print(mem_ctx, req); 739 * if (result == NULL) { 740 * return NULL; 741 * } 742 * 743 * return talloc_asprintf_append_buffer(result, "foo=%d, bar=%d", 744 * data->foo, data->bar); 745 * } 746 * @endcode 747 */ 748 typedef char *(*tevent_req_print_fn)(struct tevent_req *req, TALLOC_CTX *ctx); 749 750 /** 751 * @brief This function sets a print function for the given request. 752 * 753 * This function can be used to setup a print function for the given request. 754 * This will be triggered if the tevent_req_print() function was 755 * called on the given request. 756 * 757 * @param[in] req The request to use. 758 * 759 * @param[in] fn A pointer to the print function 760 * 761 * @note This function should only be used for debugging. 762 */ 235 763 void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn); 236 764 765 /** 766 * @brief The default print function for creating debug messages. 767 * 768 * The function should not be used by users of the async API, 769 * but custom print function can use it and append custom text 770 * to the string. 771 * 772 * @param[in] req The request to be printed. 773 * 774 * @param[in] mem_ctx The memory context for the result. 775 * 776 * @return Text representation of request. 777 * 778 */ 237 779 char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx); 238 780 781 /** 782 * @brief Print an tevent_req structure in debug messages. 783 * 784 * This function should be used by callers of the async API. 785 * 786 * @param[in] mem_ctx The memory context for the result. 787 * 788 * @param[in] req The request to be printed. 789 * 790 * @return Text representation of request. 791 */ 239 792 char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req); 240 793 241 typedef bool (*tevent_req_cancel_fn)(struct tevent_req *); 242 794 /** 795 * @brief A typedef for a cancel function for a tevent request. 796 * 797 * @param[in] req The tevent request calling this function. 798 * 799 * @return True if the request could be canceled, false if not. 800 */ 801 typedef bool (*tevent_req_cancel_fn)(struct tevent_req *req); 802 803 /** 804 * @brief This function sets a cancel function for the given tevent request. 805 * 806 * This function can be used to setup a cancel function for the given request. 807 * This will be triggered if the tevent_req_cancel() function was 808 * called on the given request. 809 * 810 * @param[in] req The request to use. 811 * 812 * @param[in] fn A pointer to the cancel function. 813 */ 243 814 void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn); 244 815 816 #ifdef DOXYGEN 817 /** 818 * @brief Try to cancel the given tevent request. 819 * 820 * This function can be used to cancel the given request. 821 * 822 * It is only possible to cancel a request when the implementation 823 * has registered a cancel function via the tevent_req_set_cancel_fn(). 824 * 825 * @param[in] req The request to use. 826 * 827 * @return This function returns true is the request is cancelable, 828 * othererwise false is returned. 829 * 830 * @note Even if the function returns true, the caller need to wait 831 * for the function to complete normally. 832 * Only the _recv() function of the given request indicates 833 * if the request was really canceled. 834 */ 835 bool tevent_req_cancel(struct tevent_req *req); 836 #else 245 837 bool _tevent_req_cancel(struct tevent_req *req, const char *location); 246 838 #define tevent_req_cancel(req) \ 247 839 _tevent_req_cancel(req, __location__) 248 840 #endif 841 842 #ifdef DOXYGEN 843 /** 844 * @brief Create an async tevent request. 845 * 846 * The new async request will be initialized in state TEVENT_REQ_IN_PROGRESS. 847 * 848 * @code 849 * struct tevent_req *req; 850 * struct computation_state *state; 851 * req = tevent_req_create(mem_ctx, &state, struct computation_state); 852 * @endcode 853 * 854 * Tevent_req_create() creates the state variable as a talloc child of 855 * its result. The state variable should be used as the talloc parent 856 * for all temporary variables that are allocated during the async 857 * computation. This way, when the user of the async computation frees 858 * the request, the state as a talloc child will be free'd along with 859 * all the temporary variables hanging off the state. 860 * 861 * @param[in] mem_ctx The memory context for the result. 862 * @param[in] pstate Pointer to the private request state. 863 * @param[in] type The name of the request. 864 * 865 * @return A new async request. NULL on error. 866 */ 867 struct tevent_req *tevent_req_create(TALLOC_CTX *mem_ctx, 868 void **pstate, #type); 869 #else 249 870 struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, 250 871 void *pstate, … … 256 877 _tevent_req_create((_mem_ctx), (_pstate), sizeof(_type), \ 257 878 #_type, __location__) 258 879 #endif 880 881 /** 882 * @brief Set a timeout for an async request. 883 * 884 * @param[in] req The request to set the timeout for. 885 * 886 * @param[in] ev The event context to use for the timer. 887 * 888 * @param[in] endtime The endtime of the request. 889 * 890 * @return True if succeeded, false if not. 891 */ 259 892 bool tevent_req_set_endtime(struct tevent_req *req, 260 893 struct tevent_context *ev, 261 894 struct timeval endtime); 262 895 896 #ifdef DOXYGEN 897 /** 898 * @brief Call the notify callback of the given tevent request manually. 899 * 900 * @param[in] req The tevent request to call the notify function from. 901 * 902 * @see tevent_req_set_callback() 903 */ 904 void tevent_req_notify_callback(struct tevent_req *req); 905 #else 263 906 void _tevent_req_notify_callback(struct tevent_req *req, const char *location); 264 907 #define tevent_req_notify_callback(req) \ 265 908 _tevent_req_notify_callback(req, __location__) 266 909 #endif 910 911 #ifdef DOXYGEN 912 /** 913 * @brief An async request has successfully finished. 914 * 915 * This function is to be used by implementors of async requests. When a 916 * request is successfully finished, this function calls the user's completion 917 * function. 918 * 919 * @param[in] req The finished request. 920 */ 921 void tevent_req_done(struct tevent_req *req); 922 #else 267 923 void _tevent_req_done(struct tevent_req *req, 268 924 const char *location); 269 925 #define tevent_req_done(req) \ 270 926 _tevent_req_done(req, __location__) 271 927 #endif 928 929 #ifdef DOXYGEN 930 /** 931 * @brief An async request has seen an error. 932 * 933 * This function is to be used by implementors of async requests. When a 934 * request can not successfully completed, the implementation should call this 935 * function with the appropriate status code. 936 * 937 * If error is 0 the function returns false and does nothing more. 938 * 939 * @param[in] req The request with an error. 940 * 941 * @param[in] error The error code. 942 * 943 * @return On success true is returned, false if error is 0. 944 * 945 * @code 946 * int error = first_function(); 947 * if (tevent_req_error(req, error)) { 948 * return; 949 * } 950 * 951 * error = second_function(); 952 * if (tevent_req_error(req, error)) { 953 * return; 954 * } 955 * 956 * tevent_req_done(req); 957 * return; 958 * @endcode 959 */ 960 bool tevent_req_error(struct tevent_req *req, 961 uint64_t error); 962 #else 272 963 bool _tevent_req_error(struct tevent_req *req, 273 964 uint64_t error, … … 275 966 #define tevent_req_error(req, error) \ 276 967 _tevent_req_error(req, error, __location__) 277 968 #endif 969 970 #ifdef DOXYGEN 971 /** 972 * @brief Helper function for nomem check. 973 * 974 * Convenience helper to easily check alloc failure within a callback 975 * implementing the next step of an async request. 976 * 977 * @param[in] p The pointer to be checked. 978 * 979 * @param[in] req The request being processed. 980 * 981 * @code 982 * p = talloc(mem_ctx, bla); 983 * if (tevent_req_nomem(p, req)) { 984 * return; 985 * } 986 * @endcode 987 */ 988 bool tevent_req_nomem(const void *p, 989 struct tevent_req *req); 990 #else 278 991 bool _tevent_req_nomem(const void *p, 279 992 struct tevent_req *req, … … 281 994 #define tevent_req_nomem(p, req) \ 282 995 _tevent_req_nomem(p, req, __location__) 283 996 #endif 997 998 /** 999 * @brief Finish a request before the caller had the change to set the callback. 1000 * 1001 * An implementation of an async request might find that it can either finish 1002 * the request without waiting for an external event, or it can not even start 1003 * the engine. To present the illusion of a callback to the user of the API, 1004 * the implementation can call this helper function which triggers an 1005 * immediate timed event. This way the caller can use the same calling 1006 * conventions, independent of whether the request was actually deferred. 1007 * 1008 * @code 1009 * struct tevent_req *computation_send(TALLOC_CTX *mem_ctx, 1010 * struct tevent_context *ev) 1011 * { 1012 * struct tevent_req *req, *subreq; 1013 * struct computation_state *state; 1014 * req = tevent_req_create(mem_ctx, &state, struct computation_state); 1015 * if (req == NULL) { 1016 * return NULL; 1017 * } 1018 * subreq = subcomputation_send(state, ev); 1019 * if (tevent_req_nomem(subreq, req)) { 1020 * return tevent_req_post(req, ev); 1021 * } 1022 * tevent_req_set_callback(subreq, computation_done, req); 1023 * return req; 1024 * } 1025 * @endcode 1026 * 1027 * @param[in] req The finished request. 1028 * 1029 * @param[in] ev The tevent_context for the timed event. 1030 * 1031 * @return The given request will be returned. 1032 */ 284 1033 struct tevent_req *tevent_req_post(struct tevent_req *req, 285 1034 struct tevent_context *ev); 286 1035 1036 /** 1037 * @brief Check if the given request is still in progress. 1038 * 1039 * It is typically used by sync wrapper functions. 1040 * 1041 * @param[in] req The request to poll. 1042 * 1043 * @return The boolean form of "is in progress". 1044 */ 287 1045 bool tevent_req_is_in_progress(struct tevent_req *req); 288 1046 1047 /** 1048 * @brief Actively poll for the given request to finish. 1049 * 1050 * This function is typically used by sync wrapper functions. 1051 * 1052 * @param[in] req The request to poll. 1053 * 1054 * @param[in] ev The tevent_context to be used. 1055 * 1056 * @return On success true is returned. If a critical error has 1057 * happened in the tevent loop layer false is returned. 1058 * This is not the return value of the given request! 1059 * 1060 * @note This should only be used if the given tevent context was created by the 1061 * caller, to avoid event loop nesting. 1062 * 1063 * @code 1064 * req = tstream_writev_queue_send(mem_ctx, 1065 * ev_ctx, 1066 * tstream, 1067 * send_queue, 1068 * iov, 2); 1069 * ok = tevent_req_poll(req, tctx->ev); 1070 * rc = tstream_writev_queue_recv(req, &sys_errno); 1071 * TALLOC_FREE(req); 1072 * @endcode 1073 */ 289 1074 bool tevent_req_poll(struct tevent_req *req, 290 1075 struct tevent_context *ev); 291 1076 1077 /** 1078 * @brief Get the tevent request state and the actual error set by 1079 * tevent_req_error. 1080 * 1081 * @code 1082 * int computation_recv(struct tevent_req *req, uint64_t *perr) 1083 * { 1084 * enum tevent_req_state state; 1085 * uint64_t err; 1086 * if (tevent_req_is_error(req, &state, &err)) { 1087 * *perr = err; 1088 * return -1; 1089 * } 1090 * return 0; 1091 * } 1092 * @endcode 1093 * 1094 * @param[in] req The tevent request to get the error from. 1095 * 1096 * @param[out] state A pointer to store the tevent request error state. 1097 * 1098 * @param[out] error A pointer to store the error set by tevent_req_error(). 1099 * 1100 * @return True if the function could set error and state, false 1101 * otherwise. 1102 * 1103 * @see tevent_req_error() 1104 */ 292 1105 bool tevent_req_is_error(struct tevent_req *req, 293 1106 enum tevent_req_state *state, 294 1107 uint64_t *error); 295 1108 1109 /** 1110 * @brief Use as the last action of a _recv() function. 1111 * 1112 * This function destroys the attached private data. 1113 * 1114 * @param[in] req The finished request. 1115 */ 296 1116 void tevent_req_received(struct tevent_req *req); 297 1117 1118 /** 1119 * @brief Create a tevent subrequest at a given time. 1120 * 1121 * The idea is that always the same syntax for tevent requests. 1122 * 1123 * @param[in] mem_ctx The talloc memory context to use. 1124 * 1125 * @param[in] ev The event handle to setup the request. 1126 * 1127 * @param[in] wakeup_time The time to wakeup and execute the request. 1128 * 1129 * @return The new subrequest, NULL on error. 1130 * 1131 * Example: 1132 * @code 1133 * static void my_callback_wakeup_done(tevent_req *subreq) 1134 * { 1135 * struct tevent_req *req = tevent_req_callback_data(subreq, 1136 * struct tevent_req); 1137 * bool ok; 1138 * 1139 * ok = tevent_wakeup_recv(subreq); 1140 * TALLOC_FREE(subreq); 1141 * if (!ok) { 1142 * tevent_req_error(req, -1); 1143 * return; 1144 * } 1145 * ... 1146 * } 1147 * @endcode 1148 * 1149 * @code 1150 * subreq = tevent_wakeup_send(mem_ctx, ev, wakeup_time); 1151 * if (tevent_req_nomem(subreq, req)) { 1152 * return false; 1153 * } 1154 * tevent_set_callback(subreq, my_callback_wakeup_done, req); 1155 * @endcode 1156 * 1157 * @see tevent_wakeup_recv() 1158 */ 298 1159 struct tevent_req *tevent_wakeup_send(TALLOC_CTX *mem_ctx, 299 1160 struct tevent_context *ev, 300 1161 struct timeval wakeup_time); 1162 1163 /** 1164 * @brief Check if the wakeup has been correctly executed. 1165 * 1166 * This function needs to be called in the callback function set after calling 1167 * tevent_wakeup_send(). 1168 * 1169 * @param[in] req The tevent request to check. 1170 * 1171 * @return True on success, false otherwise. 1172 * 1173 * @see tevent_wakeup_recv() 1174 */ 301 1175 bool tevent_wakeup_recv(struct tevent_req *req); 302 1176 1177 /* @} */ 1178 1179 /** 1180 * @defgroup tevent_helpers The tevent helper functiions 1181 * @ingroup tevent 1182 * 1183 * @todo description 1184 * 1185 * @{ 1186 */ 1187 1188 /** 1189 * @brief Compare two timeval values. 1190 * 1191 * @param[in] tv1 The first timeval value to compare. 1192 * 1193 * @param[in] tv2 The second timeval value to compare. 1194 * 1195 * @return 0 if they are equal. 1196 * 1 if the first time is greater than the second. 1197 * -1 if the first time is smaller than the second. 1198 */ 303 1199 int tevent_timeval_compare(const struct timeval *tv1, 304 1200 const struct timeval *tv2); 305 1201 1202 /** 1203 * @brief Get a zero timval value. 1204 * 1205 * @return A zero timval value. 1206 */ 306 1207 struct timeval tevent_timeval_zero(void); 307 1208 1209 /** 1210 * @brief Get a timeval value for the current time. 1211 * 1212 * @return A timval value with the current time. 1213 */ 308 1214 struct timeval tevent_timeval_current(void); 309 1215 1216 /** 1217 * @brief Get a timeval structure with the given values. 1218 * 1219 * @param[in] secs The seconds to set. 1220 * 1221 * @param[in] usecs The milliseconds to set. 1222 * 1223 * @return A timeval structure with the given values. 1224 */ 310 1225 struct timeval tevent_timeval_set(uint32_t secs, uint32_t usecs); 311 1226 1227 /** 1228 * @brief Get the difference between two timeval values. 1229 * 1230 * @param[in] tv1 The first timeval. 1231 * 1232 * @param[in] tv2 The second timeval. 1233 * 1234 * @return A timeval structure with the difference between the 1235 * first and the second value. 1236 */ 312 1237 struct timeval tevent_timeval_until(const struct timeval *tv1, 313 1238 const struct timeval *tv2); 314 1239 1240 /** 1241 * @brief Check if a given timeval structure is zero. 1242 * 1243 * @param[in] tv The timeval to check if it is zero. 1244 * 1245 * @return True if it is zero, false otherwise. 1246 */ 315 1247 bool tevent_timeval_is_zero(const struct timeval *tv); 316 1248 1249 /** 1250 * @brief Add the given amount of time to a timeval structure. 1251 * 1252 * @param[in] tv The timeval structure to add the time. 1253 * 1254 * @param[in] secs The seconds to add to the timeval. 1255 * 1256 * @param[in] usecs The milliseconds to add to the timeval. 1257 * 1258 * @return The timeval structure with the new time. 1259 */ 317 1260 struct timeval tevent_timeval_add(const struct timeval *tv, uint32_t secs, 318 1261 uint32_t usecs); 319 1262 1263 /** 1264 * @brief Get a timeval in the future with a specified offset from now. 1265 * 1266 * @param[in] secs The seconds of the offset from now. 1267 * 1268 * @param[in] usecs The milliseconds of the offset from now. 1269 * 1270 * @return A timval with the given offset in the future. 1271 */ 320 1272 struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs); 321 1273 1274 /* @} */ 1275 1276 1277 /** 1278 * @defgroup tevent_queue The tevent queue functions 1279 * @ingroup tevent 1280 * 1281 * A tevent_queue is used to queue up async requests that must be 1282 * serialized. For example writing buffers into a socket must be 1283 * serialized. Writing a large lump of data into a socket can require 1284 * multiple write(2) or send(2) system calls. If more than one async 1285 * request is outstanding to write large buffers into a socket, every 1286 * request must individually be completed before the next one begins, 1287 * even if multiple syscalls are required. 1288 * 1289 * Take a look at @ref tevent_queue_tutorial for more details. 1290 * @{ 1291 */ 1292 322 1293 struct tevent_queue; 323 1294 1295 #ifdef DOXYGEN 1296 /** 1297 * @brief Create and start a tevent queue. 1298 * 1299 * @param[in] mem_ctx The talloc memory context to allocate the queue. 1300 * 1301 * @param[in] name The name to use to identify the queue. 1302 * 1303 * @return An allocated tevent queue on success, NULL on error. 1304 * 1305 * @see tevent_start() 1306 * @see tevent_stop() 1307 */ 1308 struct tevent_queue *tevent_queue_create(TALLOC_CTX *mem_ctx, 1309 const char *name); 1310 #else 324 1311 struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx, 325 1312 const char *name, … … 328 1315 #define tevent_queue_create(_mem_ctx, _name) \ 329 1316 _tevent_queue_create((_mem_ctx), (_name), __location__) 330 1317 #endif 1318 1319 /** 1320 * @brief A callback trigger function run by the queue. 1321 * 1322 * @param[in] req The tevent request the trigger function is executed on. 1323 * 1324 * @param[in] private_data The private data pointer specified by 1325 * tevent_queue_add(). 1326 * 1327 * @see tevent_queue_add() 1328 */ 331 1329 typedef void (*tevent_queue_trigger_fn_t)(struct tevent_req *req, 332 1330 void *private_data); 1331 1332 /** 1333 * @brief Add a tevent request to the queue. 1334 * 1335 * @param[in] queue The queue to add the request. 1336 * 1337 * @param[in] ev The event handle to use for the request. 1338 * 1339 * @param[in] req The tevent request to add to the queue. 1340 * 1341 * @param[in] trigger The function triggered by the queue when the request 1342 * is called. 1343 * 1344 * @param[in] private_data The private data passed to the trigger function. 1345 * 1346 * @return True if the request has been successfully added, false 1347 * otherwise. 1348 */ 333 1349 bool tevent_queue_add(struct tevent_queue *queue, 334 1350 struct tevent_context *ev, … … 336 1352 tevent_queue_trigger_fn_t trigger, 337 1353 void *private_data); 1354 1355 /** 1356 * @brief Start a tevent queue. 1357 * 1358 * The queue is started by default. 1359 * 1360 * @param[in] queue The queue to start. 1361 */ 338 1362 void tevent_queue_start(struct tevent_queue *queue); 1363 1364 /** 1365 * @brief Stop a tevent queue. 1366 * 1367 * The queue is started by default. 1368 * 1369 * @param[in] queue The queue to stop. 1370 */ 339 1371 void tevent_queue_stop(struct tevent_queue *queue); 340 1372 1373 /** 1374 * @brief Get the length of the queue. 1375 * 1376 * @param[in] queue The queue to get the length from. 1377 * 1378 * @return The number of elements. 1379 */ 341 1380 size_t tevent_queue_length(struct tevent_queue *queue); 342 1381 … … 367 1406 #endif 368 1407 369 370 /** 1408 int tevent_re_initialise(struct tevent_context *ev); 1409 1410 /* @} */ 1411 1412 /** 1413 * @defgroup tevent_ops The tevent operation functions 1414 * @ingroup tevent 1415 * 371 1416 * The following structure and registration functions are exclusively 372 1417 * needed for people writing and pluggin a different event engine. 373 1418 * There is nothing useful for normal tevent user in here. 1419 * @{ 374 1420 */ 375 1421 … … 424 1470 bool tevent_register_backend(const char *name, const struct tevent_ops *ops); 425 1471 426 427 /** 1472 /* @} */ 1473 1474 /** 1475 * @defgroup tevent_compat The tevent compatibility functions 1476 * @ingroup tevent 1477 * 428 1478 * The following definitions are usueful only for compatibility with the 429 1479 * implementation originally developed within the samba4 code and will be 430 1480 * soon removed. Please NEVER use in new code. 1481 * 1482 * @todo Ignore it? 1483 * 1484 * @{ 431 1485 */ 432 1486 … … 505 1559 #endif /* TEVENT_COMPAT_DEFINES */ 506 1560 1561 /* @} */ 1562 507 1563 #endif /* __TEVENT_H__ */ -
trunk/server/lib/tevent/tevent.pc.in
r414 r745 9 9 Requires: talloc 10 10 Libs: -L${libdir} -ltevent 11 Cflags: -I${includedir}11 Cflags: @LIB_RPATH@ -I${includedir} 12 12 URL: http://samba.org/ -
trunk/server/lib/tevent/tevent_epoll.c
r414 r745 43 43 44 44 /* 45 called when a epoll call fails, and we should fallback 46 to using select 45 called when a epoll call fails 47 46 */ 48 47 static void epoll_panic(struct epoll_event_context *epoll_ev, const char *reason) … … 438 437 }; 439 438 440 bool tevent_epoll_init(void)439 _PRIVATE_ bool tevent_epoll_init(void) 441 440 { 442 441 return tevent_register_backend("epoll", &epoll_event_ops); -
trunk/server/lib/tevent/tevent_fd.c
r414 r745 52 52 struct tevent_fd *fde; 53 53 54 /* tevent will crash later on select() if we save 55 * a negative file descriptor. Better to fail here 56 * so that consumers will be able to debug it 57 */ 58 if (fd < 0) return NULL; 59 54 60 fde = talloc(mem_ctx?mem_ctx:ev, struct tevent_fd); 55 61 if (!fde) return NULL; -
trunk/server/lib/tevent/tevent_internal.h
r429 r745 163 163 const char *location; 164 164 /* this is private for the events_ops implementation */ 165 uint 16_t additional_flags;165 uint64_t additional_flags; 166 166 void *additional_data; 167 167 }; … … 304 304 bool tevent_standard_init(void); 305 305 bool tevent_select_init(void); 306 bool tevent_poll_init(void); 306 307 #ifdef HAVE_EPOLL 307 308 bool tevent_epoll_init(void); -
trunk/server/lib/tevent/tevent_liboop.c
r414 r745 32 32 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 33 33 34 NOTE: this code compiles fine, but is complet ly *UNTESTED*35 and is only commit ed asexample34 NOTE: this code compiles fine, but is completely *UNTESTED* 35 and is only committed as an example 36 36 37 37 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -
trunk/server/lib/tevent/tevent_req.c
r414 r745 27 27 #include "tevent_internal.h" 28 28 #include "tevent_util.h" 29 30 /**31 * @brief The default print function for creating debug messages32 * @param[in] req The request to be printed33 * @param[in] mem_ctx The memory context for the result34 * @retval Text representation of req35 *36 * The function should not be used by users of the asynx API,37 * but custom print function can use it and append custom text38 * to the string.39 */40 29 41 30 char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) … … 54 43 } 55 44 56 /**57 * @brief Print an tevent_req structure in debug messages58 * @param[in] mem_ctx The memory context for the result59 * @param[in] req The request to be printed60 * @retval Text representation of req61 *62 * This function should be used by callers of the async API63 */64 65 45 char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) 66 46 { … … 71 51 return req->private_print(req, mem_ctx); 72 52 } 73 74 /**75 * @brief Create an async request76 * @param[in] mem_ctx The memory context for the result77 * @param[in] ev The event context this async request will be driven by78 * @retval A new async request79 *80 * The new async request will be initialized in state ASYNC_REQ_IN_PROGRESS81 */82 53 83 54 struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, … … 134 105 } 135 106 136 /**137 * @brief An async request has successfully finished138 * @param[in] req The finished request139 *140 * tevent_req_done is to be used by implementors of async requests. When a141 * request is successfully finished, this function calls the user's completion142 * function.143 */144 145 107 void _tevent_req_done(struct tevent_req *req, 146 108 const char *location) … … 148 110 tevent_req_finish(req, TEVENT_REQ_DONE, location); 149 111 } 150 151 /**152 * @brief An async request has seen an error153 * @param[in] req The request with an error154 * @param[in] error The error code155 *156 * tevent_req_done is to be used by implementors of async requests. When a157 * request can not successfully completed, the implementation should call this158 * function with the appropriate status code.159 *160 * If error is 0 the function returns false and does nothing more.161 *162 * Call pattern would be163 * \code164 * int error = first_function();165 * if (tevent_req_error(req, error)) {166 * return;167 * }168 *169 * error = second_function();170 * if (tevent_req_error(req, error)) {171 * return;172 * }173 *174 * tevent_req_done(req);175 * return;176 * \endcode177 */178 112 179 113 bool _tevent_req_error(struct tevent_req *req, … … 190 124 } 191 125 192 /**193 * @brief Helper function for nomem check194 * @param[in] p The pointer to be checked195 * @param[in] req The request being processed196 *197 * Convenience helper to easily check alloc failure within a callback198 * implementing the next step of an async request.199 *200 * Call pattern would be201 * \code202 * p = talloc(mem_ctx, bla);203 * if (tevent_req_nomem(p, req)) {204 * return;205 * }206 * \endcode207 */208 209 126 bool _tevent_req_nomem(const void *p, 210 127 struct tevent_req *req, … … 219 136 220 137 /** 221 * @brief Immediate event callback 222 * @param[in] ev Event context 223 * @param[in] im The immediate event 224 * @param[in] priv The async request to be finished 138 * @internal 139 * 140 * @brief Immediate event callback. 141 * 142 * @param[in] ev The event context to use. 143 * 144 * @param[in] im The immediate event. 145 * 146 * @param[in] priv The async request to be finished. 225 147 */ 226 148 static void tevent_req_trigger(struct tevent_context *ev, … … 235 157 } 236 158 237 /**238 * @brief Finish a request before the caller had the change to set the callback239 * @param[in] req The finished request240 * @param[in] ev The tevent_context for the timed event241 * @retval req will be returned242 *243 * An implementation of an async request might find that it can either finish244 * the request without waiting for an external event, or it can't even start245 * the engine. To present the illusion of a callback to the user of the API,246 * the implementation can call this helper function which triggers an247 * immediate timed event. This way the caller can use the same calling248 * conventions, independent of whether the request was actually deferred.249 */250 251 159 struct tevent_req *tevent_req_post(struct tevent_req *req, 252 160 struct tevent_context *ev) … … 257 165 } 258 166 259 /**260 * @brief This function destroys the attached private data261 * @param[in] req The request to poll262 * @retval The boolean form of "is in progress".263 *264 * This function can be used to ask if the given request265 * is still in progress.266 *267 * This function is typically used by sync wrapper functions.268 */269 167 bool tevent_req_is_in_progress(struct tevent_req *req) 270 168 { … … 276 174 } 277 175 278 /**279 * @brief This function destroys the attached private data280 * @param[in] req The finished request281 *282 * This function can be called as last action of a _recv()283 * function, it destroys the data attached to the tevent_req.284 */285 176 void tevent_req_received(struct tevent_req *req) 286 177 { … … 294 185 } 295 186 296 /**297 * @brief This function destroys the attached private data298 * @param[in] req The request to poll299 * @param[in] ev The tevent_context to be used300 * @retval If a critical error has happened in the301 * tevent loop layer false is returned.302 * Otherwise true is returned.303 * This is not the return value of the given request!304 *305 * This function can be used to actively poll for the306 * given request to finish.307 *308 * Note: this should only be used if the given tevent context309 * was created by the caller, to avoid event loop nesting.310 *311 * This function is typically used by sync wrapper functions.312 */313 187 bool tevent_req_poll(struct tevent_req *req, 314 188 struct tevent_context *ev) … … 384 258 } 385 259 386 /**387 * @brief This function sets a print function for the given request388 * @param[in] req The given request389 * @param[in] fn A pointer to the print function390 *391 * This function can be used to setup a print function for the given request.392 * This will be triggered if the tevent_req_print() function was393 * called on the given request.394 *395 * Note: this function should only be used for debugging.396 */397 260 void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn) 398 261 { … … 400 263 } 401 264 402 /**403 * @brief This function sets a cancel function for the given request404 * @param[in] req The given request405 * @param[in] fn A pointer to the cancel function406 *407 * This function can be used to setup a cancel function for the given request.408 * This will be triggered if the tevent_req_cancel() function was409 * called on the given request.410 *411 */412 265 void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn) 413 266 { … … 415 268 } 416 269 417 /**418 * @brief This function tries to cancel the given request419 * @param[in] req The given request420 * @param[in] location Automaticly filled with the __location__ macro421 * via the tevent_req_cancel() macro. This is for debugging422 * only!423 * @retval This function returns true is the request is cancelable.424 * Otherwise false is returned.425 *426 * This function can be used to cancel the given request.427 *428 * It is only possible to cancel a request when the implementation429 * has registered a cancel function via the tevent_req_set_cancel_fn().430 *431 * Note: Even if the function returns true, the caller need to wait432 * for the function to complete normally.433 * Only the _recv() function of the given request indicates434 * if the request was really canceled.435 */436 270 bool _tevent_req_cancel(struct tevent_req *req, const char *location) 437 271 { -
trunk/server/lib/tevent/tevent_select.c
r593 r745 122 122 if (!fde) return NULL; 123 123 124 if (fde->fd > select_ev->maxfd) { 124 if ((select_ev->maxfd != EVENT_INVALID_MAXFD) 125 && (fde->fd > select_ev->maxfd)) { 125 126 select_ev->maxfd = fde->fd; 126 127 } … … 252 253 }; 253 254 254 bool tevent_select_init(void)255 _PRIVATE_ bool tevent_select_init(void) 255 256 { 256 257 return tevent_register_backend("select", &select_event_ops); -
trunk/server/lib/tevent/tevent_signal.c
r664 r745 214 214 multiple event contexts */ 215 215 if (sig_state == NULL) { 216 sig_state = talloc_zero( talloc_autofree_context(), struct tevent_sig_state);216 sig_state = talloc_zero(NULL, struct tevent_sig_state); 217 217 if (sig_state == NULL) { 218 218 return NULL; -
trunk/server/lib/tevent/tevent_standard.c
r593 r745 462 462 return -1; 463 463 } 464 465 464 if (fde->flags & TEVENT_FD_READ) { 466 465 FD_SET(fde->fd, &r_fds); … … 511 510 if (FD_ISSET(fde->fd, &r_fds)) flags |= TEVENT_FD_READ; 512 511 if (FD_ISSET(fde->fd, &w_fds)) flags |= TEVENT_FD_WRITE; 513 if (flags ) {512 if (flags & fde->flags) { 514 513 fde->handler(std_ev->ev, fde, flags, fde->private_data); 515 514 break; … … 568 567 569 568 570 bool tevent_standard_init(void)569 _PRIVATE_ bool tevent_standard_init(void) 571 570 { 572 571 return tevent_register_backend("standard", &std_event_ops); -
trunk/server/lib/tevent/tevent_timed.c
r414 r745 198 198 do a single event loop using the events defined in ev 199 199 200 return the delay until lthe next timed event,200 return the delay until the next timed event, 201 201 or zero if a timed event was triggered 202 202 */ … … 209 209 /* have a default tick time of 30 seconds. This guarantees 210 210 that code that uses its own timeout checking will be 211 able to procee ed eventually */211 able to proceed eventually */ 212 212 return tevent_timeval_set(30, 0); 213 213 } -
trunk/server/lib/tevent/tevent_util.h
r414 r745 2 2 Unix SMB/CIFS implementation. 3 3 4 Copyright (C) Andrew Tridgell 1998-20 054 Copyright (C) Andrew Tridgell 1998-2010 5 5 Copyright (C) Jelmer Vernooij 2005 6 6 … … 25 25 #define _DLINKLIST_H 26 26 27 /* 28 February 2010 - changed list format to have a prev pointer from the 29 list head. This makes DLIST_ADD_END() O(1) even though we only have 30 one list pointer. 27 31 28 /* hook into the front of the list */ 32 The scheme is as follows: 33 34 1) with no entries in the list: 35 list_head == NULL 36 37 2) with 1 entry in the list: 38 list_head->next == NULL 39 list_head->prev == list_head 40 41 3) with 2 entries in the list: 42 list_head->next == element2 43 list_head->prev == element2 44 element2->prev == list_head 45 element2->next == NULL 46 47 4) with N entries in the list: 48 list_head->next == element2 49 list_head->prev == elementN 50 elementN->prev == element{N-1} 51 elementN->next == NULL 52 53 This allows us to find the tail of the list by using 54 list_head->prev, which means we can add to the end of the list in 55 O(1) time 56 57 58 Note that the 'type' arguments below are no longer needed, but 59 are kept for now to prevent an incompatible argument change 60 */ 61 62 63 /* 64 add an element at the front of a list 65 */ 29 66 #define DLIST_ADD(list, p) \ 30 67 do { \ 31 68 if (!(list)) { \ 32 ( list) = (p);\33 (p)->next = (p)->prev =NULL; \69 (p)->prev = (list) = (p); \ 70 (p)->next = NULL; \ 34 71 } else { \ 72 (p)->prev = (list)->prev; \ 35 73 (list)->prev = (p); \ 36 74 (p)->next = (list); \ 37 (p)->prev = NULL; \38 75 (list) = (p); \ 39 } \76 } \ 40 77 } while (0) 41 78 42 /* remove an element from a list - element doesn't have to be in list. */ 79 /* 80 remove an element from a list 81 Note that the element doesn't have to be in the list. If it 82 isn't then this is a no-op 83 */ 43 84 #define DLIST_REMOVE(list, p) \ 44 85 do { \ 45 86 if ((p) == (list)) { \ 87 if ((p)->next) (p)->next->prev = (p)->prev; \ 46 88 (list) = (p)->next; \ 47 if (list) (list)->prev = NULL; \ 89 } else if ((list) && (p) == (list)->prev) { \ 90 (p)->prev->next = NULL; \ 91 (list)->prev = (p)->prev; \ 48 92 } else { \ 49 93 if ((p)->prev) (p)->prev->next = (p)->next; \ 50 94 if ((p)->next) (p)->next->prev = (p)->prev; \ 51 95 } \ 52 if ((p) != (list)) (p)->next = (p)->prev = NULL; 96 if ((p) != (list)) (p)->next = (p)->prev = NULL; \ 53 97 } while (0) 54 98 55 /* promote an element to the top of the list */ 56 #define DLIST_PROMOTE(list, p) \ 99 /* 100 find the head of the list given any element in it. 101 Note that this costs O(N), so you should avoid this macro 102 if at all possible! 103 */ 104 #define DLIST_HEAD(p, result_head) \ 57 105 do { \ 58 DLIST_REMOVE(list,p); \59 DLIST_ADD(list, p); \60 } while 106 (result_head) = (p); \ 107 while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \ 108 } while(0) 61 109 62 /* hook into the end of the list - needs a tmp pointer */ 63 #define DLIST_ADD_END(list, p, type) \ 64 do { \ 65 if (!(list)) { \ 66 (list) = (p); \ 67 (p)->next = (p)->prev = NULL; \ 68 } else { \ 69 type tmp; \ 70 for (tmp = (list); tmp->next; tmp = tmp->next) ; \ 71 tmp->next = (p); \ 72 (p)->next = NULL; \ 73 (p)->prev = tmp; \ 74 } \ 75 } while (0) 110 /* return the last element in the list */ 111 #define DLIST_TAIL(list) ((list)?(list)->prev:NULL) 112 113 /* return the previous element in the list. */ 114 #define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL) 76 115 77 116 /* insert 'p' after the given element 'el' in a list. If el is NULL then … … 82 121 DLIST_ADD(list, p); \ 83 122 } else { \ 84 p->prev = el; \ 85 p->next = el->next; \ 86 el->next = p; \ 87 if (p->next) p->next->prev = p; \ 123 (p)->prev = (el); \ 124 (p)->next = (el)->next; \ 125 (el)->next = (p); \ 126 if ((p)->next) (p)->next->prev = (p); \ 127 if ((list)->prev == (el)) (list)->prev = (p); \ 88 128 }\ 89 129 } while (0) 90 130 91 /* demote an element to the end of the list, needs a tmp pointer */ 92 #define DLIST_DEMOTE(list, p, tmp) \ 131 132 /* 133 add to the end of a list. 134 Note that 'type' is ignored 135 */ 136 #define DLIST_ADD_END(list, p, type) \ 93 137 do { \ 94 DLIST_REMOVE(list, p); \ 95 DLIST_ADD_END(list, p, tmp); \ 138 if (!(list)) { \ 139 DLIST_ADD(list, p); \ 140 } else { \ 141 DLIST_ADD_AFTER(list, p, (list)->prev); \ 142 } \ 96 143 } while (0) 97 144 98 /* concatenate two lists - putting all elements of the 2nd list at the 99 end of the first list */ 100 #define DLIST_CONCATENATE(list1, list2, type) \ 145 /* promote an element to the from of a list */ 146 #define DLIST_PROMOTE(list, p) \ 101 147 do { \ 102 if (!(list1)) { \ 103 (list1) = (list2); \ 104 } else { \ 105 type tmp; \ 106 for (tmp = (list1); tmp->next; tmp = tmp->next) ; \ 107 tmp->next = (list2); \ 108 if (list2) { \ 109 (list2)->prev = tmp; \ 110 } \ 148 DLIST_REMOVE(list, p); \ 149 DLIST_ADD(list, p); \ 150 } while (0) 151 152 /* 153 demote an element to the end of a list. 154 Note that 'type' is ignored 155 */ 156 #define DLIST_DEMOTE(list, p, type) \ 157 do { \ 158 DLIST_REMOVE(list, p); \ 159 DLIST_ADD_END(list, p, NULL); \ 160 } while (0) 161 162 /* 163 concatenate two lists - putting all elements of the 2nd list at the 164 end of the first list. 165 Note that 'type' is ignored 166 */ 167 #define DLIST_CONCATENATE(list1, list2, type) \ 168 do { \ 169 if (!(list1)) { \ 170 (list1) = (list2); \ 171 } else { \ 172 (list1)->prev->next = (list2); \ 173 if (list2) { \ 174 void *_tmplist = (void *)(list1)->prev; \ 175 (list1)->prev = (list2)->prev; \ 176 (list2)->prev = _tmplist; \ 111 177 } \ 178 } \ 112 179 } while (0) 113 180
Note:
See TracChangeset
for help on using the changeset viewer.