More on threads - PowerPoint PPT Presentation

1 / 24
About This Presentation
Title:

More on threads

Description:

It would not work with const member functions. ... One more parameter (perhaps, with default value) can be added to create thread ... – PowerPoint PPT presentation

Number of Views:61
Avg rating:3.0/5.0
Slides: 25
Provided by: christoph435
Category:
Tags: more | threads | usage

less

Transcript and Presenter's Notes

Title: More on threads


1
More on threads
  • Konstantin Bukin
  • CSE791 Advanced Windows Programming
  • Summer 2001

2
  • MFCs thread implementation MFC Internals by G.
    Shepherd, S. Wingo
  • Executing a class member in its own thread (C/C
    Users Journal, Vol.17, No. 12, p. 57)
  • Singleton Creation the thread-safe way (C/C
    Users Journal, Vol.17, No. 10, p. 43)
  • Improving performance with thread-private heaps
    (C/C Users Journal, Vol.17, No. 9, p. 50)

3
Threads thread creation
  • CWinThread AFXAPI AfxBeginThread(AFX_THREADPROC
    pfnThreadProc, LPVOID pParam,
  • int nPriority, UINT nStackSize,
  • DWORD dwCreateFlags, LPSECURITY_ATTRIBUTES
    lpSecurityAttrs)
  • CWinThread AFXAPI AfxBeginThread(CRuntimeClass
    pThreadClass,
  • int nPriority, UINT nStackSize,
  • DWORD dwCreateFlags, LPSECURITY_ATTRIBUTES
    lpSecurityAttrs)

4
AfxBeginThread()
  • CWinThread pThread new CWinThread(pfnThreadPro
    c, pParam)
  • if (!pThread-gtCreateThread( dwCreateFlags
    CREATE_SUSPENDED, nStackSize, lpSecurityAttrs))
  • pThread-gtDelete()
  • return NULL
  • VERIFY(pThread-gtSetThreadPriority(nPriority))
  • if (!(dwCreateFlags CREATE_SUSPENDED))
  • VERIFY(pThread-gtResumeThread() ! (DWORD)-1)
  • return pThread
  • Its all about CWinThread and its CreateThread()

5
CWinThread
  • class CWinThread public CCmdTarget
  • public
  • CWinThread()
  • CWinThread(AFX_THREADPROC pfnThreadProc, LPVOID
    pParam)
  • BOOL CreateThread(DWORD dwCreateFlags 0, UINT
    nStackSize 0,
  • LPSECURITY_ATTRIBUTES lpSecurityAttrs NULL)
  • virtual BOOL InitInstance()
  • virtual int Run()
  • virtual BOOL PreTranslateMessage(MSG pMsg)
  • virtual BOOL PumpMessage() // low level
    message pump
  • virtual BOOL OnIdle(LONG lCount) //return TRUE
    if more idle processing
  • virtual BOOL IsIdleMessage(MSG pMsg) //checks
    for special messages
  • private
  • LPVOID m_pThreadParams //generic parameters
    passed to starting function
  • AFX_THREADPROC m_pfnThreadProc
  • HANDLE m_hThread // this thread's HANDLE

6
CWinThreadCreateThread()

  • Initialization of _AFX_THREAD_STARTUP startup
    structure
  • m_hThread (HANDLE)_beginthreadex(lpSecurityAttr
    s,
  • nStackSize, _AfxThreadEntry, startup,
    dwCreateFlags
  • CREATE_SUSPENDED, (UINT) m_nThreadID)
  • ResumeThread(), ResumeThread(m_hThread)
  • WaitForSingleObject(startup.hEvent, INFINITE)
  • _AfxThreadEntry()
  • Cleans up after creating child thread
  • SetEvent(startup.hEvent2)
  • _AfxThreadEntry() keeps running
  • Pic

7
_AfxThreadEntry()

  • Copies and initializes threads specific data (a
    lot of them)
  • Unblocks parent thread
  • WaitForSingleObject(startup.hEvent2, INFINITE)
  • Back to CWinThreadCreateThread()
  • if (pThread-gtm_pfnThreadProc ! NULL)
  • nResult(pThread-gtm_pfnThreadProc)(pThread-gtm_pT
    hreadParams)
  • else if (!pThread-gtInitInstance())
  • nResultpThread-gtExitInstance()
  • else
  • pThread-gt Run()
  • //clean up and shutdown thread
  • AfxEndThread(nResult)
  • Pic

8
A time line for Mom and Junior threads
9
CWinThreadRun()
  • int CWinThreadRun()
  • ASSERT_VALID(this)
  • // for tracking the idle time state
  • BOOL bIdle TRUE
  • LONG lIdleCount 0
  • // acquire and dispatch messages until a WM_QUIT
    message is received.
  • for ()
  • // phase1 check to see if we can do idle work
  • while (bIdle !PeekMessage(m_msgCur, NULL,
    NULL, NULL, PM_NOREMOVE))
  • // call OnIdle while in bIdle state
  • if (!OnIdle(lIdleCount))
  • bIdle FALSE // assume "no idle" state
  • // phase2 pump messages while available
  • do // pump message, but quit on WM_QUIT
  • if (!PumpMessage())
  • return ExitInstance()
  • // reset "no idle" state after pumping
    "normal" message
  • if (IsIdleMessage(m_msgCur))
  • bIdle TRUE

10
CWinThreadOnIdle()
  • BOOL CWinThreadOnIdle(LONG lCount)
  • if (lCount lt 0)
  • // send WM_IDLEUPDATECMDUI to the main window
  • // send WM_IDLEUPDATECMDUI to all frame window
  • else if (lCount gt 0)
  • //Call AfxLockTempMaps/AfxUnlockTempMaps
  • //to free maps, DLLs, etc
  • return lCount lt 0 //nothing more to do if
    lCount gt 0

11
Executing a class member in its own thread
  • Motivation
  • class Task
  • class Processor
  • public
  • void SubmitTask(Task t)
  • private
  • usigned ProcessTask(void data)
  • stdqueueltTaskgt m_tasks
  • Problem
  • WINBASEAPI HANDLE WINAPI CreateThread(LPSECURITY_
    ATTRIBUTES lpSecurityAttributes, DWORD
    dwStackSize, LPTHREAD_START_ROUTINE
    lpStartAddress, LPVOID lpParameter, WDORD
    dwCreationFlags, LPDWORD lpThreadID)

12
Usage
  • Foo f
  • runInThread(f, Foomember, args)

13
Solution 1
  • template ltclass Objectgt
  • void runInThread(Object obj, DWORD(WINAPI
    ObjecgmemberFunc)(void), HANDLE handle0,
    DWORD id0)
  • using stdruntime_error
  • DWORD (WINAPI threadFunc)(void)
  • //pass object this pointer via thread void
    pointer
  • void thisPointersatic_castltvoidgt(obj)
  • //copy class member pointer to global function
    pointer
  • reinterpret_castltlonggt(threadFunc)reinterpre
    t_castltlonggt(memberFunc)
  • DWORD threadId -1
  • HANDLE resultCreateThread(0, 0, threadFunc,
    thisPointer, 0, threadId)
  • if (result 0) throw runtime_error(CreateThrea
    d failed)
  • if (handle) handleresult
  • if (id) id threadId

14
Problems of solution 1
  • The solution relies on WINAPI calling convention
    (__stdcall) which is not always possible. It
    would not work with const member functions.
  • The solution assumes (incorectly) that non-static
    member function will always revieve their this
    pointer as the first argument on the call stack.
  • Using the void thread argument to pass the
    object this pointer prevents the member function
    from taking any parameters. Its a big limitation.

15
Solution 2
  • template ltclass Object, class MemberFunc, class
    Paramgt
  • class ThreadableMember
  • private
  • Object m_instance
  • MemberFunc m_member
  • struct ThrdArg
  • Object object
  • MemberFunc memberFunc
  • Param param
  • ThrdArg(Object o, MemberFunc m, const Param
    p)
  • object(o), memberFunc(m), param(p)
  • static DWORD WINAPI ThreadFunc(LPVOID v)
  • stdauto_ptrltThrdArggt arg(reinterpret_castltThr
    dArggt(v)
  • return ((arg-gtobject)-gt(arg-gtmemberFunc))(arg-
    gtparam)

16
Solution 2 (cont.)
  • public
  • ThreadableMember(Object instance, MemberFunc
    member) m_instance(instance), m_member(member)
  • void run(const Param param, HANDLE handle0,
    DWORD id0)
  • DWORD thrdId-1
  • ThrArg thrdArg new ThrArg(m_instance,
    m_member, param)
  • HANDLE result CreateThread(0, 0, ThreadFunc,
    thrdArg,0,thrdId)
  • if (result ! 0)
  • if (handle) handleresult
  • if (id) id thrdId
  • else
  • delete thrdArg
  • throw stdtuntime_error(CreateThread
    failed)

17
Usage
  • Foo f
  • ThreadableMemberltFoo, DWORD(Foo)(char),
    chargt
  • m(f, FooBar1)
  • m.run(alpha)
  • Helper function
  • template ltclass Object, class MemberFunc, class
    Paramgt
  • inline void runInThread(Object instance,
    MemberFunc member,
  • const Param param, HANDLE handle0, DWORD
    id0)
  • ThreadableMemberltObject,MemberFunc,Paramgt
    m(instance, member)
  • m.run(param, handle, id)
  • runInThread(f, FooBar2, class Bar2Param)

18
Issues
  • Take care of you data members
  • Thread security and stack-size can be added as a
    parameters to Threadablerun() and runInThread()
  • One more parameter (perhaps, with default value)
    can be added to create thread in a suspended
    state

19
Singleton Creation in a Thread-safe Way
  • class Singleton
  • public
  • static Singleton instance()
  • if (!m_instance)
  • m_instance new Singleton
  • return m_instance
  • protected
  • Singleton()
  • private
  • static Singleton m_instance
  • Singleton Singletonm_instance 0

20
Problem
  • Thread may be preempted by the operating system
    during if (!m_instance). Then another thread
    gets control. Since the first thread did not
    finished creation of the m_instance, the second
    thread evaluates (!m_instance) as true and
    creates another singleton.

21
Solution
  • class Singleton
  • public
  • static Singleton instance()
  • m_key.Lock()
  • if (!m_instance)
  • m_instance new Singleton
  • return m_instance
  • m_key.Unlock()
  • protected
  • Singleton()
  • private
  • static Singleton m_instance
  • static CCriticalSection m_key
  • Singleton Singletonm_instance 0
  • CCriticalSection Singletonm_key
  • Different from the code in the article

22
Heaps
  • Lets compare these two functions
  • void SomeFunc(Foo bar)
  • Obj pObjnew Obj
  • pObj-gtHadler(bar)
  • delete pObj
  • void SomeFunc(Foo bar)
  • Obj obj
  • obj.Hadler(bar)

23
  • Possible memory leak (can be solved with
    auto_ptr)
  • Heap is a shared resource, which has to be
    synchronized
  • The more interdependences between threads the
    less scalable application

24
Process heap and Private heap
  • When a new Win32 process starts up, OS creates a
    default Process heap. GetProcessHeap() returns
    its handle
  • HANDLE HeapCreate(DWORD flOptions, DWORD
    dwInitialSize, DWORD dwMaximumSize) creates
    Private heap
  • LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags,
    DWORD dwButes)
  • BOOL HeapFree(HANDLE hHeap, DWORD dwFlags,
    LPVOID lpMem)
  • BOOL HeapDestroy(HANDLE hHeap)
  • Serialization is turned on by default, but can be
    turned off by using a flag value of
    HEAP_NO_SERIALIZE
  • Access to the process heap in an multithreaded
    application must be serialized.
Write a Comment
User Comments (0)
About PowerShow.com