Show thread.cs syntax highlighted
/* **********************************************************************************
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* This source code is subject to terms and conditions of the Shared Source License
* for IronPython. A copy of the license can be found in the License.html file
* at the root of this distribution. If you can not locate the Shared Source License
* for IronPython, please send an email to ironpy@microsoft.com.
* By using this source code in any fashion, you are agreeing to be bound by
* the terms of the Shared Source License for IronPython.
*
* You must not remove this notice, or any other, from this software.
*
* **********************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Threading;
using System.Diagnostics;
using IronPython.Runtime;
using IronPython.Runtime.Exceptions;
using IronPython.Runtime.Operations;
using IronPython.Runtime.Calls;
[assembly: PythonModule("thread", typeof(IronPython.Modules.PythonThread))]
namespace IronPython.Modules {
[PythonType("thread")]
public static class PythonThread {
#region Public API Surface
public static object LockType = Ops.GetDynamicTypeFromType(typeof(Lock));
public static object error = ExceptionConverter.CreatePythonException("error", "thread");
[Documentation("start_new_thread(function, [args, [kwDict]]) -> thread id\nCreates a new thread running the given function")]
[PythonName("start_new_thread")]
public static object StartNewThread(ICallerContext context, object function, object args, object kwDict) {
Tuple tupArgs = args as Tuple;
if (tupArgs == null) throw Ops.TypeError("2nd arg must be a tuple");
Thread t = new Thread(new ThreadObj(context, function, tupArgs, kwDict).Start);
t.Start();
return t.ManagedThreadId;
}
[Documentation("start_new_thread(function, [args, [kwDict]]) -> thread id\nCreates a new thread running the given function")]
[PythonName("start_new_thread")]
public static object StartNewThread(ICallerContext context, object function, object args) {
Tuple tupArgs = args as Tuple;
if (tupArgs == null) throw Ops.TypeError("2nd arg must be a tuple");
Thread t = new Thread(new ThreadObj(context, function, tupArgs, null).Start);
t.Start();
return t.ManagedThreadId;
}
[PythonName("interrupt_main")]
public static void InterruptMain() {
throw Ops.NotImplementedError("interrupt_main not implemented");
//throw new PythonKeyboardInterrupt();
}
[PythonName("exit")]
public static void Exit() {
throw new PythonSystemExitException();
}
[Documentation("allocate_lock() -> lock object\nAllocates a new lock object that can be used for synchronization")]
[PythonName("allocate_lock")]
public static object AllocateLock() {
return new Lock();
}
[PythonName("get_ident")]
public static object GetIdentity() {
return Thread.CurrentThread.ManagedThreadId;
}
// deprecated synonyms, wrappers over preferred names...
[Documentation("start_new(function, [args, [kwDict]]) -> thread id\nCreates a new thread running the given function")]
[PythonName("start_new")]
public static object StartNew(ICallerContext context, object function, object args) {
return StartNewThread(context, function, args);
}
[PythonName("exit_thread")]
public static void ExitThread() {
Exit();
}
[PythonName("allocate")]
public static object Allocate() {
return AllocateLock();
}
#endregion
[PythonType("lock")]
public class Lock {
AutoResetEvent blockEvent;
Thread curHolder;
[PythonName("acquire")]
public object Acquire() {
return (Acquire(Ops.TRUE));
}
[PythonName("acquire")]
public object Acquire(object waitflag) {
bool fWait = Ops.IsTrue(waitflag);
for (; ; ) {
if (Interlocked.CompareExchange<Thread>(ref curHolder, Thread.CurrentThread, null) == null) {
return Ops.TRUE;
}
if (!fWait) {
return Ops.FALSE;
}
if (blockEvent == null) {
// try again in case someone released us, checked the block
// event and discovered it was null so they didn't set it.
CreateBlockEvent();
continue;
}
blockEvent.WaitOne();
}
}
[PythonName("release")]
public void Release(params object[] param) {
Release();
}
[PythonName("release")]
public void Release() {
if (Interlocked.Exchange<Thread>(ref curHolder, null) == null) {
Ops.Raise(error, "lock isn't held", null);
}
if (blockEvent != null) {
// if this isn't set yet we race, it's handled in Acquire()
blockEvent.Set();
}
}
[PythonName("locked")]
public object IsLocked() {
return (Ops.Bool2Object(curHolder != null));
}
void CreateBlockEvent() {
AutoResetEvent are = new AutoResetEvent(false);
if (Interlocked.CompareExchange<AutoResetEvent>(ref blockEvent, are, null) != null) {
are.Close();
}
}
}
#region Internal Implementation details
private class ThreadObj {
object func, kwargs;
Tuple args;
ICallerContext context;
public ThreadObj(ICallerContext context, object function, Tuple args, object kwargs) {
Debug.Assert(args != null);
func = function;
this.kwargs = kwargs;
this.args = args;
this.context = context;
}
public void Start() {
try {
if (kwargs != null) {
Ops.CallWithArgsTupleAndKeywordDictAndContext(context, func, Ops.EMPTY, new string[0], args, kwargs);
} else {
Ops.CallWithArgsTuple(func, Ops.EMPTY, args);
}
} catch (PythonSystemExitException) {
// ignore and quit
} catch (Exception e) {
Ops.Print(context.SystemState, "Unhandled exception on thread");
object pythonEx = ExceptionConverter.ToPython(e);
bool dummy = false;
string result = Hosting.PythonEngine.FormatStackTraceNoDetail(e, null, ref dummy);
result += Hosting.PythonEngine.FormatPythonException(pythonEx);
Ops.Print(context.SystemState, result);
}
}
}
#endregion
}
}
See more files for this project here