home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-05-25 | 4.1 KB | 190 lines | [TEXT/CWIE] |
- /*
- File: AEThreads.c
-
- Contains: Routines for installing threaded AppleEvent handlers
-
- Written by: Steve Sisak
-
- Copyright: © 1993-94 Steve Sisak
- License is granted to use, modify, make derivative works, and
- duplicate this code at will, so long as this notice remains intact.
-
- Change History (most recent first):
-
- <1> 1/24/95 DRF First checked in.
- */
-
- #ifndef __AETHREADS__
- #include "AEThreads.h"
- #endif
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
- #ifndef __APPLEEVENTS__
- #include <AppleEvents.h>
- #endif
-
- #include "ThreadSupport.h"
- #include "Exceptions.h"
-
-
- pascal OSErr SpawnAEThread(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon);
-
- class AEThread : public TThread
- {
- protected:
- AEEventHandlerUPP fHandler; // The real handler
- const AppleEvent* fEvent;
- AppleEvent* fReply;
- long fRefcon;
-
- public:
- AEThread(AEEventHandlerUPP handler, const AppleEvent* event, AppleEvent* reply, long refcon, ThreadID id)
- : TThread(id), fHandler(handler), fEvent(event), fReply(reply), fRefcon(refcon) {};
- virtual ~AEThread() {};
-
- static pascal void* AEThreadProc(AEThread* context);
-
- friend pascal OSErr SpawnAEThread(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon);
- };
-
- struct AEThreadDesc // Kept in the OS refcon
- {
- AEEventHandlerUPP handler; // The real handler
- long refcon; // The real refcon
- Size stackSize; // Stack size for handling event
- ThreadOptions options; // Thread options for event
- ThreadID holder; // used as a semaphore
- };
-
- AEEventHandlerUPP gSpawnAEThreadUPP = nil;
-
- //#pragma segment foobar
-
- pascal OSErr AEInstallThreadedEventHandler(
- AEEventClass theAEEventClass,
- AEEventID theAEEventID,
- AEEventHandlerUPP 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;
- }
-
-
- pascal void* AEThread::AEThreadProc(AEThread* context)
- {
- OSErr result = noErr;
-
- try
- {
- result = CallAEEventHandlerProc(context->fHandler, context->fEvent, context->fReply, context->fRefcon);
-
- // Since the event was suspended, we need to stuff the error code ourselves
- // note that there's not much we can do about reporting errors beyond here
- }
- catch (Exception& err)
- {
- err.CopyToAppleEvent(CAppleEvent(context->fReply));
- result = 1;
- }
- catch (...)
- {
- result = eGeneralErr;
- }
-
- OSErr err;
-
- if (result != 1)
- {
- err = AEPutAttributePtr(context->fReply, keyErrorNumber, typeShortInteger, &result, sizeof(result));
-
- #if qDebug
- if (err)
- SysBreakStr("\pAEPutAttributePtr failed installing error code - very bad");
- #endif
- }
-
- err = AEResumeTheCurrentEvent(context->fEvent, context->fReply, kAENoDispatch, 0); // This had better work
-
- #if qDebug
- if (err)
- SysBreakStr("\pAEResumeTheCurrentEvent failed - very bad");
- #endif
-
- delete context;
-
- return nil;
- }
-
- pascal OSErr AEHandleInThread(
- const AppleEvent* event,
- AppleEvent* reply,
- AEEventHandlerUPP handler,
- long handlerRefcon,
- ThreadOptions options,
- Size stacksize)
- {
- OSErr result;
- AEThread* context = new AEThread(handler, event, reply, handlerRefcon);
-
- try
- {
- FailNil(context);
-
- context->CreateThread(kCooperativeThread, (ThreadEntryProcPtr) AEThread::AEThreadProc, stacksize, options);
-
- result = AESuspendTheCurrentEvent(event);
- }
- catch (TException& err)
- {
- delete context;
- result = err.GetErrorNumber();
- }
- catch (...)
- {
- delete context;
- result = eGeneralErr;
- }
-
- return result;
- }
-
-
- //#pragma segment Spawn
-
- pascal OSErr SpawnAEThread(const AppleEvent *event, AppleEvent *reply, long handlerRefcon)
- {
- AEThreadDesc* desc = (AEThreadDesc*) handlerRefcon;
-
- return AEHandleInThread(event, reply,
- desc->handler,
- desc->refcon,
- desc->options,
- desc->stackSize);
- }
-
-
-
-
-