예제 #1
0
    public ReusableList <T> FindAll(Predicate <T> match)
    {
        if (match == null)
        {
            throw new ArgumentException();
        }
        Contract.EndContractBlock();

        ReusableList <T> list = new ReusableList <T>();

        for (int i = 0; i < _size; i++)
        {
            if (match(_items[i]))
            {
                list.Add(_items[i]);
            }
        }
        return(list);
    }
예제 #2
0
        private void OverlappedIoThreadMainLoop()
        {
            // WaitCommEvent
            bool serialCommPending = false;
            bool serialCommError   = false;

            m_SerialCommEvent.Reset();
            NativeOverlapped serialCommOverlapped = new NativeOverlapped();

#if NETSTANDARD15
            serialCommOverlapped.EventHandle = m_SerialCommEvent.GetSafeWaitHandle().DangerousGetHandle();
#else
            serialCommOverlapped.EventHandle = m_SerialCommEvent.SafeWaitHandle.DangerousGetHandle();
#endif
            // ReadFile
            bool readPending = false;
            m_ReadEvent.Reset();
            NativeOverlapped readOverlapped = new NativeOverlapped();
#if NETSTANDARD15
            readOverlapped.EventHandle = m_ReadEvent.GetSafeWaitHandle().DangerousGetHandle();
#else
            readOverlapped.EventHandle = m_ReadEvent.SafeWaitHandle.DangerousGetHandle();
#endif
            // WriteFile
            bool writePending = false;
            m_WriteEvent.Reset();
            NativeOverlapped writeOverlapped = new NativeOverlapped();
            m_ReadByteAvailable = false;
#if NETSTANDARD15
            writeOverlapped.EventHandle = m_WriteEvent.GetSafeWaitHandle().DangerousGetHandle();
#else
            writeOverlapped.EventHandle = m_WriteEvent.SafeWaitHandle.DangerousGetHandle();
#endif
            // SEt up the types of serial events we want to see.
            UnsafeNativeMethods.SetCommMask(m_ComPortHandle, maskRead);

            bool result;
            NativeMethods.SerialEventMask commEventMask = 0;

            bool running = true;
            uint bytes;
            ReusableList <WaitHandle> handles = new ReusableList <WaitHandle>(2, 7);

            while (running)
            {
                handles.Clear();
                handles.Add(m_StopRunning);
                handles.Add(m_WriteClearEvent);

#if PL2303_WORKAROUNDS
                // - - - - - - - - - - - - - - - - - - - - - - - - -
                // PROLIFIC PL23030 WORKAROUND
                // - - - - - - - - - - - - - - - - - - - - - - - - -
                // If we have a read pending, we don't request events
                // for reading data. To do so will result in errors.
                // Have no idea why.
                if (readPending)
                {
                    UnsafeNativeMethods.SetCommMask(m_ComPortHandle, maskReadPending);
                }
                else
                {
                    UnsafeNativeMethods.SetCommMask(m_ComPortHandle, maskRead);

                    // While the comm event mask was set to ignore read events, data could have been written
                    // to the input queue. Check for that and if there are bytes waiting or EOF was received,
                    // set the appropriate flags.
                    uint bytesInQueue;
                    bool eofReceived;
                    if (GetReceiveStats(out bytesInQueue, out eofReceived) && (bytesInQueue > 0 || eofReceived))
                    {
                        // Tell DoReadEvent that there is data pending
                        m_ReadByteAvailable = true;
                        m_ReadByteEof      |= eofReceived;
                    }
                }
#else
                UnsafeNativeMethods.SetCommMask(m_ComPortHandle, maskRead);
#endif

                // commEventMask is on the stack, and is therefore fixed
                if (!serialCommError)
                {
                    try {
                        if (!serialCommPending)
                        {
                            serialCommPending = DoWaitCommEvent(out commEventMask, ref serialCommOverlapped);
                        }
                        if (serialCommPending)
                        {
                            handles.Add(m_SerialCommEvent);
                        }
                    } catch (IOException) {
                        // Some devices, such as the Arduino Uno with a CH340 on board don't support an overlapped
                        // WaitCommEvent. So if that occurs, we remember it and don't use it again. The Windows error
                        // returned was 87 (ERROR_INVALID_PARAMETER) was returned in that case. GetReceiveStats() did
                        // work, so we can still know of data pending by polling. But we won't get any other events,
                        // such as TX_EMPTY.
                        if (Log.SerialTrace(System.Diagnostics.TraceEventType.Warning))
                        {
                            Log.Serial.TraceEvent(System.Diagnostics.TraceEventType.Warning, 0,
                                                  "{0}: SerialThread: Not processing WaitCommEvent events", m_Name);
                        }
                        serialCommError = true;
                    }
                }

                if (!readPending)
                {
                    if (!m_Buffer.Serial.ReadBufferNotFull.WaitOne(0))
                    {
                        if (Log.SerialTrace(System.Diagnostics.TraceEventType.Verbose))
                        {
                            Log.Serial.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 0, "{0}: SerialThread: Read Buffer Full", m_Name);
                        }
                        handles.Add(m_Buffer.Serial.ReadBufferNotFull);
                    }
                    else
                    {
                        readPending = DoReadEvent(ref readOverlapped);
                    }
                }
                if (readPending)
                {
                    handles.Add(m_ReadEvent);
                }

                if (!writePending)
                {
                    if (!m_Buffer.Serial.WriteBufferNotEmpty.WaitOne(0))
                    {
                        handles.Add(m_Buffer.Serial.WriteBufferNotEmpty);
                    }
                    else
                    {
                        writePending = DoWriteEvent(ref writeOverlapped);
                    }
                }
                if (writePending)
                {
                    handles.Add(m_WriteEvent);
                }

                // We wait up to 100ms, in case we're not actually pending on anything. Normally, we should always be
                // pending on a Comm event. Just in case this is not so (and is a theoretical possibility), we will
                // slip out of this WaitAny() after 100ms and then restart the loop, effectively polling every 100ms in
                // worst case.
                WaitHandle[] whandles = handles.ToArray();
                int          ev       = WaitHandle.WaitAny(whandles, 100);

                if (ev != WaitHandle.WaitTimeout)
                {
                    if (whandles[ev] == m_StopRunning)
                    {
                        if (Log.SerialTrace(System.Diagnostics.TraceEventType.Verbose))
                        {
                            Log.Serial.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 0, "{0}: SerialThread: Thread closing", m_Name);
                        }
                        result = UnsafeNativeMethods.CancelIo(m_ComPortHandle);
                        if (!result)
                        {
                            int win32Error = Marshal.GetLastWin32Error();
                            //int hr = Marshal.GetHRForLastWin32Error();
                            if (Log.SerialTrace(System.Diagnostics.TraceEventType.Warning))
                            {
                                Log.Serial.TraceEvent(System.Diagnostics.TraceEventType.Warning, 0,
                                                      "{0}: SerialThread: CancelIo error {1}", m_Name, win32Error);
                            }
                            Marshal.ThrowExceptionForHR(win32Error);
                        }
                        running = false;
                    }
                    else if (whandles[ev] == m_SerialCommEvent)
                    {
                        result = UnsafeNativeMethods.GetOverlappedResult(m_ComPortHandle, ref serialCommOverlapped, out bytes, true);
                        if (!result)
                        {
                            int win32Error = Marshal.GetLastWin32Error();
                            //int hr = Marshal.GetHRForLastWin32Error();
                            if (Log.SerialTrace(System.Diagnostics.TraceEventType.Error))
                            {
                                Log.Serial.TraceEvent(System.Diagnostics.TraceEventType.Error, 0,
                                                      "{0}: SerialThread: Overlapped WaitCommEvent() error {1}", m_Name, win32Error);
                            }
                            Marshal.ThrowExceptionForHR(win32Error);
                        }
                        ProcessWaitCommEvent(commEventMask);
                        serialCommPending = false;
                    }
                    else if (whandles[ev] == m_ReadEvent)
                    {
                        result = UnsafeNativeMethods.GetOverlappedResult(m_ComPortHandle, ref readOverlapped, out bytes, true);
                        if (!result)
                        {
                            int win32Error = Marshal.GetLastWin32Error();
                            //int hr = Marshal.GetHRForLastWin32Error();
                            // Should never get ERROR_IO_PENDING, as this method is only called when the event is triggered.
                            if (win32Error != WinError.ERROR_OPERATION_ABORTED || bytes > 0)
                            {
                                if (Log.SerialTrace(System.Diagnostics.TraceEventType.Error))
                                {
                                    Log.Serial.TraceEvent(System.Diagnostics.TraceEventType.Error, 0,
                                                          "{0}: SerialThread: Overlapped ReadFile() error {1} bytes {2}", m_Name, win32Error, bytes);
                                }
                                Marshal.ThrowExceptionForHR(win32Error);
                            }
                            else
                            {
                                // ERROR_OPERATION_ABORTED may be caused by CancelIo or PurgeComm
                                if (Log.SerialTrace(System.Diagnostics.TraceEventType.Verbose))
                                {
                                    Log.Serial.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 0,
                                                          "{0}: SerialThread: Overlapped ReadFile() error {1} bytes {2}", m_Name, win32Error, bytes);
                                }
                            }
                        }
                        else
                        {
                            ProcessReadEvent(bytes);
                        }
                        readPending = false;
                    }
                    else if (whandles[ev] == m_Buffer.Serial.ReadBufferNotFull)
                    {
                        // The read buffer is no longer full. We just loop back to the beginning to test if we
                        // should read or not.
                    }
                    else if (whandles[ev] == m_WriteEvent)
                    {
                        result = UnsafeNativeMethods.GetOverlappedResult(m_ComPortHandle, ref writeOverlapped, out bytes, true);
                        if (!result)
                        {
                            int win32Error = Marshal.GetLastWin32Error();
                            //int hr = Marshal.GetHRForLastWin32Error();
                            // Should never get ERROR_IO_PENDING, as this method is only called when the event is triggered.
                            if (win32Error != WinError.ERROR_OPERATION_ABORTED || bytes > 0)
                            {
                                if (Log.SerialTrace(System.Diagnostics.TraceEventType.Error))
                                {
                                    Log.Serial.TraceEvent(System.Diagnostics.TraceEventType.Error, 0,
                                                          "{0}: SerialThread: Overlapped WriteFile() error {1} bytes {2}", m_Name, win32Error, bytes);
                                }
                                Marshal.ThrowExceptionForHR(win32Error);
                            }
                            else
                            {
                                // ERROR_OPERATION_ABORTED may be caused by CancelIo or PurgeComm
                                if (Log.SerialTrace(System.Diagnostics.TraceEventType.Verbose))
                                {
                                    Log.Serial.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 0,
                                                          "{0}: SerialThread: Overlapped WriteFile() error {1} bytes {2}", m_Name, win32Error, bytes);
                                }
                            }
                        }
                        else
                        {
                            ProcessWriteEvent(bytes);
                        }
                        writePending = false;
                    }
                    else if (whandles[ev] == m_Buffer.Serial.WriteBufferNotEmpty)
                    {
                        // The write buffer is no longer empty. We just loop back to the beginning to test if we
                        // should write or not.
                    }
                    else if (whandles[ev] == m_WriteClearEvent)
                    {
                        if (writePending)
                        {
                            if (Log.SerialTrace(System.Diagnostics.TraceEventType.Verbose))
                            {
                                Log.Serial.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 0, "{0}: SerialThread: PurgeComm() write pending", m_Name);
                            }
                            m_PurgePending = true;
                            result         = UnsafeNativeMethods.PurgeComm(m_ComPortHandle,
                                                                           NativeMethods.PurgeFlags.PURGE_TXABORT | NativeMethods.PurgeFlags.PURGE_TXCLEAR);
                            if (!result)
                            {
                                int win32Error = Marshal.GetLastWin32Error();
                                //int hr = Marshal.GetHRForLastWin32Error();
                                if (win32Error != WinError.ERROR_OPERATION_ABORTED)
                                {
                                    if (Log.SerialTrace(System.Diagnostics.TraceEventType.Error))
                                    {
                                        Log.Serial.TraceEvent(System.Diagnostics.TraceEventType.Error, 0,
                                                              "{0}: SerialThread: PurgeComm() error {1}", m_Name, win32Error);
                                    }
                                    Marshal.ThrowExceptionForHR(win32Error);
                                }
                                else
                                {
                                    if (Log.SerialTrace(System.Diagnostics.TraceEventType.Verbose))
                                    {
                                        Log.Serial.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 0,
                                                              "{0}: SerialThread: PurgeComm() error {1}", m_Name, win32Error);
                                    }
                                }
                            }
                        }
                        else
                        {
                            lock (m_Buffer.WriteLock) {
                                if (Log.SerialTrace(System.Diagnostics.TraceEventType.Verbose))
                                {
                                    Log.Serial.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 0, "{0}: SerialThread: Purged", m_Name);
                                }
                                m_Buffer.Serial.Purge();
                                m_WriteClearDoneEvent.Set();
                            }
                        }
                    }
                }

#if STRESSTEST
                SerialTrace.TraceSer.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 0, "{0}: STRESSTEST SerialThread: Stress Test Delay of 1000ms", m_Name);
                System.Threading.Thread.Sleep(1000);
                NativeMethods.ComStatErrors commStateErrors = new NativeMethods.ComStatErrors();
                NativeMethods.COMSTAT       commStat        = new NativeMethods.COMSTAT();
                result = UnsafeNativeMethods.ClearCommError(m_ComPortHandle, out commStateErrors, out commStat);
                if (result)
                {
                    SerialTrace.TraceSer.TraceEvent(System.Diagnostics.TraceEventType.Information, 0,
                                                    "{0}: STRESSTEST SerialThread: ClearCommError errors={1}", m_Name, commStateErrors);
                    SerialTrace.TraceSer.TraceEvent(System.Diagnostics.TraceEventType.Information, 0,
                                                    "{0}: STRESSTEST SerialThread: ClearCommError stats flags={1}, InQueue={2}, OutQueue={3}", m_Name, commStat.Flags, commStat.cbInQue, commStat.cbOutQue);
                }
                else
                {
                    SerialTrace.TraceSer.TraceEvent(System.Diagnostics.TraceEventType.Warning, 0,
                                                    "{0}: STRESSTEST SerialThread: ClearCommError error: {1}", m_Name, Marshal.GetLastWin32Error());
                }
#endif
            }
        }
예제 #3
0
        private bool ExecuteGuarded(IList <string> tokens, string commandLine = null)
        {
            ResetOptions();

            Iterator <string> iter = new Iterator <string>(tokens);

            iter.Next(); // first token is a command name

            if (this.IsManualMode)
            {
                PrintPrompt(commandLine);
            }

            if (this.IsPlayModeOnly && !Runtime.IsPlaying)
            {
                PrintError("Command is available in the play mode only");
                return(false);
            }

            ReusableList <string> argsList = ReusableLists.NextAutoRecycleList <string>();

            while (iter.HasNext())
            {
                string token = StringUtils.UnArg(iter.Next());

                // first, try to parse options
                if (!TryParseOption(iter, token))
                {
                    // consume the rest of the args
                    argsList.Add(token);
                    while (iter.HasNext())
                    {
                        token = StringUtils.UnArg(iter.Next());
                        argsList.Add(token);
                    }

                    break;
                }
            }

            if (m_values != null)
            {
                if (argsList.Count != 1)
                {
                    PrintError("Unexpected arguments count {0}", argsList.Count);
                    PrintUsage();
                    return(false);
                }

                string arg = argsList[0];
                if (Array.IndexOf(m_values, arg) == -1)
                {
                    PrintError("Unexpected argument '{0}'", arg);
                    PrintUsage();
                    return(false);
                }
            }

            if (m_options != null)
            {
                for (int i = 0; i < m_options.Count; ++i)
                {
                    Option opt = m_options[i];
                    if (opt.IsRequired && !opt.IsHandled)
                    {
                        PrintError("Missing required option --{0}{1}", opt.Name, opt.ShortName != null ? "(-" + opt.ShortName + ")" : "");
                        PrintUsage();
                        return(false);
                    }
                }
            }

            string[]   args          = argsList.Count > 0 ? argsList.ToArray() : EMPTY_COMMAND_ARGS;
            MethodInfo executeMethod = resolveExecuteMethod(args);

            if (executeMethod == null)
            {
                PrintError("Wrong arguments");
                PrintUsage();
                return(false);
            }

            return(CCommandUtils.Invoke(this, executeMethod, args));
        }
예제 #4
0
        public static StackTraceLine[] ParseStackTrace(string stackTrace)
        {
            if (stackTrace != null)
            {
                ReusableList <StackTraceLine> list = ReusableLists.NextList <StackTraceLine>();

                int lineStart = 0;
                int lineEnd;

                while (lineStart < stackTrace.Length)
                {
                    // extract next line
                    lineEnd = StringUtils.EndOfLineIndex(stackTrace, lineStart);
                    string line = stackTrace.Substring(lineStart, lineEnd - lineStart);
                    lineStart = lineEnd + 1;

                    // extract data
                    Match m;
                    if ((m = PatternUnityStackTrace.Match(line)).Success)
                    {
                        GroupCollection groups        = m.Groups;
                        string          sourcePath    = groups[2].Value;
                        string          lineNumberStr = groups[3].Value;
                        int             lineNumber    = StringUtils.ParseInt(lineNumberStr, -1);

                        list.Add(new StackTraceLine(line, string.IsNullOrEmpty(sourcePath) ? null : sourcePath, lineNumber, lineNumberStr.Length));
                    }
                    else if ((m = PatternSystemStackTrace.Match(line)).Success)
                    {
                        GroupCollection groups = m.Groups;

                        string method        = groups[1].Value;
                        string args          = OptimizeArgs(groups[2].Value);
                        string path          = OptimizePath(groups[4].Value);
                        string lineNumberStr = groups[5].Value;
                        int    lineNumber    = StringUtils.ParseInt(lineNumberStr, -1);

                        if (!string.IsNullOrEmpty(path) && lineNumber != -1)
                        {
                            line = StringUtils.TryFormat("{0}({1}) (at {2}:{3})", method, args, path, lineNumberStr);
                        }
                        else
                        {
                            line = StringUtils.TryFormat("{0}({1})", method, args);
                        }

                        list.Add(new StackTraceLine(line, path, lineNumber, lineNumberStr.Length));
                    }
                    else
                    {
                        list.Add(new StackTraceLine(line));
                    }
                }

                StackTraceLine[] lines = list.ToArray();
                list.Recycle();
                return(lines);
            }

            return(StackTraceLine.kEmptyLinesArray);
        }
예제 #5
0
 public void Add(T item)
 {
     lock (_root) {
         _list.Add(item);
     }
 }