/// <summary> /// A lLoop in background thread. Change the color of the light and flash. /// </summary> private void ProcessLightControlRequestsLoop() { while (true) { int indexFired = WaitHandle.WaitAny(new WaitHandle[] { this.stopRequested, this.outstandingRequestExist }); if (indexFired == 0) { // this.stopRequested fired. Exit the thread. break; } LightControlRequest?request = null; lock (this.outstandingRequestLock) { request = this.outstandingRequest; this.outstandingRequest = null; this.outstandingRequestExist.Reset(); } if (!request.HasValue) { // Phantom event. Wait next. continue; } Trace.TraceInformation("ProcessLightControlRequestsLoop processing: color={0}, flash={1}", request.Value.Color, request.Value.Flash); if (request.Value.Color == LightColor.Off) { if (!this.wrapper.TurnOffAllLights()) { Trace.TraceError("ProcessLightControlRequestsLoop failure: off"); } else { TraceVerbose.Trace("ProcessLightControlRequestsLoop success: off"); } } else { DelcomLightColor color = ConvertColor(request.Value.Color); DelcomLightState state = request.Value.Flash ? DelcomLightState.Flash : DelcomLightState.On; if (!wrapper.SetLight(color, state)) { Trace.TraceError("ProcessLightControlRequestsLoop failure: color={0}, state={1}", color, state); } else { TraceVerbose.Trace("ProcessLightControlRequestsLoop success: color={0}, state={1}", color, state); } } } }
/// <summary> /// Process queued inputs in serialized FIFO order. /// </summary> private void InputProcessLoop() { while (true) { int indexFired = WaitHandle.WaitAny(new WaitHandle[] { this.stopRequested, this.inputQueueEvent }); if (indexFired == 0) { // this.stopRequested fired. Exit the thread. break; } // Pull an input from input queue. Input input; lock (this.inputQueue) { if (this.inputQueue.Count == 0) { // Phantom event with some reason. Wait for next input. this.inputQueueEvent.Reset(); continue; } input = inputQueue.Dequeue(); if (this.inputQueue.Count == 0) { this.inputQueueEvent.Reset(); } } // Look up the transition table. Transition transition; if (this.transitionTable.TryGetValue(new Condition(this.state, input), out transition)) { // Invoke the action. Trace.TraceInformation("Invoking {0} (Input:{1} State:{2}->{3})", transition.ActionMethod.Method.Name, input, this.state, transition.NextState); if (transition.ActionMethod(input)) { this.state = transition.NextState; this.tcp.TcpSend(this.state.ToString() + " OK"); } else { Trace.TraceError("{0} failed. State stays at {1}", transition.ActionMethod.Method.Name, this.state); this.tcp.TcpSend(transition.NextState.ToString() + " ERROR"); } } else { TraceVerbose.Trace("No transition for Input:{0} State:{1})", input, this.state); } } }
/// <summary> /// Stop processing thread. /// </summary> public void Stop() { if (this.inputProcessThread == null) { throw new ApplicationException("StateMachine.Stop() is called while not running."); } TraceVerbose.Trace("State machine is being stopped."); this.stopRequested.Set(); this.inputProcessThread.Join(); this.inputProcessThread = null; TraceVerbose.Trace("State machine has stopped."); }
public void SetSolid(LightColor color) { LightControlRequest request = new LightControlRequest() { Color = color, Flash = false }; lock (this.outstandingRequestLock) { outstandingRequest = request; outstandingRequestExist.Set(); TraceVerbose.Trace("SetSolid({0}): request queued.", color); } }
/// <summary> /// Set ILightControl interface, RemoteRecoderSync, and start processing thread. /// </summary> /// <param name="remoteRecorder">Remote recorder controller. Cannot be null.</param> /// <param name="lightControl">Light control interface. May be null.</param> public void Start(RemoteRecorderSync remoteRecorder, ILightControl lightControl) { if (remoteRecorder == null) { throw new ArgumentException("remoteRecorder cannot be null."); } if (this.inputProcessThread != null) { throw new ApplicationException("StateMachine.Start() is called while running."); } this.remoteRecorder = remoteRecorder; this.light = lightControl ?? new EmptyLightControl(); this.inputProcessThread = new Thread(this.InputProcessLoop); TraceVerbose.Trace("State machine is starting."); inputProcessThread.Start(); }
public void SetFlash(LightColor color) { if (color == LightColor.Off) { throw new ArgumentException("LightColor.Off is invalid"); } LightControlRequest request = new LightControlRequest() { Color = color, Flash = true }; lock (this.outstandingRequestLock) { outstandingRequest = request; outstandingRequestExist.Set(); TraceVerbose.Trace("SetFlash({0}): request queued.", color); } }