/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* [email protected]. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using IronPython.Runtime;
using IronPython.Runtime.Exceptions;
using IronPython.Runtime.Operations;
using IronPython.Runtime.Types;
using Microsoft.Scripting;
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;
using SpecialName = System.Runtime.CompilerServices.SpecialNameAttribute;
[assembly: PythonModule("thread", typeof(IronPython.Modules.PythonThread))]
namespace IronPython.Modules {
public static class PythonThread {
public const string __doc__ = "Provides low level primitives for threading.";
private static readonly object _stackSizeKey = new object();
private static object _threadCountKey = new object();
[SpecialName]
public static void PerformModuleReload(PythonContext/*!*/ context, PythonDictionary/*!*/ dict) {
context.SetModuleState(_stackSizeKey, 0);
context.EnsureModuleException("threaderror", dict, "error", "thread");
}
#region Public API Surface
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
public static readonly PythonType LockType = DynamicHelpers.GetPythonTypeFromType(typeof(@lock));
[Documentation("start_new_thread(function, [args, [kwDict]]) -> thread id\nCreates a new thread running the given function")]
public static object start_new_thread(CodeContext/*!*/ context, object function, object args, object kwDict) {
PythonTuple tupArgs = args as PythonTuple;
if (tupArgs == null) throw PythonOps.TypeError("2nd arg must be a tuple");
Thread t = CreateThread(context, 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")]
public static object start_new_thread(CodeContext/*!*/ context, object function, object args) {
PythonTuple tupArgs = args as PythonTuple;
if (tupArgs == null) throw PythonOps.TypeError("2nd arg must be a tuple");
Thread t = CreateThread(context, new ThreadObj(context, function, tupArgs, null).Start);
t.IsBackground = true;
t.Start();
return t.ManagedThreadId;
}
#if !SILVERLIGHT && !WP75
///
/// Stops execution of Python or other .NET code on the main thread. If the thread is
/// blocked in native code the thread will be interrupted after it returns back to Python
/// or other .NET code.
///
public static void interrupt_main(CodeContext context) {
var thread = context.LanguageContext.MainThread;
if (thread != null) {
thread.Abort(new KeyboardInterruptException(""));
} else {
throw PythonOps.SystemError("no main thread has been registered");
}
}
#endif
public static void exit() {
PythonOps.SystemExit();
}
[Documentation("allocate_lock() -> lock object\nAllocates a new lock object that can be used for synchronization")]
public static object allocate_lock() {
return new @lock();
}
public static object get_ident() {
return Thread.CurrentThread.ManagedThreadId;
}
public static int stack_size(CodeContext/*!*/ context) {
return GetStackSize(context);
}
public static int stack_size(CodeContext/*!*/ context, int size) {
if (size < 32 * 1024 && size != 0) {
throw PythonOps.ValueError("size too small: {0}", size);
}
int oldSize = GetStackSize(context);
SetStackSize(context, size);
return oldSize;
}
// deprecated synonyms, wrappers over preferred names...
[Documentation("start_new(function, [args, [kwDict]]) -> thread id\nCreates a new thread running the given function")]
public static object start_new(CodeContext context, object function, object args) {
return start_new_thread(context, function, args);
}
public static void exit_thread() {
exit();
}
public static object allocate() {
return allocate_lock();
}
public static int _count(CodeContext context) {
return (int)context.LanguageContext.GetOrCreateModuleState