锘??xml version="1.0" encoding="utf-8" standalone="yes"?>少妇无套内谢久久久久,国产农村妇女毛片精品久久,国产精品亚洲综合专区片高清久久久http://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 鍙戣〃璇勮
]]>
亚洲欧美国产日韩综合久久| 日本精品久久久久中文字幕8| 亚洲伊人久久成综合人影院| 一本久道久久综合狠狠躁AV| 亚洲愉拍99热成人精品热久久| 久久久久无码精品国产| 伊人丁香狠狠色综合久久| 久久99国产精品成人欧美| 久久人人爽人人爽人人片av麻烦| 久久精品中文闷骚内射| 精品久久久久久国产免费了| 97精品依人久久久大香线蕉97 | 国产一久久香蕉国产线看观看| 久久精品国产精品亚洲艾草网美妙| 久久综合九色综合网站| 国产精品一区二区久久精品无码 | 一本色道久久88加勒比—综合| 综合久久精品色| 亚洲嫩草影院久久精品| 亚洲级αV无码毛片久久精品| 人妻无码久久精品| 精品久久久久一区二区三区| 久久精品国产亚洲精品2020| 久久精品国产99久久久古代| 久久精品一区二区三区中文字幕| 久久777国产线看观看精品| 一本久久知道综合久久| 一本久久精品一区二区| 欧美成a人片免费看久久| 国产99久久久国产精免费| 热re99久久精品国产99热| 99国产精品久久| 欧美黑人又粗又大久久久| 伊人久久久AV老熟妇色| 国产毛片欧美毛片久久久| 日日狠狠久久偷偷色综合0| 精品久久久久中文字| 伊人久久成人成综合网222| 亚洲精品午夜国产va久久| 精品国产青草久久久久福利| 国产成人无码精品久久久性色 |