关闭

Multi-Threads in COM

标签: threadsecurityfunctionsemaphoreattributesdescriptor
227人阅读 评论(0) 收藏 举报

by Alex Zhang

I am working on distributed  calculation for complex security’s pricing , which  multi-threads knowledge is crucial, so I write down some tips , notes , ticks here, it’s not academicals just a tracing for my process.

February 20th ,2009

1. Create Thread using Windows APIs

Syntax:

   1:  HANDLE CreateThread(
   2:    LPSECURITY_ATTRIBUTES lpThreadAttributes,  // pointer to security attributes
   3:    DWORD dwStackSize,                         // initial thread stack size
   4:    LPTHREAD_START_ROUTINE lpStartAddress,     // pointer to thread function
   5:    LPVOID lpParameter,                        // argument for new thread
   6:    DWORD dwCreationFlags,                     // creation flags
   7:    LPDWORD lpThreadId                         // pointer to receive thread ID
   8:  );
   9:  
Parameters: (From MSDN)
lpThreadAttributes[in, optional]

A pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If lpThreadAttributes is NULL, the handle cannot be inherited.

The lpSecurityDescriptor member of the structure specifies a security descriptor for the new thread. If lpThreadAttributes is NULL, the thread gets a default security descriptor. The ACLs in the default security descriptor for a thread come from the primary token of the creator.

Windows XP/2000:  The ACLs in the default security descriptor for a thread come from the primary or impersonation token of the creator. This behavior changed with Windows XP with SP2 and Windows Server 2003. For more information, see Remarks.

dwStackSize [in]

The initial size of the stack, in bytes. The system rounds this value to the nearest page. If this parameter is zero, the new thread uses the default size for the executable. For more information, see Thread Stack Size.

lpStartAddress [in]

A pointer to the application-defined function to be executed by the thread. This pointer represents the starting address of the thread. For more information on the thread function, see ThreadProc.

lpParameter [in, optional]

A pointer to a variable to be passed to the thread.

dwCreationFlags [in]

The flags that control the creation of the thread.

Value

Meaning

0

The thread runs immediately after creation.

CREATE_SUSPENDED
0×00000004

The thread is created in a suspended state, and does not run until the ResumeThread function is called.

STACK_SIZE_PARAM_IS_A_RESERVATION
0×00010000

The dwStackSize parameter specifies the initial reserve size of the stack. If this flag is not specified, dwStackSize specifies the commit size.

Windows 2000:  The STACK_SIZE_PARAM_IS_A_RESERVATION flag is not supported.

lpThreadId [out, optional]

A pointer to a variable that receives the thread identifier. If this parameter is NULL, the thread identifier is not returned.

Return Value

If the function succeeds, the return value is a handle to the new thread.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

Note that CreateThread may succeed even if lpStartAddress points to data, code, or is not accessible. If the start address is invalid when the thread runs, an exception occurs, and the thread terminates. Thread termination due to a invalid start address is handled as an error exit for the thread’s process. This behavior is similar to the asynchronous nature of CreateProcess, where the process is created even if it refers to invalid or missing dynamic-link libraries (DLLs).

Specially Show the “ThreadProc” Function Here:

DWORD WINAPI ThreadProc(LPVOID lpParameter); replacing ThreadProc with the name of the function.

2. Manage Thread

2.1 Resume Thread (From MSDN)

Decrements a thread’s suspend count. When the suspend count is decremented to zero, the execution of the thread is resumed.

Syntax
DWORD WINAPI ResumeThread(
  __in  HANDLE hThread
);
Parameters
hThread [in]

A handle to the thread to be restarted.

This handle must have the THREAD_SUSPEND_RESUME access right. For more information, see Thread Security and Access Rights.

Return Value

If the function succeeds, the return value is the thread’s previous suspend count.

If the function fails, the return value is (DWORD) -1. To get extended error information, call GetLastError.

2.3 Suspend Thread (From MSDN)

SuspendThread Function

Suspends the specified thread.

A 64-bit application can suspend a WOW64 thread using the Wow64SuspendThreadfunction.

Syntax
DWORD WINAPI SuspendThread(
  __in  HANDLE hThread
);
Parameters
hThread [in]

A handle to the thread that is to be suspended.

The handle must have the THREAD_SUSPEND_RESUME access right. For more information, see Thread Security and Access Rights.

Return Value

If the function succeeds, the return value is the thread’s previous suspend count; otherwise, it is (DWORD) -1. To get extended error information, use the GetLastErrorfunction.

2.4 Waiting for terminate (From MSDN)

Obviously if “ThreadProc”  hasn’t returned within 0.1 seconds then something is wrong, but that isn’t the point. The WaitForSingleObject() function solves this problem.

WINBASEAPI DWORD WINAPI WaitForSingleObject(HANDLE,DWORD);

WaitForSingleObject() waits until either the thread has terminated or the timeout value provided in the second parameter has elapsed. For this function we need the handle of the thread. MSDN recommends that all handles are closed with the CloseHandle() function before the program terminates.

2.5 Terminate Threads

Syntax
BOOL WINAPI TerminateThread(
  __inout  HANDLE hThread,
  __in     DWORD dwExitCode
);
Parameters
hThread [in, out]

A handle to the thread to be terminated.

The handle must have the THREAD_TERMINATE access right. For more information, seeThread Security and Access Rights.

dwExitCode [in]

The exit code for the thread. Use the GetExitCodeThread function to retrieve a thread’s exit value.

Return Value

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, callGetLastError.

AHA! A link  http://msdn.microsoft.com/en-us/library/ms684847(VS.85).aspx is much more than copy and paste.

3.Utilities For Synchronization

As you know , Mutex, event , lock and semaphore are  for this, what we need to do is OO it. Luckily , the laborious have done this:

For Example (From http://www.relisoft.com/Win32/active.html):

Mutex:

   1:      class Mutex
   2:      {
   3:          friend class Lock; //grant Lock object full control rights
   4:      public:
   5:          Mutex () { InitializeCriticalSection (& _critSection); }
   6:          ~Mutex () { DeleteCriticalSection (& _critSection); }
   7:      private:
   8:          void Acquire ()
   9:          {
  10:              EnterCriticalSection (& _critSection);
  11:          }
  12:          void Release ()
  13:          {
  14:              LeaveCriticalSection (& _critSection);
  15:          }
  16:          
  17:          CRITICAL_SECTION _critSection;
  18:      };

Lock:

   1:  class Lock
   2:      {
   3:      public:
   4:          // Acquire the state of the semaphore
   5:          Lock ( Mutex & mutex )
   6:              : _mutex(mutex)
   7:          {
   8:              _mutex.Acquire();
   9:          }
  10:          // Release the state of the semaphore
  11:          ~Lock ()
  12:          {
  13:              _mutex.Release();
  14:          }
  15:      private:
  16:          Mutex & _mutex;
  17:      };
 

Event:

   1:      class Event
   2:      {
   3:      public:
   4:          Event ()
   5:          {
   6:              // start in non-signaled state (red light)
   7:              // auto reset after every Wait
   8:              _handle = CreateEvent (0, FALSE, FALSE, 0);
   9:          }
  10:          ~Event ()
  11:          {
  12:              CloseHandle (_handle);
  13:          }
  14:          // put into signaled state
  15:          void Release () { SetEvent (_handle); }
  16:          void Wait ()
  17:          {
  18:              // Wait until event is in signaled (green) state
  19:              WaitForSingleObject (_handle, INFINITE);
  20:          }
  21:          operator HANDLE () { return _handle; }
  22:      private:
  23:          HANDLE _handle;
  24:      };

Semaphore VS Mutex:

http://ju-kevin.spaces.live.com/blog/cns!907BD90CD611C0C7!221.entry?wa=wsignin1.0&sa=531454868

Thread:

       #define DCalc_Log  //

       #define QL_REQUIRE //

    class Thread
    {
    public:
        Thread ( unsigned ( __stdcall * pFun) (void* arg), void* pArg)
        {
            _handle = (HANDLE)CreateThread (
                0, // Security attributes
                0, // Stack size
                pFun,
                pArg,
                CREATE_SUSPENDED,
                &_tid);
            QL_REQUIRE(_handle!=0,"Creat Thread Failure");

            DCalc_Log("Creat Thread OK , tid=%d",_tid);
        }
        virtual ~Thread ()
        {
            DCalc_Log("Thread Release");

            HRESULT hRes(S_OK);
            GetExitCodeThread(_handle, (LPDWORD) &hRes);
            CloseHandle (_handle); 

            DCalc_Log("Thread %d exit code = %un",_tid, hRes);
        }
        void Resume ()
        {
            ResumeThread (_handle);
        }
        void WaitForDeath ()
        {
            WaitForSingleObject (_handle, INFINITE);
        }
    private:
        HANDLE      _handle;
        unsigned  _tid;
    };
    

4. Com Multi-Thread Model

    As of the application environment (COM DLL),  some knowledge about COM multi-thread model is important.

    see  FW:COM Multi-Thread Model

5. My Application

   Base Class:

   1:      class DCalcThread
   2:      {
   3:      public:
   4:          DCalcThread ()
   5:              : _thread (ThreadEntry, this)
   6:          {
   7:          }
   8:  
   9:          virtual void RunDCalc () = 0;    
  10:          virtual ~DCalcThread () {}
  11:  
  12:      protected:
  13:          struct COMEnvSetting 
  14:          {
  15:              COMEnvSetting()
  16:              {
  17:  //                ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  18:              }
  19:              ~COMEnvSetting()
  20:              {
  21:  //                ::CoUninitialize();
  22:              }
  23:          };
  24:          static unsigned __stdcall ThreadEntry (void *pArg)
  25:          {
  26:  //            COMEnvSetting _envSetter;
  27:              DCalcThread * pActive = (DCalcThread *) pArg;
  28:              pActive->RunDCalc();
  29:  
  30:              return 0;            
  31:          };
  32:          
  33:          int             _isDying;
  34:          Thread          _thread;
  35:      };

  Sub Classes:

    Sample subclass A:

   1:     #define  DCalc_Log  //
   2:      class DCalcCNPV: public DCalcThread
   3:      {
   4:      public:
   5:          DCalcCNPV();
   6:          ~DCalcCNPV();
   7:  
   8:          void RunDCalc ()
   9:          {
  10:              DCalc_Log("Calc NPV");
  11:          }
  12:      private:
  13:      };
  Sample subclass B:
   1:    #define DCalc_Log  //
   2:      class DCalcCNPV: public DCalcThread
   3:      {
   4:      public:
   5:          DCalcCNPV();
   6:          ~DCalcCNPV();
   7:  
   8:          void RunDCalc ()
   9:          {
  10:              DCalc_Log("Calc NPV");
  11:          }
  12:      private:
  13:      };
 
  

I type some links here , making up for the lost of my re-product:

http://www.relisoft.com/Win32/active.html

http://www.geocities.com/samuel_super_camel/MultiThreadingTutorial.htm

http://www.cs.rpi.edu/academics/courses/netprog/WindowsThreads.html

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:54890次
    • 积分:1371
    • 等级:
    • 排名:千里之外
    • 原创:94篇
    • 转载:1篇
    • 译文:0篇
    • 评论:5条
    最新评论