home *** CD-ROM | disk | FTP | other *** search
- #ifndef __AETHREADS__
- #include "AEThreads.h"
- #endif
- #ifndef __EXCEPTIONS__
- #include "Exceptions.h"
- #endif
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
- #include <AppleEvents.h>
-
- typedef struct AEThreadDesc AEThreadDesc;
- typedef struct AEThreadParam AEThreadParam;
-
- struct AEThreadDesc // Kept in the OS refcon
- {
- AEEventHandlerProcPtr handler; // The real handler
- long refcon; // The real refcon
- Size stackSize; // Shack size for handling event
- ThreadOptions options; // Thread options for event
- ThreadID holder; // used as a semaphore
- };
-
- struct AEThreadParam // Used in spawning
- {
- const AppleEvent* event;
- AppleEvent* reply;
- AEThreadDesc* desc;
- ThreadID thread;
- OSErr result;
- };
-
-
- pascal OSErr SpawnAEThread(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon);
- pascal long AEThread(AEThreadParam* parms);
-
- AEEventHandlerUPP gSpawnAEThreadUPP = nil;
-
- #pragma segment foobar
-
- pascal OSErr AEInstallThreadedEventHandler(
- AEEventClass theAEEventClass,
- AEEventID theAEEventID,
- AEEventHandlerProcPtr proc,
- long handlerRefcon,
- ThreadOptions options,
- Size stacksize)
- {
- AEThreadDesc* desc = (AEThreadDesc*) NewPtr(sizeof(AEThreadDesc));
- OSErr err = MemError();
-
- if (gSpawnAEThreadUPP == nil)
- {
- gSpawnAEThreadUPP = NewAEEventHandlerProc(SpawnAEThread);
- }
-
- if (err == noErr)
- {
- desc->handler = proc;
- desc->refcon = handlerRefcon;
- desc->stackSize = stacksize;
- desc->options = options;
- desc->holder = kNoThreadID;
-
- err = AEInstallEventHandler(theAEEventClass, theAEEventID, gSpawnAEThreadUPP, (long) desc, false);
- }
-
- return err;
- }
-
- static OSStatus call_event_handler(va_list arg)
- {
- VA_ARG(AppleEvent*, event, arg);
- VA_ARG(AppleEvent*, reply, arg);
- VA_ARG(AEThreadDesc*, desc, arg);
-
- FailOSErr((*desc->handler)(event, reply, desc->refcon));
-
- return noErr;
- }
-
- pascal long AEThread(AEThreadParam* parms)
- {
- AppleEvent event; // Original parameters we care about
- AppleEvent reply;
- AEThreadDesc* desc;
- OSErr err;
-
- event = *parms->event; // copy these into our own stack frame
- reply = *parms->reply;
- desc = parms->desc;
-
- // Let caller know we're ready
-
- if ((parms->result = AESuspendTheCurrentEvent(&event)) != noErr)
- {
- return nil; // Bail if there's a problem
- }
-
- // At this point, we need to let our caller return
-
- while (desc->holder != kNoThreadID)
- {
- YieldToThread(desc->holder);
- }
-
- // We are now on our own
-
- err = Exception::CatchAEErrors(
- reply.descriptorType != typeNull ? &reply : nil,
- call_event_handler, &event, &reply, desc);
-
- err = AEResumeTheCurrentEvent(&event, &reply, kAENoDispatch, 0); // This had better work
-
- #if qDebug
- LogIfErr(err, "AEResumeTheCurrentEvent failed - very bad");
- #endif
-
- return err;
- }
-
- #pragma segment Spawn
-
- pascal OSErr SpawnAEThread(const AppleEvent *event, AppleEvent *reply, long handlerRefcon)
- {
- AEThreadParam param;
-
- param.event = event;
- param.reply = reply;
- param.desc = (AEThreadDesc*) handlerRefcon;
- param.thread = kNoThreadID;
-
- if (!param.desc)
- {
- param.result = paramErr;
- }
- else
- {
- while (param.desc->holder != kNoThreadID) // make sure no-one else is trying to start a handler
- {
- YieldToAnyThread();
- }
-
- if ((param.result = GetCurrentThread(¶m.desc->holder)) == noErr) // Grab the semaphore
- {
- param.result = NewThread(kCooperativeThread,
- (ThreadEntryProcPtr) &AEThread,
- ¶m,
- param.desc->stackSize,
- param.desc->options,
- nil,
- ¶m.thread);
-
- if (param.result == noErr)
- {
- param.result = 1;
-
- do
- {
- YieldToThread(param.thread);
- }
- while (param.result == 1); // Wait for thread to pick up parameters
- }
- }
-
- param.desc->holder = kNoThreadID; // release any claims we have
- }
-
- return param.result;
- }
-
-
-
-
-