* Retrieves the next available socket from the queue. If there are no * sockets available, it will block until one becomes available. * Once retrieved, the socket is placed into the address specified by * 'sd'. */
| 430 | * 'sd'. |
| 431 | */ |
| 432 | apr_status_t ap_queue_pop_something(fd_queue_t *queue, |
| 433 | apr_socket_t **sd, void **sd_baton, |
| 434 | apr_pool_t **p, timer_event_t **te_out) |
| 435 | { |
| 436 | fd_queue_elem_t *elem; |
| 437 | timer_event_t *te; |
| 438 | apr_status_t rv; |
| 439 | |
| 440 | if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) { |
| 441 | return rv; |
| 442 | } |
| 443 | |
| 444 | /* Keep waiting until we wake up and find that the queue is not empty. */ |
| 445 | if (ap_queue_empty(queue)) { |
| 446 | if (!queue->terminated) { |
| 447 | apr_thread_cond_wait(queue->not_empty, queue->one_big_mutex); |
| 448 | } |
| 449 | /* If we wake up and it's still empty, then we were interrupted */ |
| 450 | if (ap_queue_empty(queue)) { |
| 451 | rv = apr_thread_mutex_unlock(queue->one_big_mutex); |
| 452 | if (rv != APR_SUCCESS) { |
| 453 | return rv; |
| 454 | } |
| 455 | if (queue->terminated) { |
| 456 | return APR_EOF; /* no more elements ever again */ |
| 457 | } |
| 458 | else { |
| 459 | return APR_EINTR; |
| 460 | } |
| 461 | } |
| 462 | } |
| 463 | |
| 464 | te = NULL; |
| 465 | if (te_out) { |
| 466 | if (!APR_RING_EMPTY(&queue->timers, timer_event_t, link)) { |
| 467 | te = APR_RING_FIRST(&queue->timers); |
| 468 | APR_RING_REMOVE(te, link); |
| 469 | } |
| 470 | *te_out = te; |
| 471 | } |
| 472 | if (!te) { |
| 473 | elem = &queue->data[queue->out++]; |
| 474 | if (queue->out >= queue->bounds) |
| 475 | queue->out -= queue->bounds; |
| 476 | queue->nelts--; |
| 477 | |
| 478 | *sd = elem->sd; |
| 479 | if (sd_baton) { |
| 480 | *sd_baton = elem->sd_baton; |
| 481 | } |
| 482 | *p = elem->p; |
| 483 | #ifdef AP_DEBUG |
| 484 | elem->sd = NULL; |
| 485 | elem->p = NULL; |
| 486 | #endif /* AP_DEBUG */ |
| 487 | } |
| 488 | |
| 489 | return apr_thread_mutex_unlock(queue->one_big_mutex); |