// Copyright (c) Corporation for National Research Initiatives package org.python.modules.thread; import org.python.core.ClassDictInit; import org.python.core.FunctionThread; import org.python.core.Py; import org.python.core.PyException; import org.python.core.PyInteger; import org.python.core.PyObject; import org.python.core.PyString; import org.python.core.PyType; import org.python.core.PyTuple; public class thread implements ClassDictInit { private static volatile long stack_size = 0; // XXX - can we figure out the current stack size? private static ThreadGroup group = new ThreadGroup("jython-threads"); public static PyString __doc__ = new PyString( "This module provides primitive operations to write multi-threaded "+ "programs.\n" + "The 'threading' module provides a more convenient interface." ); public static void classDictInit(PyObject dict) { dict.__setitem__("LockType", PyType.fromClass(PyLock.class)); dict.__setitem__("_local", PyLocal.TYPE); dict.__setitem__("interruptAllThreads", null); } public static PyObject error = new PyString("thread.error"); public static void start_new_thread(PyObject func, PyTuple args) { Thread pt = _newFunctionThread(func, args); PyObject currentThread = func.__findattr__("__self__"); if (currentThread != null) { PyObject isDaemon = currentThread.__findattr__("isDaemon"); if (isDaemon != null && isDaemon.isCallable()) { PyObject po = isDaemon.__call__(); pt.setDaemon(po.__nonzero__()); } PyObject getName = currentThread.__findattr__("getName"); if (getName != null && getName.isCallable()) { PyObject pname = getName.__call__(); pt.setName(String.valueOf(pname)); } } pt.start(); } /** * Initializes a {@link FunctionThread}, using the configured stack_size and * registering the thread in the @link {@link #group} of threads spawned by * the thread module. * * Also used from the threading.py module. */ public static FunctionThread _newFunctionThread(PyObject func, PyTuple args) { return new FunctionThread(func, args.getArray(), stack_size, group); } /** * Interrupt all running threads spawned by the thread module. This works in conjunction with: * {@link org.python.core.PyTableCode#call}, which checks for the interrupted status of the * current thread, and {@link FunctionThread#run()}, which exits the current thread. */ public static void interruptAllThreads() { group.interrupt(); } public static PyLock allocate_lock() { return new PyLock(); } public static void exit() { exit_thread(); } public static void exit_thread() { throw new PyException(Py.SystemExit, new PyInteger(0)); } public static long get_ident() { return Thread.currentThread().getId(); } public static long stack_size(PyObject[] args) { switch (args.length) { case 0: return stack_size; case 1: long old_stack_size = stack_size; int proposed_stack_size = args[0].asInt(); if (proposed_stack_size != 0 && proposed_stack_size < 32768) { // as specified by Python, Java quietly ignores what // it considers are too small throw Py.ValueError("size not valid: " + proposed_stack_size + " bytes"); } stack_size = proposed_stack_size; return old_stack_size; default: throw Py.TypeError("stack_size() takes at most 1 argument (" + args.length + "given)"); } } }