• ioftpd 之 tls


    //z 2014-05-12 11:07:22 L.233'46358 BG57IV3@XCL T3657726611.K.F1390913624[T7,L222,R4,V354]
    //z 2014-05-12 10:21:38 L.233'49102 T1496279357.K[T6,L217,R4,V263]
    //z 全局静态变量,所有线程共享。在线程开始之前就分配好。
    static DWORD		dwThreadDataTlsIndex;
    //z 为线程分配 Tls slot
    dwThreadDataTlsIndex	= TlsAlloc();
    
    //z tls data
    typedef struct _THREADDATA
    {
    	BOOL				bReuse;
    	HANDLE				hEvent;
    	LONG volatile       lBlockingCount;
    	LPOUTPUT_THEME      lpTheme;
    	INT32               iAutoTheme;
    	struct _FTP_USER   *lpFtpUser;
    	struct _THREADDATA *lpNext, *lpPrev;
    	LPRESOURCE_DTOR		lpDestructor;
    
    } THREADDATA, *LPTHREADDATA;
    
    //z 创建 worker thread,为各个线程分配配置 tls data
    LPTHREADDATA	lpThreadData;
    lpThreadData	= Allocate("Thread:Data", sizeof(THREADDATA));
    ZeroMemory(lpThreadData, sizeof(*lpThreadData));
    
    //z 创建 worker thread 线程。
    hThread	= CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE)WorkerThread, lpThreadData, 0, &dwThreadId);
    
    //	Store TLS data
    TlsSetValue(dwThreadDataTlsIndex, lpThreadData);
    
    //z 使用 tls data 的例子
    LPOUTPUT_THEME GetTheme()
    {
    	LPTHREADDATA	lpThreadData;
    
    	lpThreadData	= (LPTHREADDATA)TlsGetValue(dwThreadDataTlsIndex);
    	if (!lpThreadData) return NULL;
    	return lpThreadData->lpTheme;
    }
    
    VOID SetFtpUser(LPFTPUSER lpFtpUser)
    {
    	LPTHREADDATA	lpThreadData;
    
    	lpThreadData	= (LPTHREADDATA)TlsGetValue(dwThreadDataTlsIndex);
    	if (!lpThreadData) return;
    	lpThreadData->lpFtpUser = lpFtpUser;
    }
    
    
    LPFTPUSER GetFtpUser()
    {
    	LPTHREADDATA	lpThreadData;
    
    	lpThreadData	= (LPTHREADDATA)TlsGetValue(dwThreadDataTlsIndex);
    	if (!lpThreadData) return NULL;
    	return lpThreadData->lpFtpUser;
    }
    
    //z 使用完毕,清理tls资源。
    lpThreadData = (LPTHREADDATA)TlsGetValue(dwThreadDataTlsIndex);
    if (lpThreadData)
    {
    	Free(lpThreadData);
    }
    TlsFree(dwThreadDataTlsIndex);
    
    //z ioftpd 使用了 thread pool (线程池)的方式,在等待 job 时,各个线程使用的等待时间为:
    
    //z GetCurrentThreadId() 得到当前线程的 id
    //z The CreateFiber and ConvertThreadToFiber functions return the fiber address when the fiber is created.
    //z The GetCurrentFiber macro allows you to retrieve the address at any other time.
    //z GetTickCount()系统启动后所经历的时间
    //	Set random seed
    srand(GetCurrentThreadId() + GetTickCount() + (DWORD)GetCurrentFiber());
    
    // use a delay of between 5 and 10 seconds
    dwDelay = (DWORD) ((double)rand() / (RAND_MAX + 1) * 5000 + 5000);

    来自微软的例子
    Using Thread Local Storage
    Thread local storage (TLS) enables multiple threads of the same process to use an index allocated by the TlsAlloc function to store and retrieve a value that is local to the thread. In this example, an index is allocated when the process starts. When each thread starts, it allocates a block of dynamic memory and stores a pointer to this memory in the TLS slot using the TlsSetValue function. The CommonFunc function uses the TlsGetValue function to access the data associated with the index that is local to the calling thread. Before each thread terminates, it releases its dynamic memory. Before the process terminates, it calls TlsFree to release the index.

    #include <windows.h>
    #include <stdio.h>
    
    #define THREADCOUNT 4
    DWORD dwTlsIndex;
    
    VOID ErrorExit(LPSTR);
    
    VOID CommonFunc(VOID)
    {
       LPVOID lpvData;
    
    // Retrieve a data pointer for the current thread.
    
       lpvData = TlsGetValue(dwTlsIndex);
       if ((lpvData == 0) && (GetLastError() != ERROR_SUCCESS))
          ErrorExit("TlsGetValue error");
    
    // Use the data stored for the current thread.
    
       printf("common: thread %d: lpvData=%lx
    ",
          GetCurrentThreadId(), lpvData);
    
       Sleep(5000);
    }
    
    DWORD WINAPI ThreadFunc(VOID)
    {
       LPVOID lpvData;
    
    // Initialize the TLS index for this thread.
    
       lpvData = (LPVOID) LocalAlloc(LPTR, 256);
       if (! TlsSetValue(dwTlsIndex, lpvData))
          ErrorExit("TlsSetValue error");
    
       printf("thread %d: lpvData=%lx
    ", GetCurrentThreadId(), lpvData);
    
       CommonFunc();
    
    // Release the dynamic memory before the thread returns.
    
       lpvData = TlsGetValue(dwTlsIndex);
       if (lpvData != 0)
          LocalFree((HLOCAL) lpvData);
    
       return 0;
    }
    
    int main(VOID)
    {
       DWORD IDThread;
       HANDLE hThread[THREADCOUNT];
       int i;
    
    	// Allocate a TLS index.
        if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
          ErrorExit("TlsAlloc failed");
    
    	// Create multiple threads.
       for (i = 0; i < THREADCOUNT; i++)
       {
          hThread[i] = CreateThread(NULL, // default security attributes
             0,                           // use default stack size
             (LPTHREAD_START_ROUTINE) ThreadFunc, // thread function
             NULL,                    // no thread function argument
             0,                       // use default creation flags
             &IDThread);              // returns thread identifier
    
       // Check the return value for success.
          if (hThread[i] == NULL)
             ErrorExit("CreateThread error
    ");
       }
    
       for (i = 0; i < THREADCOUNT; i++)
          WaitForSingleObject(hThread[i], INFINITE);
    
       TlsFree(dwTlsIndex);
    
       return 0;
    }
    
    VOID ErrorExit (LPSTR lpszMessage)
    {
       fprintf(stderr, "%s
    ", lpszMessage);
       ExitProcess(0);
    }

    //另一个例子
    //TlsDemo.c
    //compile:cl.exe TlsDemo.c
    //下面注释为其执行顺序
    #include <windows.h>
    
    DWORD g_dwTlsIndex = -1;
    
    unsigned TlsProc1(void *unuse)
    {
        LPVOID lpValue = NULL;
        TlsSetValue(g_dwTlsIndex,(PVOID)1234);//2
        Sleep(1000);
        lpValue = TlsGetValue(g_dwTlsIndex);  //5
    
        printf("TlsProc1:%d/n",(DWORD)lpValue);
        return 0;
    }
    
    unsigned TlsProc2(void *unuse)
    {
        LPVOID lpValue = NULL;
        TlsSetValue(g_dwTlsIndex,(PVOID)4567);//3
        lpValue = TlsGetValue(g_dwTlsIndex);  //4
    
        printf("TlsProc2:%d/n",(DWORD)lpValue);
        return 0;
    }
    
    int main(void)
    {
        g_dwTlsIndex = TlsAlloc(); // 1
        _beginthreadex(NULL,0,TlsProc1,NULL,0,NULL);
        _beginthreadex(NULL,0,TlsProc2,NULL,0,NULL);
        _getch();
    
    	TlsFree(g_dwTlsIndex);
    }
    静态TLS使用__declspec(thread)修饰符声明全局或静态(static)的TLS变量,TLS变量将被编译器放到.tls段中。


    系统在载入应用程序时,将根据.tls段的大小分配足够的内存来保存所有的静态TLS变量。若进程新建了一个线程,那么系统也要为新线程分配一样大的内存来保存的静态TLS变量。如果在加载一个DLL时,DLL中也存在静态TLS变量,那么系统会为进程中的所有线程扩展其TLS的内存容量。如果卸载一个DLL时,DLL中存在静态TLS变量,那么系统会为进程中的所有线程缩减其TLS的内存容量。(P571)

    //z 2014-05-12 11:53:10 L.233'43610 BG57IV3@XCL T3557450373.K.F1390913624[T9,L474,R4,V384]
    //TlsDemo.c
    //compile:cl.exe TlsDemo.c
    //下面注释为其执行顺序
    #include <windows.h>
    
    __declspec(thread) DWORD g_dwTlsValue = 0;
    
    unsigned TlsProc1(void *unuse)
    {
        g_dwTlsValue = 0x12345678;  // 1
    
        Sleep(1000);
    
        printf("TlsProc1:0x%08x/n",g_dwTlsValue); //4
    
        return 0;
    }
    
    unsigned TlsProc2(void *unuse)
    {
        g_dwTlsValue = 0x87654321;   //2
    
        printf("TlsProc2:0x%08x/n",g_dwTlsValue);//3
    
        return 0;
    }
    
    int main(void)
    {
        _beginthreadex(NULL,0,TlsProc1,NULL,0,NULL);
        _beginthreadex(NULL,0,TlsProc2,NULL,0,NULL);
        _getch();
    }

    //z 2014-05-12 11:53:10 L.233'43610 BG57IV3@XCL T3557450373.K.F1390913624[T9,L474,R4,V384]

    @IS2120#CNBLOGS.T2169364049[T1,L65,R1,V259]:备忘
    $ € ₤ ₭ ₪ ₩ ₮ ₦ ₱ ฿ ₡ ₫ ﷼ ¥ ﷼ ₫ ₡ ฿ ₱ ₦ ₮ ₩ ₪ ₭ ₤ € $
  • 相关阅读:
    自定义事件类LoadEvent
    Sound
    (this.stage.getChildAt(0) as MovieClip).arr[1]
    menu菜单栏
    排列图片,自动换行
    滚动条
    滚动条使用示例
    载入类 举例
    舞台和主时间轴的关系
    自定义载入类(如图片、XML)
  • 原文地址:https://www.cnblogs.com/IS2120/p/6745660.html
Copyright © 2020-2023  润新知