public static bool IsStopped(Thread self) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); RubyThreadStatus status = GetStatus(self); return(status == RubyThreadStatus.Sleeping || status == RubyThreadStatus.Completed || status == RubyThreadStatus.Aborted); }
public static MutableString /*!*/ Inspect(RubyContext /*!*/ context, Thread /*!*/ self) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); MutableString result = MutableString.CreateMutable(); result.Append("#<"); result.Append(RubyUtils.GetClassName(context, self)); result.Append(':'); RubyUtils.AppendFormatHexObjectId(result, RubyUtils.GetObjectId(context, self)); result.Append(' '); if ((self.ThreadState & ThreadState.WaitSleepJoin) != 0) { result.Append("sleep"); } else if ((self.ThreadState & (ThreadState.Stopped | ThreadState.Aborted | ThreadState.AbortRequested)) != 0) { result.Append("dead"); } else { result.Append("run"); } result.Append('>'); return(result); }
public static object AbortOnException(Thread /*!*/ self, bool value) { RubyThreadInfo info = RubyThreadInfo.FromThread(self); info.AbortOnException = value; return(value); }
public static object Status(Thread /*!*/ self) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); switch (GetStatus(self)) { case RubyThreadStatus.Unstarted: return(MutableString.CreateAscii("unstarted")); case RubyThreadStatus.Running: return(MutableString.CreateAscii("run")); case RubyThreadStatus.Sleeping: return(MutableString.CreateAscii("sleep")); case RubyThreadStatus.Aborting: return(MutableString.CreateAscii("aborting")); case RubyThreadStatus.Completed: return(false); case RubyThreadStatus.Aborted: return(null); default: throw new ArgumentException("unknown thread status"); } }
public static Thread Priority(Thread /*!*/ self, int priority) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); if (priority <= -2) { self.Priority = ThreadPriority.Lowest; } else if (priority == -1) { self.Priority = ThreadPriority.BelowNormal; } else if (priority == 0) { self.Priority = ThreadPriority.Normal; } else if (priority == 1) { self.Priority = ThreadPriority.AboveNormal; } else { self.Priority = ThreadPriority.Highest; } return(self); }
private static RubyThreadStatus GetStatus(Thread thread) { ThreadState state = thread.ThreadState; RubyThreadInfo info = RubyThreadInfo.FromThread(thread); if ((state & ThreadState.Unstarted) == ThreadState.Unstarted) { if (info.CreatedFromRuby) { // Ruby threads do not have an unstarted status. We must be in the tiny window when ThreadOps.CreateThread // created the thread, but has not called Thread.Start on it yet. return(RubyThreadStatus.Running); } else { // This is a thread created from outside Ruby. In such a case, we do not know when Thread.Start // will be called on it. So we report it as unstarted. return(RubyThreadStatus.Unstarted); } } if ((state & (ThreadState.Stopped | ThreadState.Aborted)) != 0) { if (RubyThreadInfo.FromThread(thread).Exception == null) { return(RubyThreadStatus.Completed); } else { return(RubyThreadStatus.Aborted); } } if ((state & ThreadState.WaitSleepJoin) == ThreadState.WaitSleepJoin) { // We will report a thread to be sleeping more often than in CRuby. This is because any "lock" statement // can potentially cause ThreadState.WaitSleepJoin. Also, "Thread.pass" does System.Threading.Thread.Sleep(0) // which also briefly changes the state to ThreadState.WaitSleepJoin return(RubyThreadStatus.Sleeping); } if ((state & ThreadState.AbortRequested) != 0) { return(RubyThreadStatus.Aborting); } if ((state & ThreadState.Running) == ThreadState.Running) { if (info.Blocked) { return(RubyThreadStatus.Sleeping); } else { return(RubyThreadStatus.Running); } } throw new ArgumentException("unknown thread status: " + state); }
public static object SetElement(Thread /*!*/ self, [NotNull] RubySymbol /*!*/ key, object value) { RubyThreadInfo info = RubyThreadInfo.FromThread(self); info[key] = value; return(value); }
internal static void DoSleep() { RubyThreadInfo.RegisterThread(Thread.CurrentThread); // TODO: MRI throws an exception if you try to stop the main thread RubyThreadInfo info = RubyThreadInfo.FromThread(Thread.CurrentThread); info.Sleep(); }
public static Thread Run(Thread /*!*/ self) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); RubyThreadInfo info = RubyThreadInfo.FromThread(self); info.Run(); return(self); }
internal static RubyThreadInfo FromThread(Thread t) { RubyThreadInfo result; lock (_mapping) { int key = t.ManagedThreadId; if (!_mapping.TryGetValue(key, out result)) { result = new RubyThreadInfo(t); _mapping[key] = result; } } return result; }
internal static RubyThreadInfo FromThread(Thread t) { RubyThreadInfo result; lock (_mapping) { int key = t.ManagedThreadId; if (!_mapping.TryGetValue(key, out result)) { result = new RubyThreadInfo(t); _mapping[key] = result; } } return(result); }
public static Thread /*!*/ Join(Thread /*!*/ self) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); self.Join(); Exception threadException = RubyThreadInfo.FromThread(self).Exception; if (threadException != null) { throw threadException; } return(self); }
public static Thread Kill(Thread /*!*/ self) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); RubyThreadInfo info = RubyThreadInfo.FromThread(self); if (GetStatus(self) == RubyThreadStatus.Sleeping && info.ExitRequested) { // Thread must be sleeping in an ensure clause. Wake up the thread and allow ensure clause to complete info.Run(); return(self); } info.ExitRequested = true; RubyUtils.ExitThread(self); return(self); }
public static RubyArray /*!*/ List(object self) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); RubyThreadInfo[] threads = RubyThreadInfo.Threads; RubyArray result = new RubyArray(threads.Length); foreach (RubyThreadInfo threadInfo in threads) { Thread thread = threadInfo.Thread; if (thread != null) { result.Add(thread); } } return(result); }
public static Thread /*!*/ Join(Thread /*!*/ self) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); if (!(self.ThreadState == ThreadState.AbortRequested || self.ThreadState == ThreadState.Aborted)) { self.Join(); } Exception threadException = RubyThreadInfo.FromThread(self).Exception; if (threadException != null) { throw threadException; } return(self); }
public static MutableString /*!*/ Inspect(RubyContext /*!*/ context, Thread /*!*/ self) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); MutableString result = MutableString.CreateMutable(context.GetIdentifierEncoding()); result.Append("#<"); result.Append(context.GetClassDisplayName(self)); result.Append(':'); RubyUtils.AppendFormatHexObjectId(result, RubyUtils.GetObjectId(context, self)); result.Append(' '); RubyThreadStatus status = GetStatus(self); switch (status) { case RubyThreadStatus.Unstarted: result.Append("unstarted"); break; case RubyThreadStatus.Running: result.Append("run"); break; case RubyThreadStatus.Sleeping: result.Append("sleep"); break; case RubyThreadStatus.Aborting: result.Append("aborting"); break; case RubyThreadStatus.Completed: case RubyThreadStatus.Aborted: result.Append("dead"); break; } result.Append('>'); return(result); }
public static Thread /*!*/ CreateThread(RubyContext /*!*/ context, BlockParam startRoutine, object self, [NotNull] params object[] /*!*/ args) { if (startRoutine == null) { throw new ThreadError("must be called with a block"); } ThreadGroup group = Group(Thread.CurrentThread); Thread result = new Thread(new ThreadStart(delegate() { RubyThreadInfo info = RubyThreadInfo.FromThread(Thread.CurrentThread); info.Group = group; try { object threadResult; // TODO: break? startRoutine.Yield(args, out threadResult); info.Result = threadResult; #if !SILVERLIGHT } catch (ThreadInterruptedException) { // Do nothing with this for now #endif } catch (Exception e) { info.Exception = e; Utils.Log( e.Message + "\r\n\r\n" + e.StackTrace + "\r\n\r\n" + IListOps.Join(context, RubyExceptionData.GetInstance(e).Backtrace).ToString(), "THREAD" ); if (_globalAbortOnException || info.AbortOnException) { throw; } } })); result.Start(); return(result); }
public static object Status(Thread /*!*/ self) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); switch (self.ThreadState) { case ThreadState.WaitSleepJoin: return(MutableString.Create("sleep")); case ThreadState.Running: return(MutableString.Create("run")); case ThreadState.Aborted: case ThreadState.AbortRequested: return(null); case ThreadState.Stopped: case ThreadState.StopRequested: return(false); default: throw new ArgumentException("unknown thread status: " + self.ThreadState.ToString()); } }
public static Thread /*!*/ Join(Thread /*!*/ self, double seconds) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); if (!(self.ThreadState == ThreadState.AbortRequested || self.ThreadState == ThreadState.Aborted)) { double ms = seconds * 1000; int timeout = (ms <Int32.MinValue || ms> Int32.MaxValue) ? Timeout.Infinite : (int)ms; if (!self.Join(timeout)) { return(null); } } Exception threadException = RubyThreadInfo.FromThread(self).Exception; if (threadException != null) { throw threadException; } return(self); }
public static object Priority(Thread /*!*/ self) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); switch (self.Priority) { case ThreadPriority.Lowest: return(-2); case ThreadPriority.BelowNormal: return(-1); case ThreadPriority.Normal: return(0); case ThreadPriority.AboveNormal: return(1); case ThreadPriority.Highest: return(2); default: return(0); } }
public static object AbortOnException(Thread /*!*/ self) { RubyThreadInfo info = RubyThreadInfo.FromThread(self); return(info.AbortOnException); }
public static object Keys(RubyContext /*!*/ context, Thread /*!*/ self) { RubyThreadInfo info = RubyThreadInfo.FromThread(self); return(info.GetKeys()); }
public static bool IsAlive(Thread /*!*/ self) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); return(self.IsAlive); }
public static void Yield(object self) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); Thread.Sleep(0); }
public static ThreadGroup Group(Thread /*!*/ self) { RubyThreadInfo info = RubyThreadInfo.FromThread(self); return(info.Group); }
private static void RubyThreadStart(RubyContext /*!*/ context, BlockParam /*!*/ startRoutine, object[] /*!*/ args, ThreadGroup group) { RubyThreadInfo info = RubyThreadInfo.FromThread(Thread.CurrentThread); info.CreatedFromRuby = true; info.Group = group; try { object threadResult; // TODO: break/returns might throw LocalJumpError if the RFC that was created for startRoutine is not active anymore: if (startRoutine.Yield(args, out threadResult) && startRoutine.Returning(threadResult, out threadResult)) { info.Exception = new ThreadError("return can't jump across threads"); } info.Result = threadResult; } catch (MethodUnwinder) { info.Exception = new ThreadError("return can't jump across threads"); } catch (Exception e) { if (info.ExitRequested) { // Note that "e" may not be ThreadAbortException at this point If an exception was raised from a finally block, // we will get that here instead Utils.Log(String.Format("Thread {0} exited.", info.Thread.ManagedThreadId), "THREAD"); info.Result = false; #if !SILVERLIGHT Thread.ResetAbort(); #endif } else { e = RubyUtils.GetVisibleException(e); RubyExceptionData.ActiveExceptionHandled(e); info.Exception = e; StringBuilder trace = new StringBuilder(); trace.Append(e.Message); trace.AppendLine(); trace.AppendLine(); trace.Append(e.StackTrace); trace.AppendLine(); trace.AppendLine(); RubyExceptionData data = RubyExceptionData.GetInstance(e); if (data.Backtrace != null) { foreach (var frame in data.Backtrace) { trace.Append(frame.ToString()); } } Utils.Log(trace.ToString(), "THREAD"); if (_globalAbortOnException || info.AbortOnException) { throw; } } } finally { // Its not a good idea to terminate a thread which has set Thread.critical=true, but its hard to predict // which thread will be scheduled next, even with green threads. However, ConditionVariable.create_timer // in monitor.rb explicitly does "Thread.critical=true; other_thread.raise" before exiting, and expects // other_thread to be scheduled immediately. // To deal with such code, we release the critical monitor here if the current thread is holding it if (context.RubyOptions.Compatibility < RubyCompatibility.Ruby19 && context.CriticalThread == Thread.CurrentThread) { SetCritical(context, false); } } }
public static Thread /*!*/ Current(object self) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); return(Thread.CurrentThread); }
public static void Critical(RubyContext /*!*/ context, object self, bool value) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); SetCritical(context, value); }
[RubyMethod("critical", RubyMethodAttributes.PublicSingleton)] // Compatibility <= RubyCompatibility.Ruby18 public static bool Critical(RubyContext /*!*/ context, object self) { RubyThreadInfo.RegisterThread(Thread.CurrentThread); return(context.CriticalThread != null); }
public static object Value(Thread /*!*/ self) { Join(self); return(RubyThreadInfo.FromThread(self).Result); }
public static object HasKey(Thread /*!*/ self, [NotNull] RubySymbol /*!*/ key) { RubyThreadInfo info = RubyThreadInfo.FromThread(self); return(info.HasKey(key)); }