// UNCLASSIFIED /*------------------------------------------------------------------------- RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON COMPANY. THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT. UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. -------------------------------------------------------------------------*/ using System; using System.Threading; using NLog; using Raytheon.Common; namespace Raytheon.Instruments { /// /// An interface to sending/receiving data over comm devices /// internal class CommDeviceNode : ICommDevice, IDisposable { #region PrivateClassMembers private ICommDevice _commDevice; private IWorkerInterface _socketReadWorker; private Thread _socketReadThread; private readonly string _name; private SelfTestResult _selfTestResult; private State _state; private uint _commReadWorkerBufferSize; private uint _readWorkerRestTimeInMs; private MsgDevice _msgHandler; private readonly ILogger _logger; #endregion #region PrivateFuctions /// /// The finalizer. Necessary for quitting the read thread /// ~CommDeviceNode() { Dispose(false); } /// /// Quit the threads associated with the node /// /// protected virtual void Dispose(bool disposing) { if (disposing) { State initialState = _state; // close the socket and threads if (initialState == State.Ready) { Shutdown(); _commDevice.Shutdown(); } // dispose of the resources if (initialState == State.Ready) { _socketReadWorker.Dispose(); _state = State.Uninitialized; } } } #endregion #region PublicFuctions /// /// The constructor /// /// The name of this instance /// The communication device /// The message handler for this interface /// The number of bytes for the buffer internal to this class. Each individual read will read upto this buffer size (or until the timeout happens) /// Number of ms to reset between read calls on the comm interface public CommDeviceNode(string name, ICommDevice commDevice, MsgDevice msgHandler, uint commReadWorkerBufferSize = 100000, uint readWorkerRestTimeInMs = 10) { _logger = LogManager.GetCurrentClassLogger(); _name = name; _commDevice = commDevice; _commReadWorkerBufferSize = commReadWorkerBufferSize; _readWorkerRestTimeInMs = readWorkerRestTimeInMs; _msgHandler = msgHandler; Open(); } /// /// Starts communication thread /// public void Open() { _socketReadWorker = new CommReadWorker(this, _msgHandler, _commReadWorkerBufferSize, _readWorkerRestTimeInMs); _socketReadThread = new Thread(_socketReadWorker.DoWork); // start the read thread _socketReadThread.Start(); _selfTestResult = SelfTestResult.Unknown; _state = State.Uninitialized; } /// /// there is no error msg repository /// /// public bool ClearErrors() { return false; } /// /// /// public bool DisplayEnabled { get { return false; } set { throw new NotImplementedException(); } } /// /// /// public string DetailedStatus { get { return "This is a Comm Sim Device Node " + _name; } } /// /// /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// /// public bool FrontPanelEnabled { get { return false; } set { throw new NotImplementedException(); } } /// /// /// public InstrumentMetadata Info { get { throw new NotImplementedException(); } } /// /// /// public void Initialize() { _commDevice.Initialize(); _state = State.Ready; } /// /// /// public string Name { get { return _name; } } /// /// /// /// public SelfTestResult PerformSelfTest() { throw new NotImplementedException(); } /// /// Read data from the socket /// /// The data that was read /// the number of bytes read public uint Read(ref byte[] dataRead) { return _commDevice.Read(ref dataRead); } /// /// Resets communications /// public void Reset() { Close(); Open(); } /// /// /// /// public void SetReadTimeout(uint readTimeout) { _commDevice.SetReadTimeout(readTimeout); } /// /// /// public SelfTestResult SelfTestResult { get { return _selfTestResult; } } /// /// /// public State Status { get { return _state; } } /// /// Close communications /// public void Close() { Shutdown(); } /// /// Close communications /// public void Shutdown() { if (_state == State.Ready) { const int THREAD_QUIT_TIMEOUT_MS = 3000; // tell the thread to quit _socketReadWorker.QuitWork(); // close the socket which the thread might be blocked on _commDevice.Shutdown(); if (_socketReadThread.IsAlive) { bool didThreadQuit = _socketReadThread.Join(THREAD_QUIT_TIMEOUT_MS); if (didThreadQuit == false) { _socketReadThread.Abort(); } else { _logger.Debug("Logging Thread quit successfully after join"); } } else { _logger.Debug("Logging Thread quit successfully"); } } _state = State.Uninitialized; } /// /// Send data on the socket /// /// The data to send /// The number of bytes to write from the dataToSend buffer /// The number of bytes sent public uint Write(byte[] dataToSend, uint numBytesToWrite) { return _commDevice.Write(dataToSend, numBytesToWrite); } #endregion } }