void consume(int id, int X) { int n = X; while (n > 0) { unsigned m = counting_sem_lazy_wait(&sem, n); n -= m; printf("c %d consumed %d, remaining %d\n", id, m, n); } printf("consumer %d done\n", id); }
size_t McrouterClient::send( const mcrouter_msg_t* requests, size_t nreqs, folly::StringPiece ipAddr /* = folly::StringPiece() */ ) { assert(!disconnected_); auto router = router_.lock(); if (nreqs == 0 || !router) { return 0; } auto makePreq = [this, &requests, ipAddr](size_t i) { auto cb = [this, context = requests[i].context, req = McMsgRef::cloneRef(requests[i].req)] (ProxyRequestContext&, McReply&& reply) mutable { this->onReply(std::move(reply), std::move(req), context); }; auto preq = createLegacyProxyRequestContext( *proxy_, McMsgRef::cloneRef(requests[i].req), std::move(cb)); preq->requester_ = self_; if (!ipAddr.empty()) { preq->setUserIpAddress(ipAddr); } return preq; }; if (maxOutstanding_ == 0) { if (sameThread_) { for (size_t i = 0; i < nreqs; i++) { sendSameThread(makePreq(i)); } } else { for (size_t i = 0; i < nreqs; i++) { sendRemoteThread(makePreq(i)); } } } else if (maxOutstandingError_) { for(size_t begin = 0; begin < nreqs;) { auto end = begin + counting_sem_lazy_nonblocking(&outstandingReqsSem_, nreqs - begin); if (begin == end) { for (size_t i = begin; i < nreqs; ++i) { mcrouter_msg_t error_reply; error_reply.req = requests[i].req; error_reply.reply = McReply(mc_res_local_error); error_reply.context = requests[i].context; callbacks_.on_reply(&error_reply, arg_); } break; } if (sameThread_) { for (size_t i = begin; i < end; i++) { sendSameThread(makePreq(i)); } } else { for (size_t i = begin; i < end; i++) { sendRemoteThread(makePreq(i)); } } begin = end; } } else { assert(!sameThread_); size_t i = 0; size_t n = 0; while (i < nreqs) { n += counting_sem_lazy_wait(&outstandingReqsSem_, nreqs - n); for (size_t j = i; j < n; ++j) { sendRemoteThread(makePreq(j)); } i = n; } } return nreqs; }