tt_result_t tt_thread_wait_local_ntv(IN struct tt_thread_s *thread) { __thread_on_exit(thread); if (!FlsSetValue(tt_g_thread_fls_index, NULL)) { TT_ERROR_NTV("fail to clear thread specific data"); // return TT_FAIL; } return TT_SUCCESS; }
thread_specific_impl::object *thread_specific_impl::get_object() const { void *pobj = FlsGetValue(d->key); if(!pobj) { pobj = reinterpret_cast<void *>(d->base->clone()); if(!FlsSetValue(d->key,pobj)) { int err=GetLastError(); delete reinterpret_cast<object *>(pobj); throw system::system_error(system::error_code(err,system::system_category)); } } return reinterpret_cast<object *>(pobj); }
void WINAPI FiberFunc(PVOID pvParam) { PFIBERINFO pFiberInfo = (PFIBERINFO) pvParam; /* Stores a value in the calling fiber's fiber local storage (FLS) slot * for the specified FLS index. * Each fiber has its own slot for each FLS index. */ FlsSetValue(g_dwSlot, TEXT("Computation")); LogMessage(TEXT("entering computation...")); // Update the window showing which fiber is executing. SetDlgItemText(pFiberInfo->hwnd, IDC_FIBER, TEXT("Recalculation")); // Get the current count in the EDIT control. int nCount = GetDlgItemInt(pFiberInfo->hwnd, IDC_COUNT, NULL, FALSE); // Count from 0 to nCount, updating the STATIC control. for (int x = 0; x <= nCount; x++) { // UI events have higher priority than counting. // If there are any UI events, handle them ASAP. /* Retrieves the type of messages found in the calling thread's message queue. */ if (HIWORD(GetQueueStatus(QS_ALLEVENTS)) != 0) { // The UI fiber has something to do; temporarily // pause counting and handle the UI events. SwitchToFiber(pFiberInfo->pFiberUI); // The UI has no more events; continue counting. SetDlgItemText(pFiberInfo->hwnd, IDC_FIBER, TEXT("Recalculation")); } // Update the STATIC control with the most recent count. SetDlgItemInt(pFiberInfo->hwnd, IDC_ANSWER, x, FALSE); // Sleep for a while to exaggerate the effect; remove // the call to Sleep in production code. Sleep(200); } // Indicate that counting is complete. pFiberInfo->bps = BPS_DONE; // Reschedule the UI thread. When the UI thread is running // and has no events to process, the thread is put to sleep. // NOTE: If we just allow the fiber function to return, // the thread and the UI fiber die -- we don't want this! SwitchToFiber(pFiberInfo->pFiberUI); }
ZyanStatus ZyanThreadTlsSetValue(ZyanThreadTlsIndex index, void* data) { if (!FlsSetValue(index, data)) { const DWORD error = GetLastError(); if (error == ERROR_INVALID_PARAMETER) { return ZYAN_STATUS_INVALID_ARGUMENT; } return ZYAN_STATUS_BAD_SYSTEMCALL; } return ZYAN_STATUS_SUCCESS; }
void __cdecl __detached_routine_wrapper(IN void *param) { tt_thread_t *thread = (tt_thread_t *)param; tt_thread_ntv_t *sys_thread = &thread->sys_thread; if (tt_g_numa_node_id_thread != TT_NUMA_NODE_ID_UNSPECIFIED) { __thread_bind_numa(sys_thread->h_thread, (USHORT)tt_g_numa_node_id_thread); } if (FlsSetValue(tt_g_thread_fls_index, (LPVOID)thread) == 0) { TT_ERROR_NTV("fail to set thread private data"); return; } __thread_on_create(thread); thread->routine(thread->param); }
tt_result_t tt_thread_create_local_ntv(IN tt_thread_t *thread) { tt_thread_ntv_t *sys_thread = &thread->sys_thread; if (tt_g_numa_node_id_thread != TT_NUMA_NODE_ID_UNSPECIFIED) { __thread_bind_numa(GetCurrentThread(), (USHORT)tt_g_numa_node_id_thread); } TT_ASSERT(FlsGetValue(tt_g_thread_fls_index) == NULL); if (FlsSetValue(tt_g_thread_fls_index, (LPVOID)thread) == 0) { TT_ERROR_NTV("fail to set thread private data"); return TT_FAIL; } __thread_on_create(thread); return TT_SUCCESS; }
WINBOOL WINAPI TlsSetValue (DWORD id, LPVOID p) { return FlsSetValue (id, p); }
int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int) { // Counter fiber execution context PVOID pFiberCounter = NULL; // Convert this thread to a fiber. /* Converts the current thread into a fiber. * You must convert a thread into a fiber * before you can schedule other fibers. */ g_FiberInfo.pFiberUI = ConvertThreadToFiber(NULL); /* Allocates a fiber local storage (FLS) index. * Any fiber in the process can subsequently use this index * to store and retrieve values that are local to the fiber. */ g_dwSlot = FlsAlloc(LogMessage); FlsSetValue(g_dwSlot, TEXT("UI fiber")); // Create the application's UI window. g_FiberInfo.hwnd = CreateDialog(hinstExe, MAKEINTRESOURCE(IDD_COUNTER), NULL, Dlg_Proc); // Update the window showing which fiber is executing. SetDlgItemText(g_FiberInfo.hwnd, IDC_FIBER, TEXT("User interface")); // Initially, there is no background processing to be done. g_FiberInfo.bps = BPS_DONE; // While the UI window still exists... BOOL fQuit = FALSE; while (!fQuit) { // UI messages are higher priority than background processing. MSG msg; /* Dispatches incoming sent messages, checks * the thread message queue for a posted message, * and retrieves the message (if any exist). * PM_REMOVE 0x0001 * Messages are removed from the queue after processing by PeekMessage. */ if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // If a message exists in the queue, process it. /* Determines whether a message is intended * for the specified dialog box and, * if it is, processes the message. * hDlg [in] Type: HWND A handle to the dialog box. * lpMsg [in] Type: LPMSG A pointer to an MSG structure * that contains the message to be checked. */ if (!IsDialogMessage(g_FiberInfo.hwnd, &msg)) { /* Translates virtual-key messages into character messages. * The character messages are posted to the calling thread's message queue, * to be read the next time the thread calls the GetMessage or PeekMessage function */ TranslateMessage(&msg); /* Dispatches a message to a window procedure. * It is typically used to dispatch a message retrieved by the GetMessage function. */ DispatchMessage(&msg); } fQuit = (msg.message == WM_QUIT); if (fQuit) { // Release FLS slot FlsFree(g_dwSlot); // The background processing must be stopped. if (pFiberCounter != NULL) { // A recalculation fiber exists; delete it DeleteFiber(pFiberCounter); pFiberCounter = NULL; } // Quit the fiber mode and return to simple thread mode ConvertFiberToThread(); g_FiberInfo.pFiberUI = NULL; } } else { // No UI msgs exist; check the state of the background processing. switch (g_FiberInfo.bps) { case BPS_DONE: // No background processing to do; wait for a UI event. /* Yields control to other threads when a thread has no other messages * in its message queue. * The WaitMessage function suspends the thread * and does not return until a new message * is placed in the thread's message queue. */ WaitMessage(); break; case BPS_STARTOVER: // User changed the count; // cancel the current background processing. if (pFiberCounter != NULL) { // A recalculation fiber exists; delete it so that // background processing starts over from the beginning. DeleteFiber(pFiberCounter); pFiberCounter = NULL; } // Convert this thread to a fiber if needed. if (g_FiberInfo.pFiberUI == NULL) g_FiberInfo.pFiberUI = ConvertThreadToFiber(NULL); LogMessage(TEXT("convert UI thread to fiber...")); // Create a new recalc fiber that starts from the beginning. pFiberCounter = CreateFiber(0, FiberFunc, &g_FiberInfo); // The background processing started; it should continue. g_FiberInfo.bps = BPS_CONTINUE; // Fall through to BPS_CONTINUE case... case BPS_CONTINUE: // Allow the background processing to execute... SwitchToFiber(pFiberCounter); // The background processing has been paused // (because a UI message showed up) or has been // stopped (because the counting has completed). // Update the window showing which fiber is executing. SetDlgItemText(g_FiberInfo.hwnd, IDC_FIBER, TEXT("User interface")); if (g_FiberInfo.bps == BPS_DONE) { // The background processing ran to completion. Delete the // fiber so that processing will restart next time. DeleteFiber(pFiberCounter); pFiberCounter = NULL; // Quit the fiber mode and return to simple thread mode ConvertFiberToThread(); g_FiberInfo.pFiberUI = NULL; } break; } // switch on background processing state } // No UI messages exist } // while the window still exists DestroyWindow(g_FiberInfo.hwnd); return(0); // End the application. }