void RPCChannel::DebugAbort(const char* file, int line, const char* cond, const char* why, const char* type, bool reply) const { printf_stderr("###!!! [RPCChannel][%s][%s:%d] " "Assertion (%s) failed. %s (triggered by %s%s)\n", mChild ? "Child" : "Parent", file, line, cond, why, type, reply ? "reply" : ""); // technically we need the mutex for this, but we're dying anyway DumpRPCStack(" "); printf_stderr(" remote RPC stack guess: %lu\n", mRemoteStackDepthGuess); printf_stderr(" deferred stack size: %lu\n", mDeferred.size()); printf_stderr(" out-of-turn RPC replies stack size: %lu\n", mOutOfTurnReplies.size()); printf_stderr(" Pending queue size: %lu, front to back:\n", mPending.size()); MessageQueue pending = mPending; while (!pending.empty()) { printf_stderr(" [ %s%s ]\n", pending.front().is_rpc() ? "rpc" : (pending.front().is_sync() ? "sync" : "async"), pending.front().is_reply() ? "reply" : ""); pending.pop_front(); } NS_RUNTIMEABORT(why); }
Uint32 Sum(const MessageQueue& q) { Uint32 sum = 0; for (const Message* m = q.front(); m; m = m->getNext()) { const Alarm* a = (const Alarm*)m; sum += a->getKey(); } return sum; }
bool RPCChannel::OnMaybeDequeueOne() { // XXX performance tuning knob: could process all or k pending // messages here AssertWorkerThread(); mMonitor->AssertNotCurrentThreadOwns(); Message recvd; { MonitorAutoLock lock(*mMonitor); if (!Connected()) { ReportConnectionError("RPCChannel"); return false; } if (!mDeferred.empty()) MaybeUndeferIncall(); MessageQueue *queue = mUrgent.empty() ? mNonUrgentDeferred.empty() ? &mPending : &mNonUrgentDeferred : &mUrgent; if (queue->empty()) return false; recvd = queue->front(); queue->pop_front(); } if (IsOnCxxStack() && recvd.is_rpc() && recvd.is_reply()) { // We probably just received a reply in a nested loop for an // RPC call sent before entering that loop. mOutOfTurnReplies[recvd.seqno()] = recvd; return false; } CxxStackFrame f(*this, IN_MESSAGE, &recvd); if (recvd.is_rpc()) Incall(recvd, 0); else if (recvd.is_sync()) SyncChannel::OnDispatchMessage(recvd); else AsyncChannel::OnDispatchMessage(recvd); return true; }
void TestMessageQueue2() { MessageQueue q; Uint32 sum = 0; for (Uint32 i = 1; i <= 5; i++) { q.enqueue(new Alarm(i)); sum += i; } assert(sum == 15); while (!q.isEmpty()) q.remove(q.front()); assert(q.getCount() == 0); }
void TestMessageQueue1() { MessageQueue q; Uint32 sum = 0; for (Uint32 i = 1; i <= 5; i++) { q.enqueue(new Alarm(i)); sum += i; } assert(Sum(q) == sum); // Test removing from the middle: Message* m = q.findByKey(3); assert(m != 0); q.remove(m); assert(Sum(q) == sum - 3); assert(q.getCount() == 4); // Test removing from the front: q.remove(q.front()); assert(Sum(q) == sum - 3 - 1); assert(q.getCount() == 3); // Test removing from the front: q.remove(q.back()); assert(Sum(q) == sum - 3 - 1 - 5); assert(q.getCount() == 2); // Test dequeue: m = q.dequeue(); assert(m->getKey() == 2); assert(Sum(q) == sum - 3 - 1 - 5 - 2); assert(q.getCount() == 1); // Test dequeue: m = q.dequeue(); assert(m->getKey() == 4); assert(Sum(q) == sum - 3 - 1 - 5 - 2 - 4); assert(q.getCount() == 0); }