// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
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
public static double TIMEOUT_MAX = 0; // TODO: fill this with a proper value
[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;
}
///
/// 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");
}
}
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