home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-09-17 | 9.3 KB | 307 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWThrdGd.cpp
- // Release Version: $ ODF 2 $
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #ifndef FWTHRDGD_H
- #include "FWThrdGd.h"
- #endif
-
- #ifndef FWPRIMEM_H
- #include "FWPriMem.h"
- #endif
-
- #ifndef FWEXCDEF_H
- #include "FWExcDef.h"
- #endif
-
- #ifdef FW_BUILD_MAC
- #pragma segment FWCommon
- #endif
-
- //=====================================================================================
- // Class FW_CThreadSafe
- //=====================================================================================
-
- FW_CThreadGuard *FW_CThreadSafe::fgSwitchGuards = 0;
- FW_CThreadGuard *FW_CThreadSafe::fgTerminationGuards = 0;
-
-
- //------------------------------------------------------------------------------
- // FW_CThreadSafe::NoteCreation
- //
- // Register the creation of a thread. This should be called from a critical
- // section. All guards are on the list of termination guards.
- //------------------------------------------------------------------------------
- void FW_CThreadSafe::NoteCreation(FW_ThreadID newlyCreatedThread)
- {
- #ifdef FW_BUILD_MAC
- FW_CThreadGuard *aThreadGuard;
-
- for (aThreadGuard = fgTerminationGuards; aThreadGuard != 0; aThreadGuard = aThreadGuard->fNext)
- {
- // A throw in the middle of this would be bad. Catch everything and ignore
- // it. We can't do much else (except assert, and that might also be deadly).
- FW_TRY
- {
- // The "Created" method can call AddThreadInfo to associate a chunk of storage
- // with this thread.
- aThreadGuard->Created(newlyCreatedThread);
- }
- FW_CATCH_BEGIN
- FW_CATCH_EVERYTHING()
- {
- }
- FW_CATCH_END
- }
- #endif
- }
-
-
- //------------------------------------------------------------------------------
- // FW_CThreadSafe::NoteTermination
- //
- // Register the destruction of a thread. This should be called from a critical
- // section
- //------------------------------------------------------------------------------
- void FW_CThreadSafe::NoteTermination(FW_ThreadID threadBeingKilled)
- {
- #ifdef FW_BUILD_MAC
- FW_CThreadGuard *aThreadGuard;
-
- for (aThreadGuard = fgTerminationGuards; aThreadGuard != 0; aThreadGuard = aThreadGuard->fNext)
- {
- FW_TRY
- {
- // The "Terminating" method can call DeleteThreadInfo to remove the association
- // of any information with this thread.
- aThreadGuard->Terminating(threadBeingKilled);
- }
- FW_CATCH_BEGIN
- FW_CATCH_EVERYTHING()
- {
- }
- FW_CATCH_END
- }
- #endif
- }
-
-
- #ifdef FW_BUILD_MAC
- //------------------------------------------------------------------------------
- // FW_CThreadSafe::NoteSwitch
- //
- // Called between threads, indicating which are the old and the new threads.
- // This should be called from a critical section.
- //------------------------------------------------------------------------------
- void FW_CThreadSafe::NoteSwitch(FW_ThreadID aThread, FW_Boolean switchingIn)
- {
- FW_CThreadGuard *aThreadGuard;
- unsigned long mask;
-
- if (switchingIn)
- mask = FW_CThreadGuard::kSwitchInThreadEvent;
- else
- mask = FW_CThreadGuard::kSwitchOutThreadEvent;
-
- for (aThreadGuard = fgSwitchGuards; aThreadGuard != 0; aThreadGuard = aThreadGuard->fNext)
- {
- // The "Switch()" method must not throw! We cannot do an FW_TRY here
- // because in the case of interest (swapping exception globals), the
- // Switch() would be entered with one set of exception globals and
- // exit with another. Don't ask how I discovered this...
- if (aThreadGuard->GetMask() & mask)
- aThreadGuard->Switch(aThread, switchingIn);
- }
- }
- #endif
-
-
- //------------------------------------------------------------------------------
- // FW_CThreadSafe::RegisterTerminationGuard
- //
- // Add a ThreadGuard to the list of guardians
- //------------------------------------------------------------------------------
- void FW_CThreadSafe::RegisterTerminationGuard(FW_CThreadGuard *aThreadGuard)
- {
- // Add this guardian to the head of the list
- aThreadGuard->fNext = fgTerminationGuards;
- fgTerminationGuards = aThreadGuard;
- }
-
-
- //------------------------------------------------------------------------------
- // FW_CThreadSafe::DeRegisterTerminationGuard
- //
- // Remove a ThreadGuard from the list of guardians
- //------------------------------------------------------------------------------
- void FW_CThreadSafe::DeRegisterTerminationGuard(FW_CThreadGuard *aThreadGuard)
- {
- // Remove from the head of the list. Should be safe as destructors are
- // executed in reverse order from the constructors
- if (fgTerminationGuards == aThreadGuard)
- fgTerminationGuards = aThreadGuard->fNext;
- }
-
-
- //------------------------------------------------------------------------------
- // FW_CThreadSafe::RegisterSwitchGuard
- //
- // Add a ThreadGuard to the list of guardians
- //------------------------------------------------------------------------------
- void FW_CThreadSafe::RegisterSwitchGuard(FW_CThreadGuard *aThreadGuard)
- {
- // Add this guardian to the head of the list
- aThreadGuard->fNext = fgSwitchGuards;
- fgSwitchGuards = aThreadGuard;
- }
-
-
- //------------------------------------------------------------------------------
- // FW_CThreadSafe::DeRegisterSwitchGuard
- //
- // Remove a ThreadGuard from the list of guardians
- //------------------------------------------------------------------------------
- void FW_CThreadSafe::DeRegisterSwitchGuard(FW_CThreadGuard *aThreadGuard)
- {
- // Remove from the head of the list. Should be safe as destructors are
- // executed in reverse order from the constructors
- if (fgSwitchGuards == aThreadGuard)
- fgSwitchGuards = aThreadGuard->fNext;
- }
-
-
- //=====================================================================================
- // Class FW_CThreadGuard
- //=====================================================================================
-
- //------------------------------------------------------------------------------
- // FW_CThreadGuard::FW_CThreadGuard
- //
- // Constructor for FW_CThreadGuard
- //------------------------------------------------------------------------------
- FW_CThreadGuard::FW_CThreadGuard(unsigned long threadEventMask) :
- fActiveThreads(0),
- fMask(threadEventMask)
- {
- // Always check for termination if checking for anything
- if (threadEventMask != 0)
- FW_CThreadSafe::RegisterTerminationGuard(this);
-
- if (threadEventMask & (kSwitchInThreadEvent | kSwitchOutThreadEvent))
- FW_CThreadSafe::RegisterSwitchGuard(this);
- }
-
-
- //------------------------------------------------------------------------------
- // FW_CThreadGuard::~FW_CThreadGuard
- //
- // Destructor for FW_CThreadGuard
- //------------------------------------------------------------------------------
- FW_CThreadGuard::~FW_CThreadGuard()
- {
- FW_CThreadSafe::DeRegisterTerminationGuard(this);
- FW_CThreadSafe::DeRegisterSwitchGuard(this);
-
- while (fActiveThreads != 0)
- {
- FW_SThreadItem *anItem = fActiveThreads;
-
- fActiveThreads = anItem->fNext;
- FW_PrimitiveFreeBlock(anItem);
- }
- }
-
-
- #ifdef FW_BUILD_MAC
- //------------------------------------------------------------------------------
- // FW_CThreadGuard::Switch
- //
- // Called between thread switches
- //------------------------------------------------------------------------------
- void FW_CThreadGuard::Switch(FW_ThreadID, FW_Boolean)
- {
- // Default is to do nothing
- }
- #endif
-
-
- //------------------------------------------------------------------------------
- // FW_CThreadGuard::AddThreadInfo
- //
- // Associates a void* with a ThreadID.
- //------------------------------------------------------------------------------
- void FW_CThreadGuard::AddThreadInfo(FW_ThreadID aThreadID, void *threadInfo)
- {
- FW_SThreadItem *newItem = (FW_SThreadItem *)FW_PrimitiveAllocateBlock(sizeof(FW_SThreadItem));
-
- // [jkp] -- what's the approved method of suicide?
- if (newItem != 0)
- {
- newItem->fThreadID = aThreadID;
- newItem->fThreadInfo = threadInfo;
-
- newItem->fNext = fActiveThreads;
- fActiveThreads = newItem;
- }
- }
-
-
- //------------------------------------------------------------------------------
- // FW_CThreadGuard::GetThreadInfo
- //
- // Returns the void* with a ThreadID.
- //------------------------------------------------------------------------------
-
- void *FW_CThreadGuard::GetThreadInfo(FW_ThreadID aThreadID)
- {
- for (FW_SThreadItem *anItem = fActiveThreads; anItem != 0; anItem = anItem->fNext)
- {
- if (anItem->fThreadID == aThreadID)
- return anItem->fThreadInfo;
- }
-
- // [jkp] -- what's the approved method of suicide?
- return 0;
- }
-
-
- //------------------------------------------------------------------------------
- // FW_CThreadGuard::RemoveThreadInfo
- //
- // Removes the association between a ThreadID and any chunk of data it pointed
- // to. The caller must destroy the chunk of data, we don't know how.
- //------------------------------------------------------------------------------
- void FW_CThreadGuard::RemoveThreadInfo(FW_ThreadID aThreadID)
- {
- FW_SThreadItem **itemPtr = &fActiveThreads;
- FW_SThreadItem *anItem = fActiveThreads;
-
- while (anItem != 0)
- {
- if (anItem->fThreadID == aThreadID)
- {
- *itemPtr = anItem->fNext;
- FW_PrimitiveFreeBlock(anItem);
- return;
- }
- itemPtr = &anItem->fNext;
- anItem = anItem->fNext;
- }
- // [jkp] -- what's the approved method of suicide?
- }
-
-
- //------------------------------------------------------------------------------
- // FW_CThreadGuard::GetMask
- //------------------------------------------------------------------------------
- unsigned long FW_CThreadGuard::GetMask() const
- {
- return fMask;
- }
-
-