home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
Information
/
CSMP Digest
/
volume 3
/
csmp-digest-v3-035
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
UTF-8
Wrap
Text File
|
1995-06-07
|
72.0 KB
|
2,097 lines
|
[
TEXT/R*ch
]
Received-Date: Wed, 15 Jun 1994 15:34:00 +0200
From: pottier@clipper.ens.fr (Francois Pottier)
Subject: csmp-digest-v3-035
To: csmp-digest@ens.fr
Date: Wed, 15 Jun 1994 15:33:50 +0200 (MET DST)
X-Mailer: ELM [version 2.4 PL23]
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
Errors-To: listman@ens.fr
Reply-To: pottier@clipper.ens.fr
X-Sequence: 38
C.S.M.P. Digest Wed, 15 Jun 94 Volume 3 : Issue 35
Today's Topics:
"Magical" conversion from (char *) to Pascal string in C++
"New" bugs in 'develop' floating window code?
Detecting Universal Headers?
Enumerating messages from PowerTalk
MicroSeconds trap # and arguments?
Ok, where's my Quickdraw globals? (Help!)
Symantec C++ 7.0- any good?
Thread Mgr for blocking I-O
The Comp.Sys.Mac.Programmer Digest is moderated by Francois Pottier
(pottier@clipper.ens.fr).
The digest is a collection of article threads from the internet newsgroup
comp.sys.mac.programmer. It is designed for people who read c.s.m.p. semi-
regularly and want an archive of the discussions. If you don't know what a
newsgroup is, you probably don't have access to it. Ask your systems
administrator(s) for details. If you don't have access to news, you may
still be able to post messages to the group by using a mail server like
anon.penet.fi (mail help@anon.penet.fi for more information).
Each issue of the digest contains one or more sets of articles (called
threads), with each set corresponding to a 'discussion' of a particular
subject. The articles are not edited; all articles included in this digest
are in their original posted form (as received by our news server at
nef.ens.fr). Article threads are not added to the digest until the last
article added to the thread is at least two weeks old (this is to ensure that
the thread is dead before adding it to the digest). Article threads that
consist of only one message are generally not included in the digest.
The digest is officially distributed by two means, by email and ftp.
If you want to receive the digest by mail, send email to listserv@ens.fr
with no subject and one of the following commands as body:
help Sends you a summary of commands
subscribe csmp-digest Your Name Adds you to the mailing list
signoff csmp-digest Removes you from the list
Once you have subscribed, you will automatically receive each new
issue as it is created.
The official ftp info is //ftp.dartmouth.edu/pub/csmp-digest.
Questions related to the ftp site should be directed to
scott.silver@dartmouth.edu. Currently no previous volumes of the CSMP
digest are available there.
Also, the digests are available to WAIS users. To search back issues
with WAIS, use comp.sys.mac.programmer.src. With Mosaic, use
http://www.wais.com/wais-dbs/comp.sys.mac.programmer.html.
-------------------------------------------------------
>From oleg@ponder.csci.unt.edu (Kiselyov Oleg)
Subject: "Magical" conversion from (char *) to Pascal string in C++
Date: 31 May 1994 14:28:19 GMT
Organization: University of North Texas, Denton
There has been some discussion recently about conversion of a C string
to the Pascal string and correctly casting of the result.
I thought I'd throw in my couple of cents:
First, let's define the following class
class Pstr // Pascal String, this is just a type conversion
{
Str255 pas_string;
public:
Pstr(const char * c_str);
~Pstr(void) {}
operator unsigned char const * () { return pas_string; }
};
// Used to "implicitly" convert from C to
Pstr::Pstr(const char * c_str) // Pascal string
{
strncpy((char *)pas_string,c_str,sizeof(*this)-2);
CtoPstr((char *)pas_string);
}
After that, one can write smth like that
char * title = "some title";
this_window = NewWindow(nil,rect += window_offset,(Pstr)title,....etc)
It is THAT simple: just putting (Pstr) before a C string magically converts
it to a Pascal string and "does" correct casting, while keeping the original
C string intact.
The way I figure it, (Pstr)title should make an object of type Pstr
from 'title' by applying the Pstr::Pstr(const char * c_str)
constructor. Since NewWindow() requires a pascal string as its third
argument, the operator 'unsigned char const *' would apply, which
gives exactly what NewWindow() wants. And here how it actually works
(peeked from the object code generated by the Symantec C++ compiler):
the compiler allocates 256 bytes on stack, copies the C string in
there, calls CtoPstr(), and then pushes the address of that temporary
PASCAL string into stack for NewWindow(). After the NewWindow()
returns, the temporary space allocated for the Pascal string is
disposed of (by simply incrementing A7, mind you). To me, it looks
exactly as I wanted: conversion of a C string into the PASCAL one
without messing up the C string.
Here is more of the same idea:
class ScreenRect : public Rect
{
public:
ScreenRect(const Rect& rect) { *this = *(ScreenRect *)▭ }
ScreenRect(const rowcol& heightwidth);
~ScreenRect(void) {}
ScreenRect& operator += (const int offset);
operator Rect * (void) { return this; }
void print(const char * title = "") const;
};
// Create a rectangle of given height/width
// positioned at the origin
ScreenRect::ScreenRect(const rowcol& heightwidth)
{
left = top = 0;
bottom = heightwidth.row();
right = heightwidth.col();
}
// Shifting a rectangle by the same amount
// in X and Y
ScreenRect& ScreenRect::operator += (const int offset)
{
top += offset; bottom += offset; left += offset; right += offset;
return *this;
}
Then I can write
ScreenRect sub_horizon(q_bounds());
sub_horizon.print("sub horizon");
EraseRect(sub_horizon);
or, even crazier,
ScreenWindow::ScreenWindow(ScreenRect rect, const char * title)
{
const int window_offset = 100; // Cannot be 0 or small!
this_window = NewWindow(nil,rect += window_offset,(Pstr)title,...
}
So, all QuickDraw functions AUTOMATICALLY accept ScreenRect as if it
were Rect *.
This way, one can build C++ classes around all QuickDraw (and other
OS) data types, and one can still use original QuickDraw functions on
the new "objects". I've done just that for a few OS data types, I can
post it if there is some interest.
BTW, this all is perfectly legal C++ and would work everywhere. The
code snippets in this post are fragments of an actual working
program. It compiles with Symantec C++ versions 6.0, 6.0.1, and 7.0.
Oleg
P.S. I'm not a frequent reader of this newsgroup, please send any comments
to oleg@ponder.csci.unt.edu or oleg@unt.edu
+++++++++++++++++++++++++++
>From lassehp@imv.aau.dk (Lasse =?ISO-8859-1?Q?Hiller=F8e?= Petersen)
Date: 1 Jun 1994 13:59:08 GMT
Organization: Information & Media Science, Aarhus University, DENMARK
In article <2sfhi3$312@hermes.unt.edu>, oleg@ponder.csci.unt.edu (Kiselyov
Oleg) wrote:
> There has been some discussion recently about conversion of a C string
> to the Pascal string and correctly casting of the result.
> I thought I'd throw in my couple of cents:
>
> First, let's define the following class
>
> class Pstr // Pascal String, this is just a type conversion
> {
> Str255 pas_string;
> public:
> Pstr(const char * c_str);
> ~Pstr(void) {}
> operator unsigned char const * () { return pas_string; }
> };
> After that, one can write smth like that
>
> char * title = "some title";
> this_window = NewWindow(nil,rect += window_offset,(Pstr)title,....etc)
>
> It is THAT simple: just putting (Pstr) before a C string magically converts
> it to a Pascal string and "does" correct casting, while keeping the original
> C string intact.
>
A friend and I used this approach to implement a string class that worked
transparently with Pascal strings, while providing >255 character strings.
Basically, the character storage had a pascal length byte in front and a C
string terminating zero in the end. When casting to unsigned char*, the
length byte would be set to something <255, and all operations would check
for length byte <255 and drop a terminating zero at the end. This way, the
string object could be passed to pascal routines expecting (VAR
result:StrNNN) parameters, and the resulting pascal string (possibly not
correctly 0 terminated) would be usable.
Alas this broke when we switched from Symantec C++ to MetroWerks. We
haven't tried it with the latest release, though.
With Symantec C++, it worked great. No more C-String/Str255 hassles. Just
always use String. Period.
If there is any interest, I could post the source.
> P.S. I'm not a frequent reader of this newsgroup, please send any comments
> to oleg@ponder.csci.unt.edu or oleg@unt.edu
--
Lasse Hillerxe Petersen ! * \
Information & Media Science ! --- |
Erhus University ! / /
DENMARK !
---------------------------
>From egurney@vcd.hp.com (Eddy J. Gurney)
Subject: "New" bugs in 'develop' floating window code?
Date: Sat, 28 May 1994 22:10:09 GMT
Organization: Hewlett-Packard VCD
I recently incorporated Dean Yu's "WindowExtensions.c" library (article
in 'develop' issue 15, "Floating Windows: Keeping Afloat in the
Window Manager", code off issue 16 or newer do to some bug fixes)
into my application to give it floating window ability. Since then
I've pretty much had to abandon my plans to use floating windows
since Modeless Dialogs do not work correctly with floating windows
[IsDialogEvent()/DialogSelect() no longer work... wish I would have
known that _before_ I started... :-]
Anyway, I am interested in using the code in another app and found two
bugs while I was experimenting with it. Since I've seen some discussion
here in c.s.m.p on this code, I thought I'd ask if anyone has already
fixed these before I attempt to do it myself.
* First bug:
Open a new window, A. Open a new window, B. Hide window B and dispose of
window A. Now create a new window C. It does NOT get hilited, but it IS
active. I believe this is a bug in ShowReferencedWindow where it does
the following check:
windowBehind = GetNextWindow(windowToShow);
if (windowBehind == FrontNonFloatingWindow()) {
if (windowBehind != nil)
DeactivateWindow(windowBehind);
// Set the highlight state Set
WindowHilite(windowToShow, true);
}
this will only set windowToShow's hilite state to true if the window
immediately after the one being shown is the frontmost VISIBLE
non-floating window.
* Second bug:
Open a new window, A. Open a new window, B. Open a new window, C and
hide window B. Now show window B and hide window C. Now hide window
B, leaving only window A visible. Window A is NOT active and is NOT
hilited.
Checking WindowList shows the order C->B->A->0, and that window C is
active and hilited, even though it is not visible. (This same sequence
using ToolBox routines has WindowList order A->B->C->0). I believe this
is a bug in HideReferencedWindow where it says:
if (windowToHide == frontNonFloater) {
windowBehind = GetNextWindow(windowToHide);
if (windowBehind != nil) {
SetNextWindow(windowToHide, GetNextWindow(windowBehind));
SetNextWindow(windowBehind, windowToHide);
...
This assumes that 'windowBehind' (the next window in the window list
after the window being hidden) is visible.
It would be nice if these routines emulated the behavior of the system
ShowWindow/HideWindow; if anyone has already fixed these bugs or has
ideas on how to fix them so they act like the ToolBox, please let me
know. I'll post the "fixes" if/when I figure them out.
--
Eddy J. Gurney N8FPW Hewlett-Packard Company, Vancouver (USA!) Division
egurney@vcd.hp.com #include <standard-disclaimer.h>
"Failures are divided into two classes-- those who thought and never did,
and those who did and never thought." John Charles Salak
+++++++++++++++++++++++++++
>From Thomas Reed <reed@medicine.wustl.edu>
Date: 31 May 1994 14:14:46 GMT
Organization: Washington University
In article <CqJ9Kx.3zB@vcd.hp.com> Eddy J. Gurney, egurney@vcd.hp.com
writes:
>I recently incorporated Dean Yu's "WindowExtensions.c" library (article
>in 'develop' issue 15, "Floating Windows: Keeping Afloat in the
>Window Manager", code off issue 16 or newer do to some bug fixes)
>into my application to give it floating window ability.
On an aside, does anyone know if you can use this code to create a
floating window that will float over ALL windows at ALL times? i.e. -
even when other apps are in the front, the window will float over ALL
windows?
I know this is possible using some kind of calls from the new IM: Text,
but as I only have the old IMs, I can't use this too easily. I also
don't want to limit this capability to Sys 7.1 only. I'd like it to work
in previous versions of Sys 7.
Thanks!
-Thomas
=====================================================
Thomas Reed Washington University
Reed@telesphere.wustl.edu Medical School
(also: Reed@medicine.wustl.edu)
- ---------------------------------------------------
Clothes make the man. Naked people have little or no
influence on society. -- Mark Twain
=====================================================
Opinions posted are not the opinions of Wash. U.
+++++++++++++++++++++++++++
>From Jens Alfke <jens_alfke@powertalk.apple.com>
Date: Tue, 31 May 1994 19:17:35 GMT
Organization: Apple Computer
Thomas Reed, reed@medicine.wustl.edu writes:
> On an aside, does anyone know if you can use this code to create a
> floating window that will float over ALL windows at ALL times? i.e. -
> even when other apps are in the front, the window will float over ALL
> windows?
No. The only ways to do this are:
(A) Build some TSM (Text Services Manager) 'service' windows, which always
float. You need System 7.1 or later for this, since TSM is part of
WorldScript.
(B) Use the Layer Manager, which does exist, but was never made public, was
never extensively tested, and which the Toolbox people swear will finally
disappear next year with the Copland system release. A few 3rd parties did
manager to reverse engineer the API, but they'll definitely have some work to
do when Copland ships.
(C) Punch a hole out of the GrayRgn and patch the Window Manager to draw your
stuff in the hole when it needs updating. Also hook into the Event Manager to
grab mouse clicks in that part of the screen. Note that what you have is not
a window at all, just a hole in the screen, so you are responsible for
drawing the title bar and controls yourself. This is REALLY skanky and REALLY
complicated, but has been done by several shipping extensions.
Needless to say I'd recommend (A), even though I hear there are some weird
issues associated with running TSM windows. Donald Brown of CE Software wrote
a little demo app that does this for last years' MacHack; perhaps the source
code is around somewhere.
--Jens Alfke
jens_alfke@powertalk Rebel girl, rebel girl,
.apple.com Rebel girl you are the queen of my world
+++++++++++++++++++++++++++
>From Joe Francis <Joe.Francis@dartmouth.edu>
Date: 31 May 1994 19:38:09 GMT
Organization: Smooth Roo Software
Eddy J. Gurney, egurney@vcd.hp.com writes:
> * First bug:
> Open a new window, A. Open a new window, B. Hide window B and dispose of
> window A. Now create a new window C. It does NOT get hilited, but it IS
> active. [....]
> * Second bug:
> Open a new window, A. Open a new window, B. Open a new window, C and
> hide window B. Now show window B and hide window C. Now hide window
> B, leaving only window A visible. Window A is NOT active and is NOT
> hilited. [....]
Here are my versions of the related routines. These should fix the bugs
you saw. Please let me know if these cause any problems. I edited this
a little to make the wrappng work better for the post - I may have
introduced typos. Caveat Emptor. If this code fails, I will refund
your full purchase price. :-P
pascal void ShowReferencedWindow(WindowRef windowToShow)
{
WindowRef frontNonFloatingWindow;
ActivateHandlerUPP activateHandlerProc;
short windowClass;
Boolean windowIsInFront = false;
if (GetWindowVisible(windowToShow) != false)
return;
windowClass = GetWindowKind(windowToShow);
frontNonFloatingWindow = FrontNonFloatingWindow();
// If the window we are showing will become frontdoc, deactivate
// former frontdoc, and activate new one.
if (windowClass != kApplicationFloaterKind)
{
if (IsInFrontOf(windowToShow,frontNonFloatingWindow))
{
if (frontNonFloatingWindow)
DeactivateWindow(frontNonFloatingWindow);
SetWindowHilite(windowToShow, true);
windowIsInFront = true;
}
}
else
{
// A floating window is about to be shown.
// Make sure the windows in the window list
// are all in the right place.
ValidateWindowList();
// Check to see if a modal window is up
// before trying to highlight it.
frontNonFloatingWindow = FrontNonFloatingWindow();
if ((frontNonFloatingWindow != nil) &&
(frontNonFloatingWindow == (WindowRef) FrontWindow()) &&
(WindowIsModal(frontNonFloatingWindow)))
SetWindowHilite(windowToShow, false);
else
{
SetWindowHilite(windowToShow, true);
windowIsInFront = true;
}
}
// Show the window
ShowHide((WindowPtr) windowToShow, true);
// If this is the new frontmost document window
// or a floating window, send it an activate event
if (windowIsInFront)
{
activateHandlerProc = GetActivateHandlerProc(windowToShow);
if (activateHandlerProc != nil)
CallActivateHandlerProc(activateHandlerProc,
windowToShow, kActivateWindow);
}
}
pascal void HideReferencedWindow(WindowRef windowToHide)
{
WindowRef frontFloater;
WindowRef frontNonFloater;
// The original code here reorders windows in the window list
// to make hidden windows swap places with the window behind
// them if:
// a) they are either the frontmost floater or frontmost doc;
// b) there is a window of the same type behind them;
// c) that window behind is visible
// That didn't make a lot of sense to me, and it caused bugs,
// so I've scrapped it and taken a simpler approach.
// Don't do anything if the window is already invisible.
if (GetWindowVisible(windowToHide) == false)
return;
// Get the first visible floating window, if any.
frontFloater = (WindowRef) FrontWindow();
if (GetWindowKind(frontFloater) != kApplicationFloaterKind)
frontFloater = nil;
// Get the first visible document window, if any.
frontNonFloater = FrontNonFloatingWindow();
// Hide the window.
ShowHide((WindowPtr) windowToHide, false);
// if we are hiding the frontmost doc window, activate the next
// frontmost doc window, if any are visible.
if (windowToHide == frontNonFloater)
{
// now that we've hidden windowToHide, frontNonFloater will
// be different
frontNonFloater = FrontNonFloatingWindow();
if (frontNonFloater)
{
ActivateWindow(frontNonFloater);
}
}
}
Boolean IsInFrontOf(WindowRef win1, WindowRef win2)
{
WindowRef nextWindow = win1;
//nil windows are always behind other windows
if (!win1) return false;
//other windows are always ahead of nil windows
if (!win2) return true;
//ok, so the programmer asked me a dumb question
if (win1 == win2) return false;
while (nextWindow)
{
nextWindow = GetNextWindow(nextWindow);
if (nextWindow==win2) return true;
}
return false;
}
- ------------------------------------------------------------------------
Clap... Hop.... say "Kweepa".....
- ------------------------------------------------------------------------
+++++++++++++++++++++++++++
>From Joe Francis <Joe.Francis@dartmouth.edu>
Date: 31 May 1994 19:43:05 GMT
Organization: Smooth Roo Software
Thomas Reed, reed@medicine.wustl.edu writes:
> On an aside, does anyone know if you can use this code to create a
> floating window that will float over ALL windows at ALL times? i.e. -
> even when other apps are in the front, the window will float over ALL
> windows?
The "develop" floating windows code (by Dean Yu) acheives it's floating
by juggling windows around in the window list. The window list, though,
is process specific. Other applications windows are not in the window
list your app sees when it is in the forground. So the answer is no,
the develop code can not be used to do what you want.
- ------------------------------------------------------------------------
No matter how subtle the wizard, a knife between the shoulder blades
will seriously cramp his style.
- ------------------------------------------------------------------------
+++++++++++++++++++++++++++
>From mxmora@unix.sri.com (Matt Mora)
Date: 1 Jun 94 15:34:17 GMT
Organization: SRI International, Menlo Park, CA
In article <1994May31.191735.10959@gallant.apple.com> Jens Alfke <jens_alfke@powertalk.apple.com> writes:
>Thomas Reed, reed@medicine.wustl.edu writes:
>Needless to say I'd recommend (A), even though I hear there are some weird
>issues associated with running TSM windows. Donald Brown of CE Software wrote
>a little demo app that does this for last years' MacHack; perhaps the source
>code is around somewhere.
Matt Slot just posted some code to do the floating windows stuff to
a.s.m.
Xavier
--
___________________________________________________________
Matthew Xavier Mora Matt_Mora@sri.com
SRI International mxmora@unix.sri.com
333 Ravenswood Ave Menlo Park, CA. 94025
---------------------------
>From dubois@uakari.primate.wisc.edu (Paul DuBois)
Subject: Detecting Universal Headers?
Date: 13 May 1994 09:59:53 -0500
Organization: Castra Parvulorum
Is there a way I can tell whether the universal headers are being
used, e.g., to do this:
#if universalheaders
do this
#else
do this instead
#endif
--
Paul DuBois
dubois@primate.wisc.edu
+++++++++++++++++++++++++++
>From dmg@dcs.ed.ac.uk (Dominik Gamble)
Date: Mon, 16 May 1994 13:58:08 GMT
Organization: Department of Computer Science, University of Edinburgh
In article <2r04l9INN1r9@uakari.primate.wisc.edu>, dubois@uakari.primate.wisc.edu (Paul DuBois) writes:
> Is there a way I can tell whether the universal headers are being
> used, e.g., to do this:
>
> #if universalheaders
> do this
> #else
> do this instead
> #endif
As far as I know,
#ifdef USES68KINLINES
/* universal headers present */
#else
/* universal headers absent */
#endif
should work. (At least as far as you know you are compiling
for a 680x0).
+++++++++++++++++++++++++++
>From dean@genmagic.com (Dean Yu)
Date: 18 May 1994 18:01:57 GMT
Organization: General Magic, Inc.
In article <CpwEsx.4zz@dcs.ed.ac.uk>, dmg@dcs.ed.ac.uk (Dominik Gamble)
wrote:
> In article <2r04l9INN1r9@uakari.primate.wisc.edu>, dubois@uakari.primate.wisc.edu (Paul DuBois) writes:
> > Is there a way I can tell whether the universal headers are being
> > used, e.g., to do this:
> >
> > #if universalheaders
> > do this
> > #else
> > do this instead
> > #endif
>
> As far as I know,
>
> #ifdef USES68KINLINES
> /* universal headers present */
> #else
> /* universal headers absent */
> #endif
>
This will work for now, but USES68KINLINES was meant to mean that system
software prototypes are defined using inlined 680x0 instructions (like
A-Traps, and possible some register moving instructions). If Apple ever
moves the system over to shared libraries, then USES68KINLINES would be 0,
even though Universal headers might be present.
Oh, wait. You used #ifdef, not #if. Never mind.
At any rate, the Universal Headers comes with a file called
ConditionalMacros.h, which has all the compile time switches that makes the
headers universal. I can't remember if anything specifically about
universal headres was defined in there, but that's the place to look.
-- Dean Yu
Negative Ethnic Role Model
General Magic, Inc.
+++++++++++++++++++++++++++
>From tdevon@aol.com (TDevon)
Date: 30 May 1994 04:57:02 -0400
Organization: America Online, Inc. (1-800-827-6364)
In article <dean-180594105746@dean_yu.genmagic.com>,
dean@genmagic.com (Dean Yu) writes:
I've been using #ifdef's with 'USESROUTINEDESCRIPTORS' but you could
check for '__MIXEDMODE__' as well since that file only exists in the
Universal Headers. Such a shame that Apple went to all the work in
creating the Universal Headers and they didn't give us defined way to
detect whether they were present or not. slap, slap!
dEVoN
---------------------------
>From Adrian C Ruigrok <adrianr@wimsey.com>
Subject: Enumerating messages from PowerTalk
Date: 26 May 1994 23:12:13 GMT
Organization: Ruigrok Innovations Inc.
Has anyone figured out how to enumerate AOCE folder?
The documentation seems to imply that all you can do
is open a letter that was passed to you when someone
double clicked on it in the compound mailbox. You can
also get the next unread letter in the mailbox.
But how do you go back the the previous message. Or
even more involved, how could you show the user a list
of messages in the compound mailbox: Both the inbox and
the outbox.
It looks like the way to do it is with the LetterSpec, but
the docs say that structure is private and there are no
functions to help you create one.
Perhaps the answer is that you should not be creating a list
of letters, but to have to go back the the finder every time
to browse through your letters is tedious at best.
Adrian
+++++++++++++++++++++++++++
>From Steve Bryan <sbryan@maroon.tc.umn.edu>
Date: Fri, 27 May 1994 15:42:17 GMT
Organization: Sexton Software
In article <2s3acd$29d@wolfe.wimsey.com> Adrian C Ruigrok,
adrianr@wimsey.com writes:
>Perhaps the answer is that you should not be creating a list
>of letters, but to have to go back the the finder every time
>to browse through your letters is tedious at best.
That seems to be exactly what is intended by Mr. Sidhu. There was a lot
of flak on this particular topic some time back and I've heard no
indication that Apple has changed its position. Sorry I can't provide
useful information (try to hack the external file system?) except to say
that others have reached the same conclusion.
Steve Bryan sbryan@maroon.tc.umn.edu
Sexton Software CompuServe: 76545,527
Minneapolis, MN fax: (612) 929-1799
+++++++++++++++++++++++++++
>From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Date: 30 May 94 17:02:26 +1200
Organization: University of Waikato, Hamilton, New Zealand
In article <2s3acd$29d@wolfe.wimsey.com>, Adrian C Ruigrok <adrianr@wimsey.com> writes:
> Has anyone figured out how to enumerate AOCE folder?
>
> The documentation seems to imply that all you can do
> is open a letter that was passed to you when someone
> double clicked on it in the compound mailbox. You can
> also get the next unread letter in the mailbox.
>
> But how do you go back the the previous message. Or
> even more involved, how could you show the user a list
> of messages in the compound mailbox: Both the inbox and
> the outbox.
>
> It looks like the way to do it is with the LetterSpec, but
> the docs say that structure is private and there are no
> functions to help you create one.
>
> Perhaps the answer is that you should not be creating a list
> of letters, but to have to go back the the finder every time
> to browse through your letters is tedious at best.
I asked an Apple guy about this at WWDC (sorry, I didn't get his name).
He said there *is* a mail API that would allow you to do all this, but it
wasn't sufficiently tested for PowerTalk 1.0, which is why they didn't make
it public. He promised that they would do so in a future version.
In the meantime, you could try asking DTS if they'll give you information about
the unsupported API. I understand some vendors are already working with this.
Lawrence D'Oliveiro fone: +64-7-856-2889
Info & Tech Services Division fax: +64-7-838-4066
University of Waikato electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+12:00
+++++++++++++++++++++++++++
>From stevec@jolt.mpx.com.au (Stephen F Coy)
Date: 30 May 1994 10:46:04 GMT
Organization: Microplex Pty Ltd
Lawrence D'Oliveiro, Waikato University (ldo@waikato.ac.nz) wrote:
: In article <2s3acd$29d@wolfe.wimsey.com>, Adrian C Ruigrok <adrianr@wimsey.com> writes:
: > Has anyone figured out how to enumerate AOCE folder?
: >
: > The documentation seems to imply that all you can do
: > is open a letter that was passed to you when someone
: > double clicked on it in the compound mailbox. You can
: > also get the next unread letter in the mailbox.
: >
: > But how do you go back the the previous message. Or
: > even more involved, how could you show the user a list
: > of messages in the compound mailbox: Both the inbox and
: > the outbox.
: >
: > It looks like the way to do it is with the LetterSpec, but
: > the docs say that structure is private and there are no
: > functions to help you create one.
: >
: > Perhaps the answer is that you should not be creating a list
: > of letters, but to have to go back the the finder every time
: > to browse through your letters is tedious at best.
: I asked an Apple guy about this at WWDC (sorry, I didn't get his name).
: He said there *is* a mail API that would allow you to do all this, but it
: wasn't sufficiently tested for PowerTalk 1.0, which is why they didn't make
: it public. He promised that they would do so in a future version.
: In the meantime, you could try asking DTS if they'll give you information about
: the unsupported API. I understand some vendors are already working with this.
I also have heard the same story. However, I have "discovered" that the
in tray can be enumerated at a low level using the IPM calls. The queue
to access is called In_Tray or something (I can't remember the exact
name, the code is at work and I'm at home at present). You can read mail
this way, but you can't mark it as read, or tell whether it was read
before. Also, the mail MUST be present on the local machine. If it is on
a server, you will have to discover the queue name and address for yourself!
In the meantime, we have an oustanding DTS request for the private API.
Unfortunately, I expect this to be subject to an NDA :(
If anyone needs more details on the above I can probably post it from
work tomorrow.
- ---
Steve Coy
Resolve Software (WA) Pty Ltd
+++++++++++++++++++++++++++
>From Jens Alfke <jens_alfke@powertalk.apple.com>
Date: Tue, 31 May 1994 19:24:17 GMT
Organization: Apple Computer
Lawrence D'Oliveiro, ldo@waikato.ac.nz writes:
> I asked an Apple guy about this at WWDC (sorry, I didn't get his name).
> He said there *is* a mail API that would allow you to do all this, but it
> wasn't sufficiently tested for PowerTalk 1.0, which is why they didn't make
> it public. He promised that they would do so in a future version.
>
> In the meantime, you could try asking DTS if they'll give you information
about
> the unsupported API. I understand some vendors are already working with
this.
Beyond's "PowerRules" provides a suite of events for accessing the In Tray.
You can enumerate the letters, examine info like senders or date sent, all
from Apple events. This implies that they're using this private API, and also
that other apps could get this functionality by talking to PowerRules.
Unfortunately I have to say that the version I used (1.0D, I think) was
really buggy. Their Apple Event support seems flaky in the extreme, and it
was only with difficulty that I could get anything to work; even then, most
of the time it either ignored incoming mail or returned mysterious error
codes when running my agent scripts. If they could only make the thing more
solid it'd be terrific.
--Jens Alfke
jens_alfke@powertalk Rebel girl, rebel girl,
.apple.com Rebel girl you are the queen of my world
---------------------------
>From hoyer@cc.Helsinki.FI (Paul Hoyer)
Subject: MicroSeconds trap # and arguments?
Date: 25 May 1994 22:43:14 +0300
Organization: University of Helsinki
I know there was a thread a while ago concerning the MicroSeconds trap,
but I didn't follow c.s.m.p closely enough then... So sorry if I'm
asking for information I might have got from that thread!
I'd like to use the MicroSeconds() trap to measure the speed of my code,
but since Think C v5.0 doesn't seem to know about the trap I need the
trap number and how to call if from assembly. I assume the trap is
implemented in Sys. 7.1?
It's probably documented in IM-6 somewhere, but since I don't own it
(I'm just a poor student), I'd appreciate it if somebody could simply
e-mail me the info.
Thanks in advance!!!
-P. Hoyer <hoyer@cc.helsinki.fi>
+++++++++++++++++++++++++++
>From olmsted@cs.ucdavis.edu (Bret Olmsted)
Date: Wed, 25 May 1994 20:15:23 GMT
Organization: University of California, Davis
Paul Hoyer (hoyer@cc.Helsinki.FI) wrote:
: I'd like to use the MicroSeconds() trap to measure the speed of my code,
: but since Think C v5.0 doesn't seem to know about the trap I need the
: trap number and how to call if from assembly. I assume the trap is
: implemented in Sys. 7.1?
Here is some code that does just the job:
TMTask task;
static void start_timer(void) /* Start measuring elapsed time. */
{
task.qLink = NULL;
task.qType = 0;
task.tmAddr = 0;
task.tmCount = 0;
InsTime((QElemPtr) &task);
PrimeTime((QElemPtr) &task, 0x80000000);
}
static long stop_timer(void) /* Stop measuring elapsed time. */
{
RmvTime((QElemPtr) &task);
return task.tmCount - 0x80000000; /* return time elapsed. */
}
Hope that helps.
Bret Olmsted
olmsted@cs.ucdavis.edu
u
+++++++++++++++++++++++++++
>From ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
Date: 31 May 94 10:36:01 +1200
Organization: University of Waikato, Hamilton, New Zealand
In article <2s09oi$4ga@kruuna.Helsinki.FI>, hoyer@cc.Helsinki.FI (Paul Hoyer) writes:
>
> I'd like to use the MicroSeconds() trap to measure the speed of my code,
> but since Think C v5.0 doesn't seem to know about the trap I need the
> trap number and how to call if from assembly. I assume the trap is
> implemented in Sys. 7.1?
>
> It's probably documented in IM-6 somewhere...
No, it's not. It first turned up in some Sound Manager 3.0 sample code, and
I gather it has since worked its way into Apple's standard interfaces. Here's
one way you can call it:
PROCEDURE MicroSeconds64
(
VAR Result : Comp
);
(* returns the full 64 bits of a microsecond clock. *)
CODE
0A193H, (* _MicroSeconds *)
0225FH, (* move.l (sp)+, a1 *)
022C8H, (* move.l a0, (a1)+ *)
022C0H; (* move.l d0, (a1)+ *)
Lawrence D'Oliveiro fone: +64-7-856-2889
Info & Tech Services Division fax: +64-7-838-4066
University of Waikato electric mail: ldo@waikato.ac.nz
Hamilton, New Zealand 37^ 47' 26" S, 175^ 19' 7" E, GMT+12:00
+++++++++++++++++++++++++++
>From sobiloff (Blake Sobiloff)
Date: Tue, 31 May 1994 11:36:26 -0400
Organization: Lab for Automation Psychology
In article <1994May31.103601.29104@waikato.ac.nz>, ldo@waikato.ac.nz
(Lawrence D'Oliveiro, Waikato University) wrote:
> No, it's not. It first turned up in some Sound Manager 3.0 sample code, and
> I gather it has since worked its way into Apple's standard interfaces. Here's
> one way you can call it:
[...]
Or, if you have the Universal Headers, its trap is included in <Traps.h>.
--
Blake Sobiloff <sobiloff@mail.lap.umd.edu> | University of Maryland
Laboratory for Automation Psychology | College Park, MD 20742-4411
Department of Psychology | 301/405-5936 (Voice)
Ayrton Senna de Silva, RIP. (May 1, 1994)
+++++++++++++++++++++++++++
>From afcjlloyd@aol.com (AFC JLloyd)
Date: 31 May 1994 18:36:01 -0400
Organization: America Online, Inc. (1-800-827-6364)
In article <sobiloff-310594113627@dataranch.lap.umd.edu>, sobiloff
(Blake Sobiloff) writes:
>In article <1994May31.103601.29104@waikato.ac.nz>, ldo@waikato.ac.nz
>(Lawrence D'Oliveiro, Waikato University) wrote:
>
>> No, it's not. It first turned up in some Sound Manager 3.0 sample
code, and
>> I gather it has since worked its way into Apple's standard
interfaces. Here's
>> one way you can call it:
>[...]
>
>Or, if you have the Universal Headers, its trap is included in
<Traps.h>.
Or even better, if you have the Universal Headers it is defined in
<Timer.h>:
extern pascal void Microseconds(UnsignedWide *microTickCount)
FOURWORDINLINE(0xA193, 0x225F, 0x22C8, 0x2280);
I have done some experimenting with this trap today and noticed that
it seems to be true microseconds. From various documentation that I
have seen the Time Manager is based on a VIA timer that operates at
783360 hz, but the values returned by Microseconds are clearly much
closer to 1000000 hz. Perhaps this has been mentioned earlier in
this thread and I missed it, but I assume this trap is not supported
on all configurations of hardware/software. I believe it was
mentioned earlier that QuickTime relies on this trap. Can I assume
that any configuration of hardware/software that supports QuickTime
will support this trap?
Jim Lloyd
afcjlloyd@aol.com
+++++++++++++++++++++++++++
>From dean@genmagic.com (Dean Yu)
Date: 1 Jun 1994 03:16:08 GMT
Organization: General Magic, Inc.
In article <1994May31.103601.29104@waikato.ac.nz>, ldo@waikato.ac.nz
(Lawrence D'Oliveiro, Waikato University) wrote:
> In article <2s09oi$4ga@kruuna.Helsinki.FI>, hoyer@cc.Helsinki.FI (Paul Hoyer) writes:
> >
> > I'd like to use the MicroSeconds() trap to measure the speed of my code,
> > but since Think C v5.0 doesn't seem to know about the trap I need the
> > trap number and how to call if from assembly. I assume the trap is
> > implemented in Sys. 7.1?
> >
> > It's probably documented in IM-6 somewhere...
>
> No, it's not. It first turned up in some Sound Manager 3.0 sample code, and
> I gather it has since worked its way into Apple's standard interfaces. Here's
> one way you can call it:
Actually, I believe it first came out with QuickTime. I seem to recall
fixing a bug in 7.1 where the value returned by Microseconds would drift
after a while, so it's been around for at least that long. Whether it's
been public since then is a different story...
-- Dean Yu
Negative Ethnic Role Model
General Magic, Inc.
---------------------------
>From st917wbh@dunx1.ocs.drexel.edu (M. Scott Smith)
Subject: Ok, where's my Quickdraw globals? (Help!)
Date: Sat, 21 May 1994 06:01:36 GMT
Organization: Drexel University
We just got our copy of CodeWarrior Gold today, and I've been feverishly
working to port a few thousand lines of C++ code from Symantec C++.
For the most part, converting to the PPC seems to have been easy. I was
able to get everything to compile and link after some fooling around.
But I'm having a problem, and I'm familiar with it, and know it's been
raised before, but never paid too much attention.
I specifically use some QuickDraw globals such as "thePort" and
"screenBits." That's never been a problem with Symantec C++.
But CodeWarrior doesn't like them.
I note the following structure (defined in good ol' Quickdraw.h):
- --
struct QDGlobals {
char privates[76];
long randSeed;
BitMap screenBits;
Cursor arrow;
Pattern dkGray;
Pattern ltGray;
Pattern gray;
Pattern black;
Pattern white;
GrafPtr thePort;
};
#if defined(powerc) || defined(__powerc)
#pragma options align=reset
#endif
typedef struct QDGlobals QDGlobals;
- --
Obviously, this is what I'm looking for. First question: is this the
method we're supposed to use now to get at things such as thePort?
And the most important question: HOW DO I FILL THIS STRUCTURE? I'm
assuming there must be an easy way; I can't find it, and I can't find any
useful mention of it in docs anywhere.
I feel like I've been sleeping and missed the boat on this one.
I know some yechy ways of getting at screenBits and thePort, but would like
to avoid that, since I'm assuming there's a much easier way.
Any help would be appreciated.
Other than that, so far I'm pleased with CodeWarrior. Neat About
boxes. :) I'd have to echo another poster's comments on the docs, though:
I hate Apple's DocViewer. I love Think Reference.
Also, the editor seems sluggish. I assume this is because of its added
"functionality" such as colorizing different types of text. (Then again,
I'm running on an old, slow IIfx.. Sigh.)
Thanks in advance for (prompt) help.. I'd like to get this thing ported by
Sunday for an Open House we're having.
- Scott
- -
M. Scott Smith (umsmith@mcs.drexel.edu)
Math and Computer Science, Drexel University
Mac developer. Student. Ski bum. (But all the snow melted.. Sniff.)
+++++++++++++++++++++++++++
>From dan694356@aol.com (Dan 694356)
Date: 21 May 1994 03:03:14 -0400
Organization: America Online, Inc. (1-800-827-6364)
You need to allocate storage for qd...
#ifdef powerc
QDGlobals qd;
#endif
... somewhere in your code, it's not in the PPC libraries (don't know
why, Apple just left it out). If you've gotten used to doing just
'thePort' or 'screenBits' rather than 'qd.thePort' and
'qd.screenBits', now's as good a time as any to get out of that
habit, since it doesn't work in the new compilers either. :-)
- Dan
+++++++++++++++++++++++++++
>From mwron@aol.com (MW Ron)
Date: 21 May 1994 12:22:14 -0400
Organization: America Online, Inc. (1-800-827-6364)
In article <Cq522o.CKz@Dunx1.OCS.Drexel.Edu>,
st917wbh@dunx1.ocs.drexel.edu (M. Scott Smith) writes:
>> I specifically use some QuickDraw globals such as "thePort" and
"screenBits." That's never been a problem with Symantec C++.
This is not a Symantec vs CW item, it is a change Apple made to
minimaze global namespace cluttering. A few years ago Apple decided
to encapsulate the variables called the QuickDraw globals that are
referenced from A5 and include thePort and screenBits in a structure
called qd. You can find them listed in the QuickDraw.h header file.
This new way also allows the compiler to handle quickdraw globals
without any special code on non-68k Macs.
To access your global QuickDraw Variables, simply use
qd.<variableName> to access them as a structure member.
Ron Liechty
mwron@aol.com
Metrowerks Inc.
+++++++++++++++++++++++++++
>From mxmora@unix.sri.com (Matt Mora)
Date: 23 May 1994 10:30:07 -0700
Organization: SRI International, Menlo Park, CA
In article <Cq522o.CKz@Dunx1.OCS.Drexel.Edu> st917wbh@dunx1.ocs.drexel.edu (M. Scott Smith) writes:
> We just got our copy of CodeWarrior Gold today, and I've been feverishly
>working to port a few thousand lines of C++ code from Symantec C++.
>
> For the most part, converting to the PPC seems to have been easy. I was
>able to get everything to compile and link after some fooling around.
>
> But I'm having a problem, and I'm familiar with it, and know it's been
>raised before, but never paid too much attention.
>
> I specifically use some QuickDraw globals such as "thePort" and
>"screenBits." That's never been a problem with Symantec C++.
>struct QDGlobals {
You need to add
QDGlobals qd;
to your code to create the global variable. the you call InitGraf
passing the global &qd.thePort to Initgraf.
Xavier
--
___________________________________________________________
Matthew Xavier Mora Matt_Mora@sri.com
SRI International mxmora@unix.sri.com
333 Ravenswood Ave Menlo Park, CA. 94025
+++++++++++++++++++++++++++
>From Jens Alfke <jens_alfke@powertalk.apple.com>
Date: Thu, 26 May 1994 22:43:37 GMT
Organization: Apple Computer
Matt Mora, mxmora@unix.sri.com writes:
> You need to add
> QDGlobals qd;
> to your code to create the global variable. the you call InitGraf
> passing the global &qd.thePort to Initgraf.
Huh? In CodeWarrior? I've never needed to do this. As far as I can tell, qd
is automatic; it's defined in the runtime library or somewhere like that.
--Jens Alfke
jens_alfke@powertalk Rebel girl, rebel girl,
.apple.com Rebel girl you are the queen of my world
+++++++++++++++++++++++++++
>From paulw@crl.com (Paul Winterrowd)
Date: 27 May 1994 09:32:12 -0700
Organization: CRL Dialup Internet Access (415) 705-6060 [login: guest]
Jens Alfke (jens_alfke@powertalk.apple.com) wrote:
: Matt Mora, mxmora@unix.sri.com writes:
: > You need to add
: > QDGlobals qd;
: > to your code to create the global variable. the you call InitGraf
: > passing the global &qd.thePort to Initgraf.
: Huh? In CodeWarrior? I've never needed to do this. As far as I can tell, qd
: is automatic; it's defined in the runtime library or somewhere like that.
: --Jens Alfke
: jens_alfke@powertalk Rebel girl, rebel girl,
: .apple.com Rebel girl you are the queen of my world
Check out the file MacHeaderPPC (or MacHeader68K if you are compiling 68k code)
and I believe that's where it is defined. The really nice part about it is
you can change the precompiled header!
paulw@crl.com
--
- ---------------------------------------------------------------
I only speak for myself.
+++++++++++++++++++++++++++
>From bell@apple.com (Mike Bell)
Date: Tue, 31 May 1994 18:09:32 GMT
Organization: Apple Computer, Inc.
In article <2s57ac$eap@crl.crl.com>, paulw@crl.com (Paul Winterrowd) writes:
> Path: gallant.apple.com!murky.apple.com!apple.com!olivea!decwrl!nntp.
> crl.com!crl.crl.com!not-for-mail From: paulw@crl.com (Paul Winterrowd)
> Newsgroups: comp.sys.mac.programmer
> Subject: Re: Ok, where's my Quickdraw globals? (Help!)
> Date: 27 May 1994 09:32:12 -0700
> Organization: CRL Dialup Internet Access (415) 705-6060 [login:
> guest] Lines: 23
> Message-ID: <2s57ac$eap@crl.crl.com>
> References: <Cq522o.CKz@Dunx1.OCS.Drexel.Edu> <2rqp6v$1oe@unix.sri.
> com> <1994May26.224337.8856@gallant.apple.com> NNTP-Posting-Host: crl.
> com
> X-Newsreader: TIN [version 1.2 PL2]
>
> Jens Alfke (jens_alfke@powertalk.apple.com) wrote:
> : Matt Mora, mxmora@unix.sri.com writes:
> : > You need to add
> : > QDGlobals qd;
> : > to your code to create the global variable. the you call
> InitGraf : > passing the global &qd.thePort to Initgraf.
>
> : Huh? In CodeWarrior? I've never needed to do this. As far as I can
> tell, qd : is automatic; it's defined in the runtime library or
> somewhere like that.
>
> : --Jens Alfke
> : jens_alfke@powertalk Rebel girl, rebel girl,
> : .apple.com Rebel girl you are the queen of
> my world
>
> Check out the file MacHeaderPPC (or MacHeader68K if you are
> compiling 68k code) and I believe that's where it is defined. The
> really nice part about it is you can change the precompiled header!
>
> paulw@crl.com
> --
> -----------------------------------------------------------------
> I only speak for myself.
>
>
As Matt mentioned, you need to define your own QuickDraw globals if you are
using the Apple PowerMacintosh development tools. The CodeWarrior stuff
defines it for you, but this is build system dependent.
-Mike
---------------------------
>From timmyd@netcom.com (Tim DeBenedictis)
Subject: Symantec C++ 7.0- any good?
Date: Sun, 29 May 1994 18:04:06 GMT
Organization: NETCOM On-line Communication Services (408 261-4700 guest)
I'm trying to decide between upgrading from THINK C 5.0.4 to Symantec C++
7.0 or CodeWarrior. Given that I've got a lot of code committed to THINK/
Symantec, is it worth switching to MetroWerks? I've heard that Sym C++ 6.0
was so buggy as to be practically useless. Is 7.0 decent? Also, can I
compile native PPC apps with Symantec? (I don't have a PPC yet, but I
may in the not so distant future.) I also don't want to give up 50
megs of hard drive space to a compiler... which package is smaller?
Any comments greatly appreciated,
Tim DeBenedictis
PS please send e-mail, since I don't read this group often.
+++++++++++++++++++++++++++
>From nick@pitt.edu ( nick.c )
Date: Mon, 30 May 94 12:29:40 GMT
Organization: University of Pittsburgh
In Article <timmydCqKsuv.6vw@netcom.com>, timmyd@netcom.com (Tim
DeBenedictis) wrote:
>I'm trying to decide between upgrading from THINK C 5.0.4 to Symantec C++
>7.0 or CodeWarrior. Given that I've got a lot of code committed to THINK/
>Symantec, is it worth switching to MetroWerks? I've heard that Sym C++ 6.0
>was so buggy as to be practically useless. Is 7.0 decent? Also, can I
>compile native PPC apps with Symantec? (I don't have a PPC yet, but I
>may in the not so distant future.) I also don't want to give up 50
>megs of hard drive space to a compiler... which package is smaller?
I haven't tried CodeWarrior yet (have thought about it), but
SC++ 7.02 seems pretty stable to me. Here's some info I think
is important:
- SC++ takes up about 17 MB HD space (full installation + 7.02 updated),
while CodeWarrior takes up 6 MB for C/C++ (with another 8 MB for
class library: total 14 MB) - ie both seem to be about the same.
- With SC++ you have to pay extra to get a "cross platform" kit
from symantec - and I'm not really clear if this includes a PPC
compiler. I don't think it does. CodeWarrior gold includes
a PPC compiler and runs native. No version of SC++ runs native yet.
- If your code doesn't use TCL it should be portable to CodeWarrrior.
- MetroWerks seems to have the best customer support. They don't
charge you for it (Symantec does after 30 days or so), they give you
three free updates (Symantec has started something like this, but
again you have to subscrivbe - ie pay - for it), and their guys
seem to pay more attention to this newsgroup (no slight intended
to those folks from symantec who are here).
- CodeWarrior is only available on CD. For me this is a plus (I like
CD's) - but if you don't have a drive yet this will be an issue.
- TPM w/out VA can run in about 2.5 MB of ram. I don't know how much
CodeWarrior wants.
- Both are compatible with other development tools like Think Reference
(a must have in my book), Object Master (something I'm really
getting addicted to), Alpha or BBedit, etc.
- There is an established base of literature and example code out there
specific for symantec. (eg. Dave Mark's Books, Sydow's Book,
and guestimate >70% of shareware was written with Symantec's stuff).
I'm kind of new to all this (been at it about a year), so for me the
last point is pretty important. CodeWarrior is coming on strong,
and I don't doubt that in another year there will be a wealth of
software and literature out there written in/for CodeWarrior.
For now, I'm going to stick with Symantec, and if other folks are
just getting started I'd recommend same. If you're familiar with
the toolbox, have C or C++ down, and are generally a mature developer
CodeWarrior seems to be the best deal. I figure by the time I get
there I'll be able to switch over fairly easy, or perhaps Symantec
will come back strong with a packaged PPC compiler, a native
environment, maybe a faster compiler, and (on my wish list) better
documentation of TCL (sorry guys - I still can't make heads or
tails out of it... still trying). Anyway, hope the info helps and
take the opinions with a grain of salt - both are good products.
-- nick
BTW - has someone put together a SC++ vs CodeWarrior FAQ yet? Seems
like we need one...
_/ _/ _/ _/_/_/ _/ _/ Sea Shells to C shells, Waikiki to
_/_/ _/ _/ _/ _/ _/_/_/ the Internet, a wave, is a wave...
_/ _/_/ _/ _/ _/ _/
_/ _/ _/ _/_/_/ _/ _/ CompSrv: 71232,766 I-Net: Nick@pitt.edu
---------------------------
>From rmah@panix.com (Robert S. Mah)
Subject: Thread Mgr for blocking I-O
Date: Sat, 21 May 1994 03:14:19 -0500
Organization: One Step Beyond
I'm currently experimenting with the Thread Mgr to implement blocking I/O
as per the examples in develop 17. I'm doing this with MacTCP 2.0.x and
was wondering if anyone else has tried this.
For example, while the article recomends putting the I/O thread to sleep,
and using a wake up thread which is triggered by the completion routine,
I was wondering how much less efficient a simpler solutio would be.
That is, instead of...
I/O Thread
Create WakeUp thread in stopped state
Async call with completion routine
Sleep this thread
Handle results
WakeUp Thread
Wakeup the I/O thread
Completion Routine
Wakeup the WakeUp thread
How about...
I/O Thread
Async call without completion routine
while ioResult not done
Yield
Handle results
So, while the I/O thread is always running, and does not sleep, thereby
hogging resources, does this incur _that_ much overhead? I have a
suspician that this would be more efficient than calling WaitNextEvent
(i.e. in a single threaded app) instead of Yield. Or would it?
Cheers,
Rob
___________________________________________________________________________
Robert S. Mah -=- One Step Beyond -=- 212-947-6507 -=- rmah@panix.com
+++++++++++++++++++++++++++
>From stevec@jolt.mpx.com.au (Stephen F Coy)
Date: 22 May 1994 02:06:41 GMT
Organization: Microplex Pty Ltd
Robert S. Mah (rmah@panix.com) wrote:
: I'm currently experimenting with the Thread Mgr to implement blocking I/O
: as per the examples in develop 17. I'm doing this with MacTCP 2.0.x and
: was wondering if anyone else has tried this.
: For example, while the article recomends putting the I/O thread to sleep,
: and using a wake up thread which is triggered by the completion routine,
: I was wondering how much less efficient a simpler solutio would be.
: That is, instead of...
: I/O Thread
: Create WakeUp thread in stopped state
: Async call with completion routine
: Sleep this thread
: Handle results
: WakeUp Thread
: Wakeup the I/O thread
: Completion Routine
: Wakeup the WakeUp thread
: How about...
: I/O Thread
: Async call without completion routine
: while ioResult not done
: Yield
: Handle results
: So, while the I/O thread is always running, and does not sleep, thereby
: hogging resources, does this incur _that_ much overhead? I have a
: suspician that this would be more efficient than calling WaitNextEvent
: (i.e. in a single threaded app) instead of Yield. Or would it?
I have been using the second method you described above for some time
now, both with the original threads package and the new stuff. Sure, you
get a lot of thread swapping, but this is pretty cheap these days.
The technique described in Develop seems like a lot of trouble to me. I
would love to see someone justify it. (That is, I want to know the
technical reasons why it should be done that way.)
: Cheers,
: Rob
: ___________________________________________________________________________
: Robert S. Mah -=- One Step Beyond -=- 212-947-6507 -=- rmah@panix.com
Steve Coy
Resolve Software (WA) Pty Ltd
+++++++++++++++++++++++++++
>From qmot@cs.mcgill.ca (Thomas PUSHPATHADAM)
Date: 22 May 1994 08:33:37 GMT
Organization: SOCS, McGill University, Montreal, Canada
Path: NewsWatcher!user
Date: Sun, 22 May 1994 04:16:58 -0400
From: paul@architecture.mcgill.ca (Paul Lalonde)
Newsgroups: comp.sys.mac.programmer
Followup-To: comp.sys.mac.programmer
Subject: Re: Thread Mgr for blocking I/O
Message-ID: <paul-220594041658@132.206.27.50>
References: <rmah-210594031419@rmah.dialup.access.net>
Organization: McGill University School of Architecture
In article <rmah-210594031419@rmah.dialup.access.net>, rmah@panix.com (Robert S. Mah) wrote:
> I'm currently experimenting with the Thread Mgr to implement blocking I/O
> as per the examples in develop 17. I'm doing this with MacTCP 2.0.x and
> was wondering if anyone else has tried this.
[stuff deleted]
>
> So, while the I/O thread is always running, and does not sleep, thereby
> hogging resources, does this incur _that_ much overhead? I have a
> suspician that this would be more efficient than calling WaitNextEvent
> (i.e. in a single threaded app) instead of Yield. Or would it?
Well, if you have several threads that are looping like the example above
(the technical term is "busy-waiting"), you may spend a lot of time just
switching contexts for no reason. The technique illustrated in develop 17,
although quite a bit more complicated, has the advantage of not having any
busy-waiting threads.
If you have CodeWarrior, DR/3 includes some PowerPlant classes for
implementing threads. They let you do thread-blocking I/O relatively
painlessly. You also get some semaphore classes and a class for inter-
thread communication.
Paul Lalonde
paul@architecture.mcgill.ca
+++++++++++++++++++++++++++
>From rmah@panix.com (Robert S. Mah)
Date: Sun, 22 May 1994 22:42:45 -0500
Organization: One Step Beyond
qmot@cs.mcgill.ca (Thomas PUSHPATHADAM) wrote:
> rmah@panix.com (Robert S. Mah) wrote:
>
> > I'm currently experimenting with the Thread Mgr to implement blocking I/O
> > as per the examples in develop 17. I'm doing this with MacTCP 2.0.x and
> > was wondering if anyone else has tried this.
>
> [stuff deleted]
>
> > So, while the I/O thread is always running, and does not sleep, thereby
> > hogging resources, does this incur _that_ much overhead? I have a
> > suspician that this would be more efficient than calling WaitNextEvent
> > (i.e. in a single threaded app) instead of Yield. Or would it?
>
> Well, if you have several threads that are looping like the example above
> (the technical term is "busy-waiting"), you may spend a lot of time just
> switching contexts for no reason. The technique illustrated in develop 17,
> although quite a bit more complicated, has the advantage of not having any
> busy-waiting threads.
>
> If you have CodeWarrior, DR/3 includes some PowerPlant classes for
> implementing threads. They let you do thread-blocking I/O relatively
> painlessly. You also get some semaphore classes and a class for inter-
> thread communication.
Ohhh, I can't wait for DR/3 to get to my hot little hands!
But...back to the theory. What I've done currently is the following...
I/O Thread
Async Call with FrontProcess completion
while not finished
YieldToAnyTask
Do my stuff
FrontProcess completion
SetFrontProcess to my process
This gives me very good throughput, but seems to be, like you said, hogging
lot's of CPU time -- well more than chained async I/O calls anyway. .
Are there any other techniques? Why can't one just do the following...
I/O Thread
Async Call with no completion
if doneFlag is true
Sleep this thread
Do my stuff
Wakeup completion
Wakeup completion thread
set doneFlag to true
Can one get a deadlock situation with this? I don't see how. Or is it
really bad to wakeup a thread that isn't asleep?
Cheers,
Rob
___________________________________________________________________________
Robert S. Mah -=- One Step Beyond -=- 212-947-6507 -=- rmah@panix.com
+++++++++++++++++++++++++++
>From Manuel Veloso <veloso@netcom.com>
Date: Mon, 23 May 1994 03:01:44 GMT
Organization: Ibex Productions
In article <2rmenh$8bt@inferno.mpx.com.au> Stephen F Coy, stevec@jolt.mpx.com.au writes:
>I have been using the second method you described above for some time
>now, both with the original threads package and the new stuff. Sure, you
>get a lot of thread swapping, but this is pretty cheap these days.
>
>The technique described in Develop seems like a lot of trouble to me. I
>would love to see someone justify it. (That is, I want to know the
>technical reasons why it should be done that way.)
Maybe it's one of those examples that's a bit too complicated, but illustrated
the point of sleep/wake. If the routine in question required that there
be some kind of completion routine (like ADSP or MacTCP) for handling
callbacks/parameters, the yield() method wouldn't work. Maybe also
if you were doing a socket listener, etc.
Still, for async IO that doesn't require a completion routine, way #2
is a whole lot easier.
+++++++++++++++++++++++++++
>From rmah@panix.com (Robert S. Mah)
Date: Mon, 23 May 1994 07:04:10 -0500
Organization: One Step Beyond
Manuel Veloso <veloso@netcom.com> wrote:
> Maybe it's one of those examples that's a bit too complicated, but illustrated
> the point of sleep/wake. If the routine in question required that there
> be some kind of completion routine (like ADSP or MacTCP) for handling
> callbacks/parameters, the yield() method wouldn't work. Maybe also
> if you were doing a socket listener, etc.
>
> Still, for async IO that doesn't require a completion routine, way #2
> is a whole lot easier.
Oh, the develop example isn't so much because of a completion routine
requirement as much as a problem with trying to sleep a thread after the
async routine completes.
The basic idea behind the develop article is to...
1. Start the async routine
2. Sleep this thread
...
3. Wake the thread from the completion routine.
Note, that, as Anderson & Post put it, "there is a window of misfortune
after the thread makes the asynchronous call and before it completes the
sleep call" I.e. you're completion can fire off between #1 and #2. So
you wake, then you sleep and never awake.
Cheers,
Rob
___________________________________________________________________________
Robert S. Mah -=- One Step Beyond -=- 212-947-6507 -=- rmah@panix.com
+++++++++++++++++++++++++++
>From stevec@jolt.mpx.com.au (Stephen F Coy)
Date: 23 May 1994 13:54:54 GMT
Organization: Microplex Pty Ltd
Manuel Veloso (veloso@netcom.com) wrote:
: In article <2rmenh$8bt@inferno.mpx.com.au> Stephen F Coy, stevec@jolt.mpx.com.au writes:
: >I have been using the second method you described above for some time
: >now, both with the original threads package and the new stuff. Sure, you
: >get a lot of thread swapping, but this is pretty cheap these days.
: >
: >The technique described in Develop seems like a lot of trouble to me. I
: >would love to see someone justify it. (That is, I want to know the
: >technical reasons why it should be done that way.)
: Maybe it's one of those examples that's a bit too complicated, but illustrated
: the point of sleep/wake. If the routine in question required that there
: be some kind of completion routine (like ADSP or MacTCP) for handling
: callbacks/parameters, the yield() method wouldn't work. Maybe also
: if you were doing a socket listener, etc.
But these are the exact places that I have been using the yield technique!
I can't think of ANY part of the Mac OS that REQUIRES a completion
routine to perform async I/O. (I am of course willing to be corrected
here :) ).
Typically, the yield loop polls the ioresult field of the parameter block
until it is not 1.
: Still, for async IO that doesn't require a completion routine, way #2
: is a whole lot easier.
- ----
Steve Coy
+++++++++++++++++++++++++++
>From Jens Alfke <jens_alfke@powertalk.apple.com>
Date: Wed, 25 May 1994 19:20:09 GMT
Organization: Apple Computer
In article <rmah-210594031419@rmah.dialup.access.net> Robert S. Mah,
rmah@panix.com writes:
> So, while the I/O thread is always running, and does not sleep, thereby
> hogging resources, does this incur _that_ much overhead?
Isn't 50% of your CPU time spent in pre-emptive threads, if any are ready to
run? This implies that the Thread Manager will make sure your app spends
exactly 50% of its time in that little wait loop. (Disclaimer: I have not
used the Thread Manager, but I've read the documentation closely...)
--Jens Alfke
jens_alfke@powertalk Rebel girl, rebel girl,
.apple.com Rebel girl you are the queen of my world
+++++++++++++++++++++++++++
>From rmah@panix.com (Robert S. Mah)
Date: Wed, 25 May 1994 20:13:31 -0500
Organization: One Step Beyond
Jens Alfke <jens_alfke@powertalk.apple.com> wrote:
> Robert S. Mah, rmah@panix.com writes:
> > So, while the I/O thread is always running, and does not sleep,
> > thereby hogging resources, does this incur _that_ much overhead?
>
> Isn't 50% of your CPU time spent in pre-emptive threads, if any are
> ready to run? This implies that the Thread Manager will make sure your
> app spends exactly 50% of its time in that little wait loop.
> (Disclaimer: I have not used the Thread Manager, but I've read the
> documentation closely...)
I'm not using pre-emptive threads since they don't work on the PowerMac's.
And you're _almost_ right. Pre-emptive threads get 50% of you're
application's timeslice, not 50% of the CPU since the "pre-emptive" threads
only pre-empt when your app is awake. Or did you mean that and I'm read-
ing you wrong...hmm...
Anyway, my main thing now is a search for good a profiling tool that
measures the load on the system by each process. This will help my quest
for multi-threaded efficiency immeasurably.
Cheers,
Rob
___________________________________________________________________________
Robert S. Mah -=- One Step Beyond -=- 212-947-6507 -=- rmah@panix.com
+++++++++++++++++++++++++++
>From jlscott@tigr.org (John L. Scott)
Date: Tue, 31 May 1994 14:41:07 GMT
Organization: Self
In article <rmah-220594224245@rmah.dialup.access.net>, rmah@panix.com
(Robert S. Mah) wrote:
> qmot@cs.mcgill.ca (Thomas PUSHPATHADAM) wrote:
> Are there any other techniques? Why can't one just do the following...
>
> I/O Thread
> Async Call with no completion
> if doneFlag is true
> Sleep this thread
> Do my stuff
>
> Wakeup completion
> Wakeup completion thread
> set doneFlag to true
>
> Can one get a deadlock situation with this? I don't see how. Or is it
> really bad to wakeup a thread that isn't asleep?
Welcome to the headachy world of concurrent programming. If it can
preempt, it will preempt.
Async Call WITH completion
if doneFlag is FALSE
<---- Completion routine happens here
Sleep this thread
Do my stuff
If your code is interrupted AFTER the conditional but BEFORE the sleep
call, you will sleep forever. That is a very small window of opportunity,
but it will eventually happen. As far as I know, there are no other
solutions other than busy-waiting or using a second thread as in Develop
17.
--John L. Scott
+++++++++++++++++++++++++++
>From eastman@bnr.ca (Gordon Eastman)
Date: Tue, 31 May 1994 21:36:53 GMT
Organization: Bell-Northern Research
In article <jlscott-310594094108@jlscott.tigr.org>, jlscott@tigr.org (John
L. Scott) wrote:
> Welcome to the headachy world of concurrent programming. If it can
> preempt, it will preempt.
>
> Async Call WITH completion
> if doneFlag is FALSE
> <---- Completion routine happens here
> Sleep this thread
> Do my stuff
>
> If your code is interrupted AFTER the conditional but BEFORE the sleep
> call, you will sleep forever. That is a very small window of opportunity,
> but it will eventually happen. As far as I know, there are no other
> solutions other than busy-waiting or using a second thread as in Develop
> 17.
>
> --John L. Scott
Here is another solution.
>From the completion routine, check the state of the thread. If it is
sleeping, wake it. Otherwise you hit that small window of misfortune, so
install a time manager task that triggers in a bit and try again.
I have done this successfully, and see with my Code Warrior DR/3 CD that
arrived today that the PowerPlant thread class library also uses this
technique.
-- Gord
+++++++++++++++++++++++++++
>From rmah@panix.com (Robert S. Mah)
Date: Wed, 01 Jun 1994 10:25:27 -0500
Organization: One Step Beyond
eastman@bnr.ca (Gordon Eastman) wrote:
> From the completion routine, check the state of the thread. If it is
> sleeping, wake it. Otherwise you hit that small window of misfortune, so
> install a time manager task that triggers in a bit and try again.
>
> I have done this successfully, and see with my Code Warrior DR/3 CD that
> arrived today that the PowerPlant thread class library also uses this
> technique.
Better be careful there. If I understand you correctly, you're saying
do this...
I/O Thread
Async call with completion
Sleep this thread
Completion
if I/O Thread is asleap
Wake I/O Thread
Potentially, the completion routine could fire before you sleep the I/O
thread. This means that the I/O thread will sleep forever! Not much
chance, but it could happen. This was precisely the problem that the
example in develop 17 (the one that uses a wake up thread) was supposed
to solve.
Cheers,
Rob
___________________________________________________________________________
Robert S. Mah -=- One Step Beyond -=- 212-947-6507 -=- rmah@panix.com
+++++++++++++++++++++++++++
>From qmot@cs.mcgill.ca (Thomas PUSHPATHADAM)
Date: 1 Jun 1994 16:50:26 GMT
Organization: SOCS, McGill University, Montreal, Canada
(*** Posting from borrowed account ***)
rmah@panix.com (Robert S. Mah) wrote:
> eastman@bnr.ca (Gordon Eastman) wrote:
> > From the completion routine, check the state of the thread. If it is
> > sleeping, wake it. Otherwise you hit that small window of misfortune,
> > so
> > install a time manager task that triggers in a bit and try again.
> >
> > I have done this successfully, and see with my Code Warrior DR/3 CD
> > that
> > arrived today that the PowerPlant thread class library also uses this
> > technique.
> Better be careful there. If I understand you correctly, you're saying
> do this...
> I/O Thread
> Async call with completion
> Sleep this thread
>
> Completion
> if I/O Thread is asleap
> Wake I/O Thread
>
> Potentially, the completion routine could fire before you sleep the I/O
> thread. This means that the I/O thread will sleep forever! Not much
> chance, but it could happen. This was precisely the problem that the
> example in develop 17 (the one that uses a wake up thread) was supposed
> to solve.
Actually, I think he meant to do this:
I/O thread
async call with completion
sleep thread
Completion routine
if I/O thread is asleep
wake I/O thread
else
install time manager task with same completion routine
In this way, if the completion routine executes before the I/O thread
has been put to sleep, the completion routine just arranged to regain
control after a small delay. This is precisely the method used in the
threads classes in PowerPlant.
Strictly speaking, this is a form of busy waiting. However, the time
window within which the busy waiting occurs is very small, assuming
you don't something like call WaitNextEvent between the async call
and the sleep call.
Cheers,
Paul Lalonde
paul@architecure.mcgill.ca
+++++++++++++++++++++++++++
>From eastman@bnr.ca (Gord Eastman)
Date: Wed, 1 Jun 1994 16:23:21 GMT
Organization: Bell-Northern Research
In article <rmah-010694102527@rmah.dialup.access.net>, rmah@panix.com
(Robert S. Mah) wrote:
> eastman@bnr.ca (Gordon Eastman) wrote:
>
> > From the completion routine, check the state of the thread. If it is
> > sleeping, wake it. Otherwise you hit that small window of misfortune, so
> > install a time manager task that triggers in a bit and try again.
> >
> > I have done this successfully, and see with my Code Warrior DR/3 CD that
> > arrived today that the PowerPlant thread class library also uses this
> > technique.
>
> Better be careful there. If I understand you correctly, you're saying
> do this...
>
> I/O Thread
> Async call with completion
> Sleep this thread
>
> Completion
> if I/O Thread is asleap
> Wake I/O Thread
>
> Potentially, the completion routine could fire before you sleep the I/O
> thread. This means that the I/O thread will sleep forever! Not much
> chance, but it could happen. This was precisely the problem that the
> example in develop 17 (the one that uses a wake up thread) was supposed
> to solve.
And the precise problem that the time manager task solves. You seem to have
missed the "Otherwise" sentence of my post.The completion routine would be:
if I/O Thread is asleep
Wake I/O Thread
else
Install Time Manager task
When the Time Manager task fires,
if I/O Thread is asleep
Wake I/O Thread
else
reinstall Time Manager task
-- Gord
+++++++++++++++++++++++++++
>From rmah@panix.com (Robert S. Mah)
Date: Wed, 01 Jun 1994 19:47:34 -0500
Organization: One Step Beyond
eastman@bnr.ca (Gord Eastman) wrote:
> And the precise problem that the time manager task solves. You seem to have
> missed the "Otherwise" sentence of my post.The completion routine would be:
Oops...sorry about that. I'll endevour to be more attentive next time :-)
Cheers,
Rob
___________________________________________________________________________
Robert S. Mah -=- One Step Beyond -=- 212-947-6507 -=- rmah@panix.com
---------------------------
End of C.S.M.P. Digest
**********************