void copy_from_disk_queue_to_memory_queue(auto_drainer_t::lock_t keepalive) { try { while (!keepalive.get_drain_signal()->is_pulsed()) { if (disk_queue->empty()) { if (items_in_queue != memory_queue.size()) { // There is a push in progress, there's no good way to wait on it, so we'll start a new coroutine later restart_copy_coro = true; } else { disk_queue.reset(); } break; } T value; disk_queue->pop(&value); if (memory_queue.full()) { guarantee(notify_when_room_in_memory_queue == NULL); cond_t cond; assignment_sentry_t<cond_t *> assignment_sentry(¬ify_when_room_in_memory_queue, &cond); wait_interruptible(&cond, keepalive.get_drain_signal()); } memory_queue.push_back(value); available_control.set_available(true); } } catch (const interrupted_exc_t &) { /* ignore */ } }
void copy_from_disk_queue_to_memory_queue(auto_drainer_t::lock_t keepalive) { try { while (!keepalive.get_drain_signal()->is_pulsed()) { if (disk_queue->empty()) { if (items_in_queue != memory_queue.size()) { // There is a push in progress, there's no good way to wait on // it, so we'll start a new coroutine later restart_copy_coro = true; } else { disk_queue.reset(); } break; } write_message_t wm; copying_viewer_t viewer(&wm); disk_queue->pop(&viewer); if (memory_queue_free_space <= 0) { guarantee(notify_when_room_in_memory_queue == nullptr); cond_t cond; assignment_sentry_t<cond_t *> assignment_sentry( ¬ify_when_room_in_memory_queue, &cond); wait_interruptible(&cond, keepalive.get_drain_signal()); } memory_queue_free_space -= wm.size(); memory_queue.emplace_back(std::move(wm)); available_control.set_available(true); } } catch (const interrupted_exc_t &) { /* ignore */ } }
void perform_request(const request_type &request, auto_drainer_t::lock_t keepalive) { requests_since_last_qps_sample++; try { registrant.perform_request(request, keepalive.get_drain_signal()); } catch (interrupted_exc_t) { /* ignore */ } in_use_tickets--; parent->return_tickets(1); }
void on_create(registration_id_t rid, peer_id_t peer, business_card_t business_card, auto_drainer_t::lock_t keepalive) { /* Grab the mutex to avoid race conditions if a message arrives at the update mailbox or the delete mailbox while we're working. We must not block between when `on_create()` begins and when `mutex_acq` is constructed. */ mutex_t::acq_t mutex_acq(&mutex); /* If the registrant has already deregistered but the deregistration message arrived ahead of the registration message, it will have left a NULL in the `registrations` map. */ typename std::map<registration_id_t, cond_t *>::iterator it = registrations.find(rid); if (it != registrations.end()) { guarantee(it->second == NULL); registrations.erase(it); return; } /* Construct a `registrant_t` to tell the controller that something has now registered. */ registrant_type registrant(controller, business_card); /* `registration` is the interface that we expose to the `on_update()` and `on_delete()` handlers. */ cond_t deletion_cond; /* Expose `deletion_cond` so that `on_delete()` can find it. */ map_insertion_sentry_t<registration_id_t, cond_t *> registration_map_sentry( ®istrations, rid, &deletion_cond); /* Begin monitoring the peer so we can disconnect when necessary. */ disconnect_watcher_t peer_monitor(mailbox_manager->get_connectivity_service(), peer); /* Release the mutex, since we're done with our initial setup phase */ { mutex_t::acq_t doomed; swap(mutex_acq, doomed); } /* Wait till it's time to shut down */ wait_any_t waiter(&deletion_cond, &peer_monitor, keepalive.get_drain_signal()); waiter.wait_lazily_unordered(); /* Reacquire the mutex, to avoid race conditions when we're deregistering from `deleters`. I'm not sure if there re any such race conditions, but better safe than sorry. */ { mutex_t::acq_t reacquisition(&mutex); swap(mutex_acq, reacquisition); } /* `registration_map_sentry` destructor run here; `deletion_cond` cannot be pulsed after this. */ /* `deletion_cond` destructor run here. */ /* `registrant` destructor run here; this will tell the controller that the registration is dead and gone. */ /* `mutex_acq` destructor run here; it's safe to release the mutex because we're no longer touching `updaters` or `deleters`. */ }