锘??xml version="1.0" encoding="utf-8" standalone="yes"?>又紧又大又爽精品一区二区,亚洲一区二区成人在线观看,99riav久久精品riavhttp://m.shnenglu.com/flagman/category/15722.html 鍞愪寒鐨勪釜浜烘妧鏈崥瀹? 銆愭榪庤漿杞斤紝浣嗚鏍囨槑鍘熶綔鑰呫?/description>zh-cnMon, 12 Dec 2011 16:19:20 GMTMon, 12 Dec 2011 16:19:20 GMT60C++ library series -- in the MFC multiple-thread environment, how to quit worker-thread safely which begins with AfxBeginThreadhttp://m.shnenglu.com/flagman/archive/2011/12/11/how_to_quit_worker-thread_safely_which_begins_with_AfxBeginThread.htmlflagmanflagmanSun, 11 Dec 2011 12:35:00 GMThttp://m.shnenglu.com/flagman/archive/2011/12/11/how_to_quit_worker-thread_safely_which_begins_with_AfxBeginThread.htmlhttp://m.shnenglu.com/flagman/comments/161934.htmlhttp://m.shnenglu.com/flagman/archive/2011/12/11/how_to_quit_worker-thread_safely_which_begins_with_AfxBeginThread.html#Feedback0http://m.shnenglu.com/flagman/comments/commentRss/161934.htmlhttp://m.shnenglu.com/flagman/services/trackbacks/161934.html
  In the MFC environment, normally, thread should be launched with AfxBeginThread for taking usage of MFC multiple-thread mechanism; In such mechanism, those datastructures, such as AFX_MODULE_STATE, would be used by MFC framework to maintain related thread information. It runs well when threads, launched with AfxBeginThread, quit before the main thread, which is responsible for initializing C run-time, but if such main thread quit before any other thread launched by AfxBeginThread, the current application would crash.
  Such crash comes from the _afxThreadData (CThreadSlotData* _afxThreadData, which is defined in AFXTLS.cpp as global data structure) has been destructed while the main thread quits and it will invoke related function to clean up global data structures, including _afxThreadData definitely.
  Consequently, serious developer should prepare for such case (other worker thread quits before main thread).
  
  The reasonable resolve for such issue, would ensure any other threads should quit before the main thread. 
  
.h file 
  /////////////////////////////////////////////////////////////////////////////
// CSafeEnterLeaveThread thread
class CSafeEnterLeaveThread : public CWinThread
{
DECLARE_DYNCREATE(CSafeEnterLeaveThread)
protected:
CSafeEnterLeaveThread();           // protected constructor used by dynamic creation
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSafeEnterLeaveThread)
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
//}}AFX_VIRTUAL
// Implementation
protected:
virtual ~CSafeEnterLeaveThread();
// Generated message map functions
//{{AFX_MSG(CSafeEnterLeaveThread)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
.cpp file 
/////////////////////////////////////////////////////////////////////////////
// CSafeEnterLeaveThread
IMPLEMENT_DYNCREATE(CSafeEnterLeaveThread, CWinThread)
CSafeEnterLeaveThread::CSafeEnterLeaveThread()
{
}
CSafeEnterLeaveThread::~CSafeEnterLeaveThread()
{
}
BOOL CSafeEnterLeaveThread::InitInstance()
{
// TODO:  perform and per-thread initialization here
ASSERT(this->m_hThread);
CMainApp::RegisterMFCThread(this->m_hThread);
return TRUE;
}
int CSafeEnterLeaveThread::ExitInstance()
{
// TODO:  perform any per-thread cleanup here
ASSERT(this->m_hThread);
CMainApp::UnRegisterMFCThread(this->m_hThread);
return CWinThread::ExitInstance();
}
BEGIN_MESSAGE_MAP(CSafeEnterLeaveThread, CWinThread)
//{{AFX_MSG_MAP(CSafeEnterLeaveThread)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
And in the CMainApp,
set<HANDLE> g_ThreadHandleSet;
HANDLE g_ThreadHandleArray[MAXIMUM_WAIT_OBJECTS];
CCriticalSection g_csGlobalData;
void CAccgbApp::CheckAllOtherMFCThreadsLeave()
{
int count = g_ThreadHandleSet.size();
if (count == 0) return;
set<HANDLE>::iterator it;
int idx = 0;
for (it = g_ThreadHandleSet.begin(); it != g_ThreadHandleSet.end() && idx < MAXIMUM_WAIT_OBJECTS; it++, idx++)
{
g_ThreadHandleArray[idx] = *it;
}
if (count > idx) count = idx;
::WaitForMultipleObjects(count, g_ThreadHandleArray, TRUE, INFINITE);
}
void CAccgbApp::CleanupGlobalData()
{
g_csGlobalData.Lock();
g_ThreadHandleSet.empty();
g_csGlobalData.Unlock();
}
BOOL CAccgbApp::RegisterMFCThread(HANDLE hThread)
{
if (hThread == NULL) return FALSE;
g_csGlobalData.Lock();
if (g_ThreadHandleSet.find(hThread) == g_ThreadHandleSet.end()) 
g_ThreadHandleSet.insert(hThread);
g_csGlobalData.Unlock();
return TRUE;
}
void CAccgbApp::UnRegisterMFCThread(HANDLE hThread)
{
if (hThread == NULL) return;
g_csGlobalData.Lock();
if (g_ThreadHandleSet.find(hThread) != g_ThreadHandleSet.end())
g_ThreadHandleSet.erase(hThread);
g_csGlobalData.Unlock();
}


flagman 2011-12-11 20:35 鍙戣〃璇勮
]]>
C++ library緋誨垪 -- static destructors in multiple threadshttp://m.shnenglu.com/flagman/archive/2011/02/08/static_destructors_in_multiple_threads.htmlflagmanflagmanTue, 08 Feb 2011 12:57:00 GMThttp://m.shnenglu.com/flagman/archive/2011/02/08/static_destructors_in_multiple_threads.htmlhttp://m.shnenglu.com/flagman/comments/139812.htmlhttp://m.shnenglu.com/flagman/archive/2011/02/08/static_destructors_in_multiple_threads.html#Feedback0http://m.shnenglu.com/flagman/comments/commentRss/139812.htmlhttp://m.shnenglu.com/flagman/services/trackbacks/139812.html  In VC++ 8.0, while  code compiled with /clr or /clr:pure, static destructors sometimes would not being properly called before process exites in multiple threads.

  CRT incorrectly set a lock at _global_unlock which resulted in such issue.

  In CLR-mixed mode, during the inialization of static local object, CRT would call _atexit_m(_CPVFV func) in msilexit.cpp to register a special __clrcall callback function which would be called back to destroy such static object when the current AppDomain quited.

  In the multithread environment, _atexit_helper which was invoked by _atexit_m, could register such callbace function successfully because it had been guarded by __global_lock() and __global_unlock(). But in the same environment, the _atexit_m would fail to assign the correct value to __onexitbegin_m and __onexitend_m.

  __onexitbegin_m and __onexitend_m were shared by the different threads; It's the key point of such issue. For example, the following statements,

  __onexitbegin_m = (_CPVFV *)_encode_pointer(onexitbegin_m);
  __onexitend_m = (_CPVFV *)_encode_pointer(onexitend_m);

should also guarded by __global_lock() and __global_unlock() or other syn primitives.


__global_lock();
__onexitbegin_m = (_CPVFV *)_encode_pointer(onexitbegin_m);
__onexitend_m   = (_CPVFV *)_encode_pointer(onexitend_m);
__global_unlock();


extern "C" int __clrcall _atexit_m(_CPVFV func)
{
 MANAGED_ASSERT(AppDomain::CurrentDomain->IsDefaultAppDomain(), "This fuction must be called in the default domain");

 __global_lock();
 _CPVFV* onexitbegin_m = (_CPVFV*)_decode_pointer(__onexitbegin_m);
 _CPVFV* onexitend_m = (_CPVFV*)_decode_pointer(__onexitend_m);
 __global_unlock();

 int retval = _atexit_helper((_CPVFV)_encode_pointer(func), &__exit_list_size, &onexitend_m, &onexitbegin_m);

 __global_lock();
 __onexitbegin_m = (_CPVFV*)_encode_pointer(onexitbegin_m);
 __onexitend_m  = (_CPVFV*)_encode_pointer(onexitend_m);
 __global_unlock();

 return retval;
}



flagman 2011-02-08 20:57 鍙戣〃璇勮
]]>
国产亚洲精午夜久久久久久| 一本一道久久a久久精品综合| 国产亚洲精久久久久久无码| 成人妇女免费播放久久久| 亚洲国产成人久久综合一 | 国产亚洲精久久久久久无码77777| 伊人久久精品无码av一区| 久久精品蜜芽亚洲国产AV| 久久精品国产清自在天天线| 久久天天躁夜夜躁狠狠躁2022 | www.久久精品| 亚洲精品tv久久久久久久久久| 久久精品视频一| 欧美精品一本久久男人的天堂| 中文精品99久久国产 | 久久久久这里只有精品| 久久久一本精品99久久精品66| 久久久久久久久久久免费精品| 无遮挡粉嫩小泬久久久久久久| 久久婷婷色综合一区二区| 久久九九有精品国产23百花影院| 色老头网站久久网| 久久伊人五月天论坛| 国产午夜精品久久久久九九电影 | 青青草原综合久久大伊人导航| 久久综合九色综合欧美狠狠| 浪潮AV色综合久久天堂| 国产精品亚洲综合久久| 一级做a爰片久久毛片毛片| 久久久久婷婷| 久久精品国产99国产精品| 99久久成人18免费网站| 久久久久久a亚洲欧洲aⅴ| 国内精品久久久久影院一蜜桃| 色8久久人人97超碰香蕉987| 伊人久久大香线蕉av不卡| 97精品依人久久久大香线蕉97| 久久久久久国产a免费观看黄色大片| 一本色综合久久| 性做久久久久久久| 久久免费精品一区二区|