void RPCServerUpdate() { rpcTimer.Reset(); rpcTimer.Start(); rpcPollTimeout.Reset(); rpcPollTimer.Reset(); rpcExecTimer.Reset(); var config = Configuration.Instance; long maxTimePerUpdateTicks = StopwatchExtensions.MicrosecondsToTicks(config.MaxTimePerUpdate); long recvTimeoutTicks = StopwatchExtensions.MicrosecondsToTicks(config.RecvTimeout); ulong rpcsExecuted = 0; rpcYieldedContinuations.Clear(); for (int i = 0; i < Servers.Count; i++) { Servers [i].RPCServer.Update(); } while (true) { // Poll for RPCs rpcPollTimer.Start(); rpcPollTimeout.Reset(); rpcPollTimeout.Start(); while (true) { PollRequests(rpcYieldedContinuations); if (!config.BlockingRecv) { break; } if (rpcPollTimeout.ElapsedTicks > recvTimeoutTicks) { break; } if (rpcTimer.ElapsedTicks > maxTimePerUpdateTicks) { break; } if (rpcContinuations.Count > 0) { break; } } rpcPollTimer.Stop(); if (rpcContinuations.Count == 0) { break; } // Execute RPCs rpcExecTimer.Start(); for (int i = 0; i < rpcContinuations.Count; i++) { var continuation = rpcContinuations [i]; // Ignore the continuation if the client has disconnected if (!continuation.Client.Connected) { continue; } // Max exec time exceeded, delay to next update if (rpcTimer.ElapsedTicks > maxTimePerUpdateTicks) { rpcYieldedContinuations.Add(continuation); continue; } // Execute the continuation try { ExecuteContinuation(continuation); } catch (YieldException e) { rpcYieldedContinuations.Add((RequestContinuation)e.Continuation); } rpcsExecuted++; } rpcContinuations.Clear(); rpcExecTimer.Stop(); // Exit if only execute one RPC per update if (config.OneRPCPerUpdate) { break; } // Exit if max exec time exceeded if (rpcTimer.ElapsedTicks > maxTimePerUpdateTicks) { break; } } // Run yielded continuations on the next update var tmp = rpcContinuations; rpcContinuations = rpcYieldedContinuations; rpcYieldedContinuations = tmp; rpcTimer.Stop(); RPCsExecuted += rpcsExecuted; TimePerRPCUpdate = (float)rpcTimer.ElapsedSeconds(); PollTimePerRPCUpdate = (float)rpcPollTimer.ElapsedSeconds(); ExecTimePerRPCUpdate = (float)rpcExecTimer.ElapsedSeconds(); }
/// <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(); }