/// <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);
                    }
                }
            }
        }
Beispiel #2
0
        /// <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);
            }
        }