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); }
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 } }
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)); }
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); }
public void Add(T item) { lock (_root) { _list.Add(item); } }