[comp.sys.mac.programmer] True lightweight threads for the Mac?

gilstrap@pooh_corner.sbc.com (Brian R. Gilstrap) (10/09/90)

Has anyone managed to get true lightweight threads going on the Mac?  What
I mean is that the C++ "task" library (which last I knew didn't work under the
MacOS anyway) doesn't cut it.  I'm looking for multiple threads of execution
within the same "address space" (which in the MacOS roughly corresponds to
"the same application heap(s)").

Barring that (and off the top of my head), is there anyone out there who
has thought much about using interrupts/VBL-stuff to force switching between
C++ "tasks".


Any other approach for solving this problem (other than "Wait for IAC") would
be greatly appreciated.

Thanks,
Brian R. Gilstrap
gilstrap@pooh_corner.sbc.com
gilstrap@swbatl.sbc.com
...!{texbell,uunet}!swbatl{!pooh_corner}!gilstrap

scotth@rocco.rocco.labs.tek.com (Scott Herzinger) (10/11/90)

In article <1990Oct9.161031.12927@swbatl.sbc.com> gilstrap@pooh_corner.sbc.com (Brian R. Gilstrap) writes:

   Has anyone managed to get true lightweight threads going on the Mac?  What
   I mean is that the C++ "task" library (which last I knew didn't work under the
   MacOS anyway) doesn't cut it.  I'm looking for multiple threads of execution
   within the same "address space" (which in the MacOS roughly corresponds to
   "the same application heap(s)").

But they do execute in the same address space. That is to say, on machines
where the AT&T C++ task library runs, the tasks run in the same addr space.

Maybe they don't cut it because the scheduler doesn't work the way you
want it, or the because of the baroque, non-intuitive design. At least,
those are the problems that I have with it.

Scott Herzinger   scotth%crl.labs.tek.com@relay.cs.net
                  Computer Research Lab, Tektronix, Inc.
                  PO Box 500 MS 50-662, Beaverton, OR 97077

peirce@outpost.UUCP (Michael Peirce) (10/11/90)

In article <1990Oct9.161031.12927@swbatl.sbc.com>, gilstrap@pooh_corner.sbc.com (Brian R. Gilstrap) writes:
> 
> Has anyone managed to get true lightweight threads going on the Mac?  What
> I mean is that the C++ "task" library (which last I knew didn't work under the
> MacOS anyway) doesn't cut it.  I'm looking for multiple threads of execution
> within the same "address space" (which in the MacOS roughly corresponds to
> "the same application heap(s)").
> 
> Barring that (and off the top of my head), is there anyone out there who
> has thought much about using interrupts/VBL-stuff to force switching between
> C++ "tasks".
> 
> 
> Any other approach for solving this problem (other than "Wait for IAC") would
> be greatly appreciated.

I doubt it would satisfy you, but I've found MacApp idlers to work
well as a mechanism for executing multiple "tasks" at one time.  You
do have to "cooperate", that is you have to give up control. But given
the right structuring, I've been able to create tasks to service incoming
requests.  I just create the idler object, tell it what to respond
to, and that's the last I bother with it.  It runs until completion
with as many other idlers as need be.

I'm not sure how IAC will help you...

-- michael


--  Michael Peirce         --   {apple,decwrl}!claris!outpost!peirce
--  Peirce Software        --   Suite 301, 719 Hibiscus Place
--  Macintosh Programming  --   San Jose, California 95117
--         and Consulting  --   (408) 244-6554

ts@cup.portal.com (Tim W Smith) (10/20/90)

I don't known about C++ threads (I've never seen them), but I'm
putting together a tasking library for the Mac.  I'm planning on
doing this as part of a generic application development library.

The basic idea is that you create tasks within your application.
Tasks run and sleep and all the usual things.  You do your user
interface by associating tasks with certain events.  For example,
you could create a task to handle updates for certain window,
and have this task sleep until an update event for that window.

You could handle commands by associating tasks with various
sets of menu selections.

You are allowed to force a task switch from an interrupt, so
you can do premptive stuff if that's the kind of stuff you
want to do.  You can also do semi-premptive stuff.  In
semi-premptive mode, an interrupt can cause a task switch
to an interrupt handling task, but when that task gives up
the CPU, you go back to the preempted task.

This really simplifies interrupt routines, because they have
a context and they can sleep while they wait for the next
interrupt.  This lets interrupt routines be written in a
much clearer fashion (I've used this approach in a couple
of real-time embedded systems, and it really helps development
and debugging).

I'm working in Think C.  The basic task switching stuff works
pretty well (task switch time is about 20 microseconds on a
Mac II).  I'm just getting started on all the high level stuff.
Unfortunately, things are real busy at work, and I've got some
other stuff at home that is higher priority, so I don't know when
this will get done, but when it does, I'll post the code.

A discussion on the net about how such a system should work could
be quite interesting.  I think using tasks to implement the user
interface will make it much easier to deal with the Mac interface.
What do the rest of you think?  What kind of things should a task
be able to sleep for?  Should it be able to sleep waiting for only
a single thing, or should it be able to specify some sort of list
of things it wants to wake up for?

By the way, one thing to watch out for if you create things with
their own stacks, is the stack sniffer.  This runs at vertical
retrace time, and if it finds the stack pointer is in the heap,
you get a bomb.  If you are allocating stack space for the tasks
in the heap, you've got a problem.

And you can't just divide the space between the end of the heap and
original application stack into a bunch of chunks and switch between
them.  At first, this might seem OK, as long as you leave enough room
for hardware interrupts on each stack.  However, according to DTS, the
toolbox thinks that it owns everything between the stack and the heap.
In particular, it feels free to use this for temporary storage, so it
is never safe to store anything there.

So, you have to disable the stack sniffer (you do this by changing a
low memory global).  However, there is still a problem.  Because the
tookbox expects to be able to use the space between the stack and the
heap as temporary space, it does not like the stack pointer to be in
the heap.

This means that before calling any Mac traps from a stack, you've got
to put the stack pointer back to something "reasonable", do the call,
and then put the stack pointer back to the stack for the task.  In other
words, you are going to end up implementing your own glue for every
trap.  Yuck!

						Tim Smith

ps: Oh, DTS says you are not supposed to do this sort of thing, so
furture compatibility is a risk.