From: pottier@clipper.ens.fr (Francois Pottier) Subject: csmp-digest-v3-035 Date: Wed, 15 Jun 1994 15:33:50 +0200 (MET DST) 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 Hillerøe Petersen ! * \ Information & Media Science ! --- | Århus 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 "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 Date: 31 May 1994 14:14:46 GMT Organization: Washington University In article 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 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 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 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 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 , 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@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 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 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 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 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 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 +++++++++++++++++++++++++++ >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 . -- Blake Sobiloff | 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 (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 . Or even better, if you have the Universal Headers it is defined in : 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 , 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. 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 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 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: <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 , 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: References: Organization: McGill University School of Architecture In article , 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 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 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 Date: Wed, 25 May 1994 19:20:09 GMT Organization: Apple Computer In article 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 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@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@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@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 **********************