/// <summary> /// Update the RPC server, called once every FixedUpdate. /// This method receives and executes RPCs, for up to MaxTimePerUpdate microseconds. /// RPCs are delayed to the next update if this time expires. If AdaptiveRateControl /// is true, MaxTimePerUpdate will be automatically adjusted to achieve a target framerate. /// If NonBlockingUpdate is false, this call will block waiting for new RPCs for up to /// MaxPollTimePerUpdate microseconds. If NonBlockingUpdate is true, a single non-blocking call /// will be made to check for new RPCs. /// </summary> void RPCServerUpdate() { var timer = Stopwatch.StartNew (); var pollTimeout = new Stopwatch (); var pollTimer = new Stopwatch (); var execTimer = new Stopwatch (); long maxTimePerUpdateTicks = StopwatchExtensions.MicrosecondsToTicks (MaxTimePerUpdate); long recvTimeoutTicks = StopwatchExtensions.MicrosecondsToTicks (RecvTimeout); ulong rpcsExecuted = 0; var yieldedContinuations = new List<RequestContinuation> (); rpcServer.Update (); while (true) { // Poll for RPCs pollTimer.Start (); pollTimeout.Reset (); pollTimeout.Start (); while (true) { PollRequests (yieldedContinuations); if (!BlockingRecv) break; if (pollTimeout.ElapsedTicks > recvTimeoutTicks) break; if (timer.ElapsedTicks > maxTimePerUpdateTicks) break; if (continuations.Any ()) break; } pollTimer.Stop (); if (!continuations.Any ()) break; // Execute RPCs execTimer.Start (); foreach (var continuation in continuations) { // Ignore the continuation if the client has disconnected if (!continuation.Client.Connected) continue; // Max exec time exceeded, delay to next update if (timer.ElapsedTicks > maxTimePerUpdateTicks) { yieldedContinuations.Add (continuation); continue; } // Execute the continuation try { ExecuteContinuation (continuation); } catch (YieldException e) { yieldedContinuations.Add ((RequestContinuation)e.Continuation); } rpcsExecuted++; } continuations.Clear (); execTimer.Stop (); // Exit if only execute one RPC per update if (OneRPCPerUpdate) break; // Exit if max exec time exceeded if (timer.ElapsedTicks > maxTimePerUpdateTicks) break; } // Run yielded continuations on the next update continuations = yieldedContinuations; timer.Stop (); RPCsExecuted += rpcsExecuted; TimePerRPCUpdate = (float)timer.ElapsedSeconds (); PollTimePerRPCUpdate = (float)pollTimer.ElapsedSeconds (); ExecTimePerRPCUpdate = (float)execTimer.ElapsedSeconds (); }