📄 tclmacthrd.c
字号:
Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */{/* There is nothing to do on the Mac */}/* *---------------------------------------------------------------------- * * TclpFinalizeMutex -- * * This procedure is invoked to clean up one mutex. This is only * safe to call at the end of time. * * This assumes the Master Lock is held. * * Results: * None. * * Side effects: * The mutex list is deallocated. * *---------------------------------------------------------------------- */voidTclpFinalizeMutex(mutexPtr) Tcl_Mutex *mutexPtr;{/* There is nothing to do on the Mac */}/* *---------------------------------------------------------------------- * * TclpThreadDataKeyInit -- * * This procedure initializes a thread specific data block key. * Each thread has table of pointers to thread specific data. * all threads agree on which table entry is used by each module. * this is remembered in a "data key", that is just an index into * this table. To allow self initialization, the interface * passes a pointer to this key and the first thread to use * the key fills in the pointer to the key. The key should be * a process-wide static. * * There is no system-wide support for thread specific data on the * Mac. So we implement this as an array of pointers. The keys are * allocated sequentially, and each key maps to a slot in the table. * The table element points to a linked list of the instances of * the data for each thread. * * Results: * None. * * Side effects: * Will bump the key counter if this is the first time this key * has been initialized. May grow the DataKeyArray if that is * necessary. * *---------------------------------------------------------------------- */voidTclpThreadDataKeyInit(keyPtr) Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, * really (pthread_key_t **) */{ if (*keyPtr == NULL) { keyCounter += 1; *keyPtr = (Tcl_ThreadDataKey) keyCounter; if (keyCounter > maxNumKeys) { TclMacThrdData **newArray; int i, oldMax = maxNumKeys; maxNumKeys = maxNumKeys + TCL_MAC_INITIAL_KEYSIZE; newArray = (TclMacThrdData **) ckalloc(maxNumKeys * sizeof(TclMacThrdData *)); for (i = 0; i < oldMax; i++) { newArray[i] = tclMacDataKeyArray[i]; } for (i = oldMax; i < maxNumKeys; i++) { newArray[i] = NULL; } if (tclMacDataKeyArray != NULL) { ckfree((char *) tclMacDataKeyArray); } tclMacDataKeyArray = newArray; } /* TclRememberDataKey(keyPtr); */ }}/* *---------------------------------------------------------------------- * * TclpThreadDataKeyGet -- * * This procedure returns a pointer to a block of thread local storage. * * Results: * A thread-specific pointer to the data structure, or NULL * if the memory has not been assigned to this key for this thread. * * Side effects: * None. * *---------------------------------------------------------------------- */VOID *TclpThreadDataKeyGet(keyPtr) Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, * really (pthread_key_t **) */{ TclMacThrdData *dataPtr; dataPtr = GetThreadDataStruct(*keyPtr); if (dataPtr == NULL) { return NULL; } else { return dataPtr->data; }}/* *---------------------------------------------------------------------- * * TclpThreadDataKeySet -- * * This procedure sets the pointer to a block of thread local storage. * * Results: * None. * * Side effects: * Sets up the thread so future calls to TclpThreadDataKeyGet with * this key will return the data pointer. * *---------------------------------------------------------------------- */voidTclpThreadDataKeySet(keyPtr, data) Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, * really (pthread_key_t **) */ VOID *data; /* Thread local storage */{ TclMacThrdData *dataPtr; ThreadID curThread; dataPtr = GetThreadDataStruct(*keyPtr); /* * Is it legal to reset the thread data like this? * And if so, who owns the memory? */ if (dataPtr != NULL) { dataPtr->data = data; } else { dataPtr = (TclMacThrdData *) ckalloc(sizeof(TclMacThrdData)); GetCurrentThread(&curThread); dataPtr->threadID = curThread; dataPtr->data = data; dataPtr->next = tclMacDataKeyArray[(int) *keyPtr - 1]; tclMacDataKeyArray[(int) *keyPtr - 1] = dataPtr; }}/* *---------------------------------------------------------------------- * * TclpFinalizeThreadData -- * * This procedure cleans up the thread-local storage. This is * called once for each thread. * * Results: * None. * * Side effects: * Frees up all thread local storage. * *---------------------------------------------------------------------- */voidTclpFinalizeThreadData(keyPtr) Tcl_ThreadDataKey *keyPtr;{ TclMacThrdData *dataPtr; if (*keyPtr != NULL) { dataPtr = RemoveThreadDataStruct(*keyPtr); if ((dataPtr != NULL) && (dataPtr->data != NULL)) { ckfree((char *) dataPtr->data); ckfree((char *) dataPtr); } }}/* *---------------------------------------------------------------------- * * TclpFinalizeThreadDataKey -- * * This procedure is invoked to clean up one key. This is a * process-wide storage identifier. The thread finalization code * cleans up the thread local storage itself. * * On the Mac, there is really nothing to do here, since the key * is just an array index. But we set the key to 0 just in case * someone else is relying on that. * * Results: * None. * * Side effects: * The keyPtr value is set to 0. * *---------------------------------------------------------------------- */voidTclpFinalizeThreadDataKey(keyPtr) Tcl_ThreadDataKey *keyPtr;{ ckfree((char *) tclMacDataKeyArray[(int) *keyPtr - 1]); tclMacDataKeyArray[(int) *keyPtr - 1] = NULL; *keyPtr = NULL;}/* *---------------------------------------------------------------------- * * GetThreadDataStruct -- * * This procedure gets the data structure corresponding to * keyVal for the current process. * * Results: * The requested key data. * * Side effects: * None. * *---------------------------------------------------------------------- */TclMacThrdData *GetThreadDataStruct(keyVal) Tcl_ThreadDataKey keyVal;{ ThreadID curThread; TclMacThrdData *dataPtr; /* * The keyPtr will only be greater than keyCounter is someone * has passed us a key without getting the value from * TclpInitDataKey. */ if ((int) keyVal <= 0) { return NULL; } else if ((int) keyVal > keyCounter) { panic("illegal data key value"); } GetCurrentThread(&curThread); for (dataPtr = tclMacDataKeyArray[(int) keyVal - 1]; dataPtr != NULL; dataPtr = dataPtr->next) { if (dataPtr->threadID == curThread) { break; } } return dataPtr;}/* *---------------------------------------------------------------------- * * RemoveThreadDataStruct -- * * This procedure removes the data structure corresponding to * keyVal for the current process from the list kept for keyVal. * * Results: * The requested key data is removed from the list, and a pointer * to it is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */TclMacThrdData *RemoveThreadDataStruct(keyVal) Tcl_ThreadDataKey keyVal;{ ThreadID curThread; TclMacThrdData *dataPtr, *prevPtr; if ((int) keyVal <= 0) { return NULL; } else if ((int) keyVal > keyCounter) { panic("illegal data key value"); } GetCurrentThread(&curThread); for (dataPtr = tclMacDataKeyArray[(int) keyVal - 1], prevPtr = NULL; dataPtr != NULL; prevPtr = dataPtr, dataPtr = dataPtr->next) { if (dataPtr->threadID == curThread) { break; } } if (dataPtr == NULL) { /* No body */ } else if ( prevPtr == NULL) { tclMacDataKeyArray[(int) keyVal - 1] = dataPtr->next; } else { prevPtr->next = dataPtr->next; } return dataPtr; }/* *---------------------------------------------------------------------- * * Tcl_ConditionWait -- * * This procedure is invoked to wait on a condition variable. * On the Mac, mutexes are no-ops, and we just yield. After * all, it is the application's job to loop till the condition * variable is changed... * * * Results: * None. * * Side effects: * Will block the current thread till someone else yields. * *---------------------------------------------------------------------- */voidTcl_ConditionWait(condPtr, mutexPtr, timePtr) Tcl_Condition *condPtr; /* Really (pthread_cond_t **) */ Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */ Tcl_Time *timePtr; /* Timeout on waiting period */{ if (TclMacHaveThreads()) { YieldToAnyThread(); }}/* *---------------------------------------------------------------------- * * Tcl_ConditionNotify -- * * This procedure is invoked to signal a condition variable. * * The mutex must be held during this call to avoid races, * but this interface does not enforce that. * * Results: * None. * * Side effects: * May unblock another thread. * *---------------------------------------------------------------------- */voidTcl_ConditionNotify(condPtr) Tcl_Condition *condPtr;{ if (TclMacHaveThreads()) { YieldToAnyThread(); }}/* *---------------------------------------------------------------------- * * TclpFinalizeCondition -- * * This procedure is invoked to clean up a condition variable. * This is only safe to call at the end of time. * * This assumes the Master Lock is held. * * Results: * None. * * Side effects: * The condition variable is deallocated. * *---------------------------------------------------------------------- */voidTclpFinalizeCondition(condPtr) Tcl_Condition *condPtr;{ /* Nothing to do on the Mac */}#endif /* TCL_THREADS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -