module: threads-internal Synopsis: The implementation of the class Author: Tony Mann Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND define constant $low-priority = -1000; define constant $background-priority = -500; define constant $normal-priority = 0; define constant $interactive-priority = 500; define constant $high-priority = 1000; define sealed class () constant slot priority :: , init-value: $normal-priority, init-keyword: priority:; constant slot thread-name :: , init-value: #f, init-keyword: name:; constant slot function :: , required-init-keyword: function:; slot function-results :: = #[]; end class; define sealed class () end class; define method finalize (thread :: ) => () unless (primitive-destroy-thread(thread) == $success) error(make(, thread: thread)); end; end method; define function trampoline-function (thread :: ) => (result :: ) method () => () primitive-initialize-current-thread (thread, primitive-boolean-as-raw(instance?(thread, ))); internal-initialize-thread(); let (#rest results) = thread.function(); thread.function-results := as(, results); primitive-detach-thread (thread); end method; end; // Special-thread-function is a dummy function object. It's sole purpose // is to uniquely identify the very first thread at object initialization // time - to give the illusion that the first thread was created by this // library. // [actually, now it's also used for foreign threads] define function special-thread-function () => () end; define sealed method initialize (thr :: , #key) => () drain-finalization-queue(); next-method(); if (thr.function == special-thread-function) primitive-initialize-special-thread(thr); // This is the first thread else let res = primitive-make-thread(thr, thr.thread-name, thr.priority, thr.trampoline-function, primitive-boolean-as-raw (instance?(thr, ))); if (res ~= $success) let class = select (res) $creation-error => ; $priority-error => ; otherwise => ; end select; error(make(class, thread: thr)); end if; end if; finalize-when-unreachable(thr); end method; define function make-first-thread () => (thread :: ) make(, name: "Master thread", function: special-thread-function); end; define variable *master-thread* = #f; // Don't do this as part of the define variable init, because it's really // done for side effect. (e.g. it shouldn't be eliminated just because // the variable is unreferenced) *master-thread* := make-first-thread(); // make-foreign-thread may be called by the runtime system to // create a Dylan object, and initialize any Dylan thread-local // data, when a thread created by foreign code calls into Dylan for the // first time. // define function make-foreign-thread () => (thread :: ) let thread = make(, name: "Foreign thread", function: special-thread-function); internal-initialize-thread(); thread end; define function join-thread (thread1 :: , #rest more-threads) => (thread :: , #rest thread-values) let signal-join-error = method (res :: , thread) error(make(, thread: thread)) end method; let joined-thread = if (more-threads.empty?) // Join a single thread let res = primitive-thread-join-single(thread1); if (res == $success) thread1 else signal-join-error(res, thread1); end if; else // Join one of multiple threads let thread-vec = apply(vector, thread1, more-threads); let res = primitive-thread-join-multiple(thread-vec); if (instance?(res, )) res else signal-join-error(res, thread-vec); end if; end if; apply(values, joined-thread, joined-thread.function-results); end function join-thread; define function thread-yield () => () primitive-thread-yield(); end; define function current-thread () => (thread :: ) primitive-current-thread(); end; ///// Sleep define function sleep (secs :: ) => () primitive-sleep(secs.millisecs); end;