Konstantin Bukin CSE791 – Advanced Windows Programming Summer 2001

Slides:



Advertisements
Similar presentations
Process A process is usually defined as an instance of a running program and consists of two components: A kernel object that the operating system uses.
Advertisements

. Smart Pointers. Memory Management u One of the major issues in writing C/C++ code is managing dynamically allocated memory u Biggest question is how.
1 3. Controlling Robot Car by Wireless Sensor The ultimate objective of the project is to control the car motion using the steering wheel The only connection.
Project 2 教學. Synchronization Functions in Windows HANDLE WINAPI CreateSemaphore ( __in_opt LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, __in LONG lInitialCount,
Unix Threads operating systems. User Thread Packages pthread package mach c-threads Sun Solaris3 UI threads Kernel Threads Windows NT, XP operating systems.
Threads CNS What is a thread?  an independent unit of execution within a process  a "lightweight process"  an independent unit of execution within.
© 2004, D. J. Foreman 2-1 Concurrency, Processes and Threads.
Windows Threading Colin Roby Jaewook Kim
CSE 380 – Computer Game Programming Render Threading Portal, by Valve,
Win32 Programming Lesson 9: Jobs & Thread Basics.
MultiThreaded Applications. What is Multithreaded Programming? Having your software appear to perform multiple tasks in parallel –Individual paths of.
Lecture 11 Dynamic link libraries. Differences between static libraries and DLLs In static library code is added to the executable. In DLL, the code is.
Threads and Thread Synchronization Advanced Windows Programming Series 1.
1 Confidential Enterprise Solutions Group Process and Threads.
Windows thread programming
Win32 Programming Lesson 18: More Memory Mapped Files and the HEAP (Finally, cool stuff!)
CS 346 – Chapter 4 Threads –How they differ from processes –Definition, purpose Threads of the same process share: code, data, open files –Types –Support.
Includes slides from course CS194 at UC Berkeley, by prof. Katherine Yelick Shared Memory Programming Pthreads: an overview Ing. Andrea Marongiu
Multithreading GSP-420.
Practical Sockets and Threads Derek Weitzel. Windows Threads Concurrent processing Concurrent processing Windows Create Thread Windows Create Thread HANDLE.
Shan Gao Fall 2007 Department of Computer Science Georgia State University.
Fall 2002 CS 325 Class Notes Page 1 Lecture 25 Today –exec() in Unix –CreateProcess in Windows Announcements.
Windows Threading Colin Roby Jaewook Kim.
Threads and Thread Synchronization in MFC By Gregory Mortensen CSIS 4330 Advanced Windows Programming.
CS241 Systems Programming Discussion Section Week 2 Original slides by: Stephen Kloder.
Overview of Previous Lesson(s) Over View  Windows Programming  WinMain()  Where execution of the program begins and basic program initialization is.
CS241 Systems Programming Discussion Section Week 2 Original slides by: Stephen Kloder.
Memory Management in Java Mr. Gerb Computer Science 4.
CSE 332: C++ Exceptions Motivation for C++ Exceptions Void Number:: operator/= (const double denom) { if (denom == 0.0) { // what to do here? } m_value.
Threads and Thread Synchronization. Introduction In windows the basic unit of execution is the thread. It is the smallest schedulable unit of execution.
7/9/ Realizing Concurrency using Posix Threads (pthreads) B. Ramamurthy.
Lecture Lecture 25 Review of Last Lecture DLL’s DLL’s Processes Processes Threads Threads Memory Management Memory Management.
Window Threads Chapter 7 Windows Thread Management.
Threads Some of these slides were originally made by Dr. Roger deBry. They include text, figures, and information from this class’s textbook, Operating.
Memory Management.
Chapter 3: Windows7 Part 5.
Message Handling in MFC
Win32 Threads and Thread Synchronization
Process concept.
Module 9: Memory and Resource Management
Realizing Concurrency using the thread model
Jim Fawcett CSE681 – Software Modeling & Analysis Fall 2002
Windows Programming Lecture 09.
Concurrency, Processes and Threads
Lecture 7 : Multithread programming
CS399 New Beginnings Jonathan Walpole.
Thread Programming.
Operating System Concepts 7th Edition Abraham SilBerschatz Peter Baer Galvin Greg Gagne Prerequisite: CSE212.
Threads and Thread Synchronization
Windows Concurrency Concepts and APIs
Processes in Unix, Linux, and Windows
Chapter 3: Windows7 Part 5.
Realizing Concurrency using Posix Threads (pthreads)
Chapter 4: Threads.
Processes in Unix, Linux, and Windows
System Structure and Process Model
CSE 432 Presentation GoF: Factory Method PH: “To Kill a Singleton”
CSE 410, Spring 2008 Computer Systems
Realizing Concurrency using the thread model
Chapter 05. Multithread.
CHAPTER 4:THreads Bashair Al-harthi OPERATING SYSTEM
Windows Development Dynadata Copyright, 2014 © DynaData S.A. 1/49.
Concurrency, Processes and Threads
Realizing Concurrency using Posix Threads (pthreads)
Processes in Unix and Windows
Outline Chapter 2 (cont) Chapter 3: Processes Virtual machines
26.
Outline Chapter 3: Processes Chapter 4: Threads So far - Next -
四時讀書樂 (春) ~ 翁森 山光照檻水繞廊,舞雩歸詠春風香。 好鳥枝頭亦朋友,落花水面皆文章。 蹉跎莫遣韶光老,人生唯有讀書好。
Memory allocation.
Presentation transcript:

Konstantin Bukin CSE791 – Advanced Windows Programming Summer 2001 More on threads Konstantin Bukin CSE791 – Advanced Windows Programming Summer 2001

MFC’s 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)

Thread’s thread creation CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority, UINT nStackSize, DWORD dwCreateFlags, LPSECURITY_ATTRIBUTES lpSecurityAttrs); CWinThread* AFXAPI AfxBeginThread(CRuntimeClass* pThreadClass,

AfxBeginThread() It’s all about CWinThread and it’s CreateThread() CWinThread* pThread = new CWinThread(pfnThreadProc, pParam); if (!pThread->CreateThread( dwCreateFlags | CREATE_SUSPENDED, nStackSize, lpSecurityAttrs)) { pThread->Delete(); return NULL; } VERIFY(pThread->SetThreadPriority(nPriority)); if (!(dwCreateFlags & CREATE_SUSPENDED)) VERIFY(pThread->ResumeThread() != (DWORD)-1); return pThread; It’s all about CWinThread and it’s CreateThread()

CWinThread class CWinThread : public CCmdTarget { public: 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 } Back to AfxBeginThread()

CWinThread::CreateThread() Initialization of _AFX_THREAD_STARTUP startup structure m_hThread = (HANDLE)_beginthreadex(lpSecurityAttrs, 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

_AfxThreadEntry() Copies and initializes thread’s specific data (a lot of them) Unblocks parent thread ::WaitForSingleObject(startup.hEvent2, INFINITE) Back to CWinThread::CreateThread() if (pThread->m_pfnThreadProc != NULL) nResult=(*pThread->m_pfnThreadProc)(pThread->m_pThreadParams); else if (!pThread->InitInstance()) nResult=pThread->ExitInstance(); else pThread-> Run(); //clean up and shutdown thread AfxEndThread(nResult); Pic

A time line for Mom and Junior threads

CWinThread::Run() int CWinThread::Run() { 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; lIdleCount = 0;} } while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE)); } ASSERT(FALSE); // not reachable

CWinThread::OnIdle() BOOL CWinThread::OnIdle(LONG lCount){ if (lCount <= 0) { // send WM_IDLEUPDATECMDUI to the main window // send WM_IDLEUPDATECMDUI to all frame window else if (lCount >= 0) { //Call AfxLockTempMaps/AfxUnlockTempMaps //to free maps, DLLs, etc } return lCount < 0; //nothing more to do if lCount >= 0

Executing a class member in its own thread Motivation class Task {…}; class Processor { public: void SubmitTask(Task t); private: usigned ProcessTask(void *data); std::queue<Task> m_tasks; } Problem WINBASEAPI HANDLE WINAPI CreateThread(LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, WDORD dwCreationFlags, LPDWORD lpThreadID);

Usage Foo f; runInThread(f, &Foo::member, args);

Solution #1 template <class Object> void runInThread(Object& obj, DWORD(WINAPI Objecg::*memberFunc)(void), HANDLE* handle=0, DWORD* id=0) { using std::runtime_error; DWORD (WINAPI *threadFunc)(void*); //pass object “this” pointer via thread void* pointer void *thisPointer=satic_cast<void*>(&obj); //copy class member pointer to global function pointer *reinterpret_cast<long*>(&threadFunc)=*reinterpret_cast<long*>(&memberFunc); DWORD threadId = -1; HANDLE result=CreateThread(0, 0, threadFunc, thisPointer, 0, &threadId); if (result == 0) throw runtime_error(“CreateThread failed”); if (handle) *handle=result; if (id) *id = threadId; }

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. It’s a big limitation.

Solution #2 template <class Object, class MemberFunc, class Param> 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) { std::auto_ptr<ThrdArg> arg(reinterpret_cast<ThrdArg*>(v); return ((arg->object)->*(arg->memberFunc))(arg->param); }

Solution #2 (cont.) public: ThreadableMember(Object& instance, MemberFunc member) : m_instance(instance), m_member(member) {} void run(const Param& param, HANDLE* handle=0, DWORD* id=0){ 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) *handle=result; if (id) *id = thrdId; } else { delete thrdArg; throw std::tuntime_error(“CreateThread failed”); } };

Usage Foo f; ThreadableMember<Foo, DWORD(Foo::*)(char*), char*> m(f, &Foo::Bar1); m.run(“alpha”); Helper function: template <class Object, class MemberFunc, class Param> inline void runInThread(Object& instance, MemberFunc member, const Param& param, HANDLE* handle=0, DWORD* id=0){ ThreadableMember<Object,MemberFunc,Param> m(instance, member); m.run(param, handle, id); } runInThread(f, &Foo::Bar2, class Bar2Param);

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

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* Singleton::m_instance = 0;

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.

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* Singleton::m_instance = 0; CCriticalSection Singleton::m_key; Different from the code in the article

Heaps Let’s compare these two functions: void SomeFunc(Foo bar){ Obj* pObj=new Obj; pObj->Hadler(bar); delete pObj; } Obj obj; obj.Hadler(bar);

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

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.