Files
RepoMain/ZCppMain/ZCProcess_Win.H

3161 lines
109 KiB
C++
Raw Normal View History


#ifndef __ZCPPMAIN__PROCESS_WIN_H__
#define __ZCPPMAIN__PROCESS_WIN_H__
#include "ZCppMain/ZMainHead.H"
#include <windows.h>
#include <fstream>
#include <process.h>
namespace ZNsMain
{
namespace ZNsEnum
{
/* In WinNT : #define STATUS_WAIT_0 ((DWORD )0x00000000L)
In WinBase : #define WAIT_OBJECT_0 ((STATUS_WAIT_0 ) + 0 )
, ZEThread_Invalid
. */
enum ZEThread
{
ZEThread_OK = 0, // =WAIT_OBJECT_0
ZEThread_Invalid =-1, // 쓰레드 관련 함수 에러.
ZEThread_TimeOut = WAIT_TIMEOUT
};/*
enum ZEThread*/
/*##################################################
barrier .
barrier
BarrierClass VO_BarrierClass;
if(VO_BarrierClass.Init()==ZEBarrier_NO)
{
// some code
}
.
if(VO_BarrierClass.Init()!=ZEBarrier_OK)
{
// some code
}
.
##################################################*/
enum ZEBarrier
{
ZEBarrier_NO = false ,
ZEBarrier_OK = true
};/*
enum ZEBarrier*/
}/*
namespace ZNsEnum*/
class ZCProcess
{
protected:
STARTUPINFO mo_SI;
PROCESS_INFORMATION mo_PI;
public :
bool Exec(LPCTSTR AP_ExeName, LPCTSTR APC_WorkDir=NULL, bool AB_Inherit=TRUE)
{
::GetStartupInfoA(&mo_SI); return ::CreateProcessA(
NULL ,
(LPSTR)AP_ExeName, // Name of app to launch
NULL , // Default process security attributes
NULL , // Default thread security attributes
AB_Inherit , // Inherit handles from the parent
0 , // Normal priority
NULL , // Use the same environment as the parent
APC_WorkDir , // Launch in the current directory
&mo_SI , // Startup Information
&mo_PI // Process information stored upon return
/*/////////*/ ) == TRUE ;
}/*
bool Exec(LPCTSTR AP_ExeName, LPCTSTR APC_WorkDir=NULL, bool AB_Inherit=TRUE)*/
HANDLE GetNowProcessHandle()
{
return ::GetCurrentProcess();
}/*
HANDLE GetNowProcessHandle()*/
static long GetPID()
{
return ::GetCurrentProcessId(); // DWORD GetCurrentProcessId(VOID);
}/*
static long GetPID()*/
STARTUPINFO& GetStartUpInfo()
{
return mo_SI;
}/*
STARTUPINFO& GetStartUpInfo()*/
PROCESS_INFORMATION& GetProcInfo()
{
return mo_PI;
}/*
PROCESS_INFORMATION& GetProcInfo()*/
public:
};/*
class ZCProcess*/
//////////////////////////////////////////
/////////// end class ZCProcess ///////////
//////////////////////////////////////////
// Memory Map class
class ZCMemMap
{
private:
HANDLE mh_MemMap;
public :
ZCMemMap()
{
mh_MemMap=NULL;
}/*
ZCMemMap()*/
/*////////////////////////////////////////////////////////////////////////////
ZTypLong ALL_Size 0 AH_File .
AH_File ALL_Size 1
. AH_File ALL_Size 1 AH_File
ALL_Size .
////////////////////////////////////////////////////////////////////////////*/
bool Create(HANDLE AH_File=INVALID_HANDLE_VALUE, ZTypLong ALL_Size=0, DWORD ADW_ProtectFlag=PAGE_READWRITE, ::LPSECURITY_ATTRIBUTES AP_FileMappingAttributes=NULL, LPCTSTR AP_Name=NULL)
{
::LARGE_INTEGER LI; LI.QuadPart=ALL_Size; return (mh_MemMap=::CreateFileMapping(
AH_File, AP_FileMappingAttributes, ADW_ProtectFlag, LI.HighPart, LI.LowPart, AP_Name))!=NULL;
}/*
bool Create(HANDLE AH_File=INVALID_HANDLE_VALUE, ZTypLong ALL_Size=0, DWORD ADW_ProtectFlag=PAGE_READWRITE, ::LPSECURITY_ATTRIBUTES AP_FileMappingAttributes=NULL, LPCTSTR AP_Name=NULL)*/
/* LPVOID AP_BaseAddress 를 지정한다면 system's memory allocation granularity 의 배수여야 한다.
granularity GetSystemInfo . VOID GetSystemInfo(LPSYSTEM_INFO lpSystemInfo)
. NULL . */
/* DWORD ADW_MapSize 가 0 이면 파일전체가 map 된다. */
LPVOID LinkMap(ZTypLong ALL_Offset=0, DWORD ADW_MapSize=0, DWORD ADW_DesiredAccess=FILE_MAP_ALL_ACCESS, LPVOID AP_BaseAddress=NULL) const
{
::LARGE_INTEGER LI; LI.QuadPart=ALL_Offset; return ::MapViewOfFileEx(
mh_MemMap, ADW_DesiredAccess, LI.HighPart, LI.LowPart, ADW_MapSize, AP_BaseAddress);
}/*
LPVOID LinkMap(ZTypLong ALL_Offset=0, DWORD ADW_MapSize=0, DWORD ADW_DesiredAccess=FILE_MAP_ALL_ACCESS, LPVOID AP_BaseAddress=NULL) const*/
bool UnMap(LPCVOID AP_BaseAddress) const
{
return ::UnmapViewOfFile((void*)AP_BaseAddress)==TRUE;
}/*
bool UnMap(LPCVOID AP_BaseAddress) const*/
/* cygwin 이나 mingw 에서는 이상하게 ::UnmapViewOfFile(void*) 로 정의되어 있다.
UnMap() (void*)AP_BaseAddress . */
bool Close()
{
const bool CB_IsOK = (::CloseHandle(mh_MemMap)==TRUE); mh_MemMap=NULL; return CB_IsOK;
}/*
bool Close()*/
public:
};/*
class ZCMemMap*/
// 공유메모리 클래스
class ZCShareMemory
{
private:
ZTypeID mh_FileMap;
void* mp_Address;
public :
ZCShareMemory()
{
mh_FileMap=0;
mp_Address=0;
}/*
ZCShareMemory()*/
ZTypeID GetID() const
{
return mh_FileMap;
}/*
ZTypeID GetID() const*/
bool IsValidID() const
{
return mh_FileMap!=0;
}/*
bool IsValidID() const*/
void* GetStartAddress() const
{
return mp_Address;
}/*
void* GetStartAddress() const*/
// Create() 멤버를 호출한 다음에는 LinkMap() 멤버를 호출해야 한다.
bool Create(LPCTSTR AP_MapName, long AL_MapSize)
{
return (mh_FileMap = ::CreateFileMapping(
INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, AL_MapSize, AP_MapName))!=NULL ;
/*//////////////////////////////////////////////////////
HANDLE CreateFileMapping
(
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCTSTR lpName
);
lpName
The name of the file mapping object.
If this parameter matches the name of an existing mapping object,
the function requests access to the object with the protection that flProtect specifies.
If this parameter is NULL,
the file mapping object is created without a name.
If lpName matches the name of an existing event, semaphore,
mutex, waitable timer, or job object,
the function fails,
and the GetLastError function returns ERROR_INVALID_HANDLE.
This occurs because these objects share the same namespace.
-- lpName event, semaphore, mutex, waitable timer
-- GetLastError ERROR_INVALID_HANDLE .
-- NULL .
Return Value
If the function succeeds,
the return value is a handle to the file mapping object.
If the object exists before the function call,
the function returns a handle to the existing object
(with its current size, not the specified size),
and GetLastError returns ERROR_ALREADY_EXISTS.
If the function fails, the return value is NULL.
To get extended error information, call GetLastError.
//////////////////////////////////////////////////////*/
}/*
bool Create(LPCTSTR AP_MapName, long AL_MapSize)*/
bool Create(long AL_MapSize)
{
return this->Create(NULL/*lpMapName*/, AL_MapSize);
}/*
bool Create(long AL_MapSize)*/
/*///////////////////////////////////////////////////////////////////////////////
LPVOID MapViewOfFile
(
HANDLE hFileMappingObject ,
DWORD dwDesiredAccess ,
DWORD dwFileOffsetHigh ,
DWORD dwFileOffsetLow ,
DWORD dwNumberOfBytesToMap
);
hFileMappingObject
FILE_MAP_ALL_ACCESS
Equivalent to FILE_MAP_WRITE and FILE_MAP_READ.
The object must have been created with the PAGE_READWRITE option.
FILE_MAP_COPY
A copy-on-write view of the file is mapped.
The object must have been created with the PAGE_WRITECOPY option.
If the file mapping object is backed by the operating system paging file,
the system commits physical storage from the paging file at the time
that MapViewOfFile is called.
The actual physical storage is not used
until a thread in the process writes to an address in the view.
At that time, the system copies the original page to a new page that is backed
by the paging file, maps the page into the process address space,
and changes the page protection to PAGE_READWRITE.
The threads in the process can access only the local copy of the data,
not the original data.
If the page is ever trimmed from the working set of the process,
it can be written to the paging file storage that is committed
when MapViewOfFile is called.
This process only allocates physical memory
when a virtual address is actually written to.
Changes are never written back to the original file,
and are freed when the thread in your process unmaps the view.
Paging file space for the entire view is committed
when copy-on-write access is specified,
because the thread in the process can write to every single page.
Therefore, enough physical storage space must be obtained
at the time MapViewOfFile is called.
FILE_MAP_EXECUTE
An executable view of the file is mapped (mapped memory can be run as code).
The object must have been created with the PAGE_EXECUTE_READWRITE or PAGE_EXECUTE_READ option.
Windows Server 2003 and Windows XP:
This value is available starting with Windows XP SP2 and Windows Server 2003 SP1.
Windows 2000: This value is not supported.
-- FILE_MAP_EXECUTE .
-- , .
-- 2008-02-08 21:48:00
FILE_MAP_READ
A read-only view of the file is mapped.
The object must have been created with the PAGE_READWRITE or PAGE_READONLY option.
FILE_MAP_WRITE
A read/write view of the file is mapped.
The object must have been created with the PAGE_READWRITE option.
dwFileOffsetHigh
A high-order DWORD of the file offset where the view begins.
dwFileOffsetLow
A low-order DWORD of the file offset where the view is to begin.
The combination of the high and low offsets must specify an offset within the file mapping.
They must also match the memory allocation granularity of the system.
That is, the offset must be a multiple of the allocation granularity.
To obtain the memory allocation granularity of the system,
use the GetSystemInfo function,
which fills in the members of a SYSTEM_INFO structure.
dwNumberOfBytesToMap
The number of bytes of a file mapping to map to the view.
All bytes must be within the maximum size specified by CreateFileMapping.
If this parameter is 0 (zero),
the mapping extends from the specified offset to the end of the file mapping.
///////////////////////////////////////////////////////////////////////////////*/
bool LinkMap(DWORD dwDesiredAccess=FILE_MAP_ALL_ACCESS, DWORD dwNumberOfBytesToMap=0)
{
return (mp_Address=::MapViewOfFile(mh_FileMap, dwDesiredAccess, 0, 0, dwNumberOfBytesToMap))!=0 ;
}/*
bool LinkMap(DWORD dwDesiredAccess=FILE_MAP_ALL_ACCESS, DWORD dwNumberOfBytesToMap=0)*/
bool UnMap()
{
bool VB_IsOK =
(::UnmapViewOfFile(mp_Address)==TRUE) ;
mp_Address=0; return VB_IsOK;
}/*
bool UnMap()*/
bool Close()
{
bool VB_IsOK =
(::CloseHandle(mh_FileMap)==TRUE);
mh_FileMap=0; return VB_IsOK;
}/*
bool Close()*/
public:
};/*
class ZCShareMemory*/
///////////////////////////////////////////////
/////////// end class ZCShareMemory ///////////
///////////////////////////////////////////////
/*//////////////////////////////////////////////////////////////////////////////
class ZCProcessMutex .
Window mutex Linux
. pthread mutex
. Linux
. pthread mutex
. (2006-12-28 16:02:00)
window '' .
ReleaseMutex() FALSE .
. .
//////////////////////////////////////////////////////////////////////////////*/
class ZCProcessMutex
{
private:
ZTypeID mh_Mutex;
public :
ZCProcessMutex()
{
mh_Mutex=0;
}/*
ZCProcessMutex()*/
ZTypeID GetHandle() const
{
return mh_Mutex;
}/*
ZTypeID GetHandle() const*/
bool Make(LPCTSTR AP_MutexName=NULL, LPSECURITY_ATTRIBUTES lpMutexAttributes=NULL, BOOL bInitialOwner=FALSE)
{
if(lpMutexAttributes==NULL)
{
// Mutex 핸들을 차일드 프로세스로 상속할 수 있게 한다.
SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES_Obj;
SECURITY_ATTRIBUTES_Obj.bInheritHandle =TRUE;
SECURITY_ATTRIBUTES_Obj.lpSecurityDescriptor=NULL;
SECURITY_ATTRIBUTES_Obj.nLength =sizeof(SECURITY_ATTRIBUTES);
return (mh_Mutex = ::CreateMutex(&SECURITY_ATTRIBUTES_Obj, bInitialOwner, AP_MutexName))!=NULL ;
}/*
if(lpMutexAttributes==NULL)*/
return (mh_Mutex = ::CreateMutex(lpMutexAttributes, bInitialOwner, AP_MutexName))!=NULL ;
}/*
bool Make(LPCTSTR AP_MutexName=NULL, LPSECURITY_ATTRIBUTES lpMutexAttributes=NULL, BOOL bInitialOwner=FALSE)*/
bool Lock(DWORD ADW_TimeOut=INFINITE)
{
DWORD VI_Return=::WaitForSingleObject(mh_Mutex, ADW_TimeOut);
return VI_Return!=WAIT_ABANDONED && VI_Return!=WAIT_FAILED ;
/*///////////////////////////////////////////////////////////////////////////
WaitForSingleObject()
, .
.
(Abandoned Mutex) .
WaitForSingleObject() WAIT_ABANDONED
.
Critical Section .
///////////////////////////////////////////////////////////////////////////*/
}/*
bool Lock(DWORD ADW_TimeOut=INFINITE)*/
int LockRaw(DWORD ADW_TimeOut=INFINITE)
{
return ::WaitForSingleObject(mh_Mutex, ADW_TimeOut);
}/*
int LockRaw(DWORD ADW_TimeOut=INFINITE)*/
int LockTime(DWORD AI_TimeOutMili)
{
return LockRaw(AI_TimeOutMili);
}/*
int LockTime(DWORD AI_TimeOutMili)*/
bool UnLock()
{
return ::ReleaseMutex(mh_Mutex)==TRUE ;
}/*
bool UnLock()*/
bool Close()
{
bool VB_Result=(::CloseHandle(mh_Mutex)==TRUE) ;
mh_Mutex=0; return VB_Result;
}/*
bool Close()*/
public:
};/*
class ZCProcessMutex*/
///////////////////////////////////////////////
/////////// end class ZCProcessMutex ///////////
///////////////////////////////////////////////
class ZCProcessMutexEasy : protected ZCProcessMutex
{
public:
ZCProcessMutexEasy(LPCTSTR AP_MutexName)
{
if(this->ZCProcessMutex::Make(AP_MutexName)==false)
{
std::fstream fileout("DEBUG.txt",std::ios::out | std::ios::app);
fileout<<std::endl<<"File : "<<__FILE__<<std::endl<<"Line : "<<__LINE__<<std::endl;
fileout<<"Error !! ZCProcessMutexEasy(LPCTSTR AP_MutexName) Fail To Mutex(Name="<<AP_MutexName<<")"<<std::endl;
fileout.close();
exit(1);
}/*
if(this->ZCProcessMutex::Make(AP_MutexName)==false)*/
}/*
ZCProcessMutexEasy(LPCTSTR AP_MutexName)*/
ZCProcessMutexEasy()
{
if(this->ZCProcessMutex::Make()==false)
{
std::fstream fileout("DEBUG.txt",std::ios::out | std::ios::app);
fileout<<std::endl<<"File : "<<__FILE__<<std::endl<<"Line : "<<__LINE__<<std::endl;
fileout<<"Error !! ZCProcessMutexEasy() Fail To Mutex"<<std::endl;
fileout.close();
exit(1);
}/*
if(this->ZCProcessMutex::Make()==false)*/
}/*
ZCProcessMutexEasy()*/
/*//////////////////////////////////////////////////////////
ZCProcessMutex()
CProcess_Linux.H class ZZCThreadMutexEasy .
-- 2013-05-05 07:05:00
//////////////////////////////////////////////////////////*/
ZCProcessMutexEasy(const ZCProcessMutexEasy& rhs) : ZCProcessMutex()
{
if(this->ZCProcessMutex::Make()==false)
{
std::fstream fileout("DEBUG.txt",std::ios::out | std::ios::app);
fileout<<std::endl<<"File : "<<__FILE__<<std::endl<<"Line : "<<__LINE__<<std::endl;
fileout<<"Error !! ZCProcessMutexEasy(const ZCProcessMutexEasy& rhs) Fail To Mutex)"<<std::endl;
fileout.close();
exit(1);
}/*
if(this->ZCProcessMutex::Make()==false)*/
}/*
ZCProcessMutexEasy(const ZCProcessMutexEasy& rhs)*/
~ZCProcessMutexEasy()
{
if(this->ZCProcessMutex::Close()==false)
{
std::fstream fileout("DEBUG.txt",std::ios::out | std::ios::app);
fileout<<std::endl<<"File : "<<__FILE__<<std::endl<<"Line : "<<__LINE__<<std::endl;
fileout<<"Error !! ~ZCProcessMutexEasy() Fail To Close Mutex"<<std::endl;
fileout.close();
exit(1);
}/*
if(this->ZCProcessMutex::Close()==false)*/
}/*
~ZCProcessMutexEasy()*/
using ZCProcessMutex::Lock ;
using ZCProcessMutex::UnLock;
public:
};/*
class ZCProcessMutexEasy*/
typedef ZCProcessMutexEasy ZZCThreadMutexEasy;
/*/////////////////////////////////////////////////////////////
class ZCProcessSemaphore object.
Semaphore Window
Mutex .
Semaphore
.
class ZCThreadSemaphore
. class ZCProcessSemaphore
. semaphore
.
ReleaseSemaphore() 2
2
.
. Posix barrier
.
/////////////////////////////////////////////////////////////*/
class ZCProcessSemaphore
{
private:
ZTypeID mh_Semaphore;
public :
ZCProcessSemaphore()
{
mh_Semaphore=0;
}/*
ZCProcessSemaphore()*/
~ZCProcessSemaphore()
{
Close();
}/*
ZCProcessSemaphore*/
bool Make(LPCSTR AP_SemaName, LONG AL_InitialCnt, LONG AL_MaximumCount, LPSECURITY_ATTRIBUTES AP_SemaphoreAttributes=NULL)
{
/*/////////////////////////////////////////////////////////////////
cf) CreateSemaphore()
Return Values
If the function succeeds,
the return value is a handle to the semaphore object.
If the named semaphore object existed before the function call,
the function returns a handle to the existing object
and GetLastError returns ERROR_ALREADY_EXISTS.
If the function fails, the return value is NULL.
To get extended error information, call GetLastError.
/////////////////////////////////////////////////////////////////*/
return (mh_Semaphore = ::CreateSemaphoreA(
AP_SemaphoreAttributes, AL_InitialCnt, AL_MaximumCount, AP_SemaName))!=(HANDLE)ERROR_INVALID_HANDLE ;
}/*
bool Make(LPCSTR AP_SemaName,LONG AL_InitialCnt, LONG AL_MaximumCount, LPSECURITY_ATTRIBUTES AP_SemaphoreAttributes=NULL)*/
bool Make(LPCSTR AP_SemaName, LONG AL_InitialCnt, LPSECURITY_ATTRIBUTES AP_SemaphoreAttributes=NULL)
{
return (mh_Semaphore = ::CreateSemaphoreA(
AP_SemaphoreAttributes, AL_InitialCnt, AL_InitialCnt, AP_SemaName))!=(HANDLE)ERROR_INVALID_HANDLE ;
}/*
bool Make(LPCSTR AP_SemaName, LONG AL_InitialCnt, LPSECURITY_ATTRIBUTES AP_SemaphoreAttributes=NULL)*/
// 아래 멤버는 뮤텍스처럼 쓰려는 경우에 사용한다.
bool Make(LONG AL_InitialCnt=1, LONG AL_MaxCnt=1, LPSECURITY_ATTRIBUTES AP_SemaphoreAttributes=NULL)
{
return (mh_Semaphore=::CreateSemaphore(
AP_SemaphoreAttributes, AL_InitialCnt, AL_MaxCnt, this->GetUniqueSemaKey()) )!=(HANDLE)ERROR_INVALID_HANDLE ;
}/*
bool Make(LONG AL_InitialCnt=1, LONG AL_MaxCnt=1, LPSECURITY_ATTRIBUTES AP_SemaphoreAttributes=NULL)*/
bool MakeZero(LPCSTR AP_SemaName=NULL) // 비신호상태의 세마포어를 만든다.
{
const int CI_MaxNumSemaphore=2100000000;
return (mh_Semaphore=::CreateSemaphoreA(
NULL, 0, CI_MaxNumSemaphore, AP_SemaName))!=(HANDLE)ERROR_INVALID_HANDLE ;
}/*
bool MakeZero(LPCSTR AP_SemaName=NULL)*/
static LPCSTR GetUniqueSemaKey()
{
static long SL_UniqueID=0 ;
const long CL_AddID =100000;
long VL_UniqueLong = ( SL_UniqueID += CL_AddID ) + ::GetCurrentProcessId() ;
static char VCA_Buff[100]; ::wsprintf(VCA_Buff, _T("SemaKey%ld"), VL_UniqueLong); return VCA_Buff;
}/*
static LPCSTR GetUniqueSemaKey()*/
/* bool MakeStd() 는 class ZCProcessSemaphore 가
Window, Linux */
bool MakeStd(LPCSTR AP_SemaName, LONG AL_InitialCnt,LONG AL_MaximumCount)
{
return this->Make(AP_SemaName, AL_InitialCnt, AL_MaximumCount);
}/*
bool MakeStd(LPCSTR AP_SemaName, LONG AL_InitialCnt, LONG AL_MaximumCount)*/
bool Open(LPCSTR AP_SemaName, DWORD dwDesireAccess=SEMAPHORE_ALL_ACCESS, BOOL bInheritHandle=TRUE)
{
return (mh_Semaphore=::OpenSemaphore(dwDesireAccess, bInheritHandle, AP_SemaName))!=NULL ;
}/*
bool Open(LPCSTR AP_SemaName, DWORD dwDesireAccess=SEMAPHORE_ALL_ACCESS, BOOL bInheritHandle=TRUE)*/
/* 현재 세마포어의 값을 가져온다. 이 함수를 만든 작가 자신은 별로 자신이
. 'API ' 1101 .
. -- 2015-09-16 00:40:00 */
static int GetValue(HANDLE AH_Sema)
{
if(::WaitForSingleObject(AH_Sema, 0)==WAIT_TIMEOUT) return 0;
LONG VL_Count=0; ::ReleaseSemaphore(AH_Sema, 1, &VL_Count);
return VL_Count+1; /*#####################################*/
}/*
static int GetValue(HANDLE AH_Sema)*/
int GetValue() const
{
return GetValue(mh_Semaphore);
}/*
int GetValue() const*/
bool IsZeroCount()
{
return ::WaitForSingleObject(mh_Semaphore, 0)==WAIT_TIMEOUT;
}/*
bool IsZeroCount()*/
// cf) WaitForSingleObject() 은 시간초과의 경우에 WAIT_TIMEOUT 을 리턴한다.
bool Lock(DWORD ADW_TimeOut=INFINITE)
{
return ::WaitForSingleObject(mh_Semaphore, ADW_TimeOut)!=WAIT_FAILED;
}/*
bool Lock(DWORD ADW_TimeOut=INFINITE)*/
/* LockRaw() 는 성공이면 ZEThread_OK, 시간초과는 ZEThread_TimeOut 을 반환한다.
Posix . */
int LockRaw(DWORD ADW_TimeOut=INFINITE)
{
return ::WaitForSingleObject(mh_Semaphore, ADW_TimeOut);
}/*
int LockRaw(DWORD ADW_TimeOut=INFINITE)*/
int LockTime(DWORD AI_TimeOutMili)
{
return LockRaw(AI_TimeOutMili);
}/*
int LockTime(DWORD AI_TimeOutMili)*/
bool UnLock(LONG lReleaseCount=1, LPLONG lpPreviousCount=NULL)
{
/* cf) lReleaseCount
[in] Amount by which the semaphore object's current count is to be increased.
The value must be greater than zero.
If the specified amount would cause the semaphore's count to exceed the maximum count
that was specified when the semaphore was created,
the count is not changed and the function returns FALSE. */
return ::ReleaseSemaphore(mh_Semaphore, lReleaseCount, lpPreviousCount)!=0 ;
}/*
bool UnLock(LONG lReleaseCount=1, LPLONG lpPreviousCount=NULL)*/
bool Close()
{
if(mh_Semaphore==0) return true;
const bool CB_IsOK =(
::CloseHandle(mh_Semaphore)==TRUE) ; mh_Semaphore=0;
return CB_IsOK;
}/*
bool Close()*/
public:
};/*
class ZCProcessSemaphore*/
////////////////////////////////////////////////
/////////// end class ZCProcessMutex ///////////
////////////////////////////////////////////////
/*//////////////////////////////////////////////
.
::EnterCriticalSection()
. Mutex
.
//////////////////////////////////////////////*/
typedef ZCProcessSemaphore ZCThreadSemaphore;
typedef ZCProcessMutex ZCThreadMutex ;
typedef ZCProcessMutex ZCThreadMutexStd ;
// posix 에서는 spin lock 으로 구현한다.
class ZCCriticSect // Critical Section
{
private:
CRITICAL_SECTION mo_CriticSect;
public :
void Init()
{
::InitializeCriticalSection(&mo_CriticSect);
}/*
void Init()*/
bool Init(DWORD AI_SpinCount)
{
return ::InitializeCriticalSectionAndSpinCount(&mo_CriticSect, AI_SpinCount)==TRUE;
}/*
bool Init(DWORD AI_SpinCount)*/
void Fini()
{
::DeleteCriticalSection(&mo_CriticSect);
}/*
void Fini()*/
void Lock (){::EnterCriticalSection(&mo_CriticSect);}
void UnLock(){::LeaveCriticalSection(&mo_CriticSect);}
/*//////////////////////////////////////////////////////////////////////////////////
TryEnterCriticalSection . -- 2007-05-17 14:34:00)
bool TryLock()
{
return TryEnterCriticalSection(&mo_CriticSect)==TRUE;
}
/////////////////////////////////////////////////////////////////////////////////////*/
#if defined(__VISUAL_CPP_VER__) && __VISUAL_CPP_VER__>=200800
bool WaitCond(::PCONDITION_VARIABLE AP_Cond, DWORD AI_Mili=INFINITE)
{
return ::SleepConditionVariableCS(AP_Cond, &mo_CriticSect, AI_Mili)==TRUE;
}/*
bool WaitCond(::PCONDITION_VARIABLE AP_Cond, DWORD AI_Mili=INFINITE)*/
#endif //defined(__VISUAL_CPP_VER__) && __VISUAL_CPP_VER__>=200800
public:
};/*
class ZCCriticSect*/
class ZCCriticSectEasy : protected ZCCriticSect
{
public:
ZCCriticSectEasy(){this->Init();}
ZCCriticSectEasy(const ZCCriticSectEasy&){this->Init();}
~ZCCriticSectEasy(){this->Fini();}
void Lock (){this->ZCCriticSect::Lock ();}
void UnLock(){this->ZCCriticSect::UnLock();}
public:
};/*
class ZCCriticSectEasy : public ZCCriticSect*/
typedef ZCCriticSectEasy ZCDefLockEasy ;
typedef ZCCriticSectEasy ZCFastLockEasy;
template<typename TAutoKey> class ZtCAutoKeyRev;
/* ZtCAutoKey<> 템플릿은 Lock 을 설정하고 해제한다.
Key .
RAII(Resource Acquisition Is Initialization)
. -- 2015-03-10 15:08:00
*/
template<typename TCriticSectEasy=ZCCriticSectEasy> class ZtCAutoKey
{
public :
template<typename TAutoKey> friend class ZtCAutoKeyRev;
private:
ZtCAutoKey(const ZtCAutoKey& rhs){}
private:
TCriticSectEasy& mr_SyncEasy;
#ifdef _DEBUG_CAUTOKEY_
static int msi_CallCnt;
#endif //_DEBUG_CAUTOKEY_
public:
ZtCAutoKey(TCriticSectEasy& AR_SyncEasy):mr_SyncEasy(AR_SyncEasy)
{
#ifdef _DEBUG_CAUTOKEY_
cout<<"▶▶▶▶ ZtCAutoKey:: ZtCAutoKey() "<<this<<", "<<++msi_CallCnt<<", ▶▶▶▶"<<endl;
#endif //_DEBUG_CAUTOKEY_
mr_SyncEasy.Lock();
}/*
ZtCAutoKey(ZCCriticSectEasy& AR_SyncEasy)*/
~ZtCAutoKey()
{
#ifdef _DEBUG_CAUTOKEY_
cout<<"◀◀◀◀ ZtCAutoKey::~ZtCAutoKey() "<<this<<", "<<--msi_CallCnt<<" ◀◀◀◀"<<endl;
#endif //_DEBUG_CAUTOKEY_
mr_SyncEasy.UnLock();
}/*
~ZtCAutoKey()*/
public:
};/*
template<typename TCriticSectEasy=ZCCriticSectEasy> class ZtCAutoKey */
#ifdef _DEBUG_CAUTOKEY_
template<typename TCriticSectEasy>
int ZtCAutoKey<TCriticSectEasy>::msi_CallCnt = 0;
#endif //_DEBUG_CAUTOKEY_
/*////////////////////////////////////////////////////////////////
ZtCAutoKeyRev<> ZtCAutoKey<>
Lock , Lock .
.
Dead Lock .
2008-04-09 21:01:00
////////////////////////////////////////////////////////////////*/
template<typename TAutoKey> class ZtCAutoKeyRev
{
private:
TAutoKey& mr_CAutoKey;
public :
ZtCAutoKeyRev(TAutoKey& AR_CAutoKey):mr_CAutoKey(AR_CAutoKey)
{
mr_CAutoKey.mr_SyncEasy.UnLock();
}/*
ZtCAutoKeyRev(TAutoKey& AR_CAutoKey)*/
~ZtCAutoKeyRev()
{
mr_CAutoKey.mr_SyncEasy.Lock();
}/*
~ZtCAutoKeyRev()*/
public:
};/*
template<typename TAutoKey> class ZtCAutoKeyRev */
/*////////////////////////////////////////////////////
http://blog.naver.com/kimsk99?Redirect=Log&logNo=50004383787
, CreateThread와 _beginthread라는 , .
API같은 CreateThread를 . . MSDN에
. CreateThread는 SDK에서 API
. . _beginthread( _beginthreadex) standard C
library에 . .
. _beginthread와 .
_beginthreadex는 CreateThread와 . CreateThread _beginthreadex
.
_beginthread standard C library에서 TLB . standary C
library에 thread-safty를 TLB를 .
_beginthreadex ExitThread
_endthreadex .
C library를 _beginthreadex .
uintptr_t _beginthreadex
(
void *security,
unsigned stack_size,
unsigned ( *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
--
////////////////////////////////////////////////////*/
//////////////////////////////////////////////////////
///////////////// 쓰레드 관련 클래스 /////////////////
//////////////////////////////////////////////////////
/*////////////////////////////////////////////////////
uintptr_t _beginthreadex
(
void *security,
unsigned stack_size,
unsigned ( __stdcall *start_address )( void * ),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
HANDLE CreateThread
(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE AP_StartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
CreateThread _beginthreadex .
dwCreationFlags
[in] Flags that control the creation of the thread.
If the CREATE_SUSPENDED flag is specified,
the thread is created in a suspended state,
and will not run until the ResumeThread function is called.
If this value is zero,
the thread runs immediately after creation.
If the STACK_SIZE_PARAM_IS_A_RESERVATION flag is specified,
the dwStackSize parameter specifies the initial reserve size of the stack.
Otherwise, dwStackSize specifies the commit size.
Windows 2000/NT and Windows Me/98/95:
The STACK_SIZE_PARAM_IS_A_RESERVATION flag is not supported.
lpThreadId
[out] Pointer to a variable that receives the thread identifier.
If this parameter is NULL, the thread identifier is not returned.
Windows Me/98/95: This parameter may not be NULL.
cf) DWORD ResumeThread( HANDLE hThread );
**** IN WINBASE.H ****
typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)
(
LPVOID lpThreadParameter
);
typedef struct _SECURITY_ATTRIBUTES
{
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE;
LPTHREAD_START_ROUTINE AP_StartAddress
DWORD WINAPI ThreadFunc(LPVOID lpRarameter)
********** MFC object **********
object <afxmt.h>
1) CCriticalSection cs;
cs.Lock();
// 작업코드
cs.Unlock();
2) CEvent event;
Thread
CEvent object Thread CallBack
UINT ThreadFunc(LPVOID pParam)
{
while(TRUE)
{
CEventOvj.Lock(); // 잠이든다.
// 이벤트가 발생할 때 실행될 코드를 적는다.
// 그리고 외부에서
// CEventOvj.PulseEvent(); 이나
// CEventOvj.SetEvent(); 를 호출하면 깨어난다.
// Thread 가 Lock 이 걸려 있지 않은 상태에서
// PulseEvent 함수를 먼저 호출하면 아무일도 일어나지 않고
// 바로 다음 순간에 Lock() 를 호출하면 다시 잠을 잔다.
// SetEvent() 의 경우에는 그냥 통과한다.
}
//while(TRUE)
}
//UINT ThreadFunc(LPVOID pParam)
# Window Thread Callback Type;
DWORD WINAPI ThreadFunc(LPVOID lpParameter);
cf) typedef unsigned long DWORD;
# Linux Thread Callback Type:
void* ThreadFunc()(void*)
////////////////////////////////////////////////////*/
typedef DWORD ThreadReturnType ;
typedef HANDLE ThreadID ;
/*///////////////////////////////////////////////////////////////////
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
///////////////////////////////////////////////////////////////////*/
#define _THREAD_RETURN_ unsigned __stdcall
namespace ZNsIFace
{
class ZCThread_BASE{};
}/*
namespace ZNsIFace*/
template< typename TTypeBase=ZNsIFace::ZCThread_BASE
>
class ZtCThread : public TTypeBase ///////////////////
{
protected:
ThreadID mh_ThreadID;
public :
ZtCThread()
{
_DEBUG_REENTRANT_CHECK_
mh_ThreadID = INVALID_HANDLE_VALUE ;
}/*
ZtCThread()*/
ZtCThread(TTypeBase& AR_CBaseType):TTypeBase(AR_CBaseType)
{
_DEBUG_REENTRANT_CHECK_
}/*
ZtCThread(TTypeBase& AR_CBaseType):TTypeBase(AR_CBaseType)*/
ZtCThread(const ZtCThread& rhs):TTypeBase(rhs)
{
_DEBUG_REENTRANT_CHECK_
mh_ThreadID =rhs.mh_ThreadID ;
(TTypeBase&)(*this)=static_cast<const TTypeBase&>(rhs);
}/*
ZtCThread(TTypeBase& AR_CBaseType):TTypeBase(AR_CBaseType)*/
template<typename TTypeArg>
ZtCThread(const TTypeArg& AR_TTypeArg):TTypeBase(AR_TTypeArg)
{
_DEBUG_REENTRANT_CHECK_
}/*
template<typename TTypeArg>
ZtCThread(const TTypeArg& AR_TTypeArg):TTypeBase(AR_TTypeArg) */
ZtCThread& operator=(const ZtCThread& rhs)
{
return *this; // nothing to do
}/*
ZtCThread& operator=(const ZtCThread& rhs)*/
operator ThreadID () const
{
return mh_ThreadID;
}/*
operator ThreadID () const*/
ThreadID GetThreadID() const
{
return mh_ThreadID;
}/*
ThreadID GetThreadID() const*/
/*///////////////////////////////////////////////////
typedef DWORD (WINAPI *PTHREAD_START_ROUTINE)
(
LPVOID lpThreadParameter
);
typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE;
///////////////////////////////////////////////////*/
bool Make(LPTHREAD_START_ROUTINE AP_StartAddress, void* AP_Arg=0, DWORD dwCreationFlags=0, DWORD dwStackSize=0, LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL)
{
unsigned int VUI_ThreadID=0;
return ( mh_ThreadID = (void*)::/*CreateThread*/_beginthreadex
(
lpThreadAttributes
, dwStackSize
, (unsigned int (__stdcall *)(void *))AP_StartAddress
, AP_Arg
, dwCreationFlags
, &VUI_ThreadID
)
/*****/ )!=INVALID_HANDLE_VALUE ; //////////////////////////////////
#if 0 // CreateThread() 함수를 쓰는 경우
DWORD VUI_ThreadID;
return ( mh_ThreadID=::CreateThread
(
lpThreadAttributes,
dwStackSize,
AP_StartAddress,
AP_Arg,
dwCreationFlags,
&VUI_ThreadID
)
/*****/ )!=INVALID_HANDLE_VALUE ;
#endif
}/*
bool Make(LPTHREAD_START_ROUTINE AP_StartAddress, void* AP_Arg=0, DWORD dwCreationFlags=0, DWORD dwStackSize=0, LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL)*/
bool Make(unsigned (__stdcall *AP_StartAddress)(void *), void* AP_Arg=0, DWORD dwCreationFlags=0, DWORD dwStackSize=0, LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL)
{
unsigned int VUI_ThreadID=0;
return ( mh_ThreadID=(void*)::_beginthreadex
(
lpThreadAttributes ,
dwStackSize ,
AP_StartAddress ,
AP_Arg ,
dwCreationFlags ,
&VUI_ThreadID
)
/*****/ )!=INVALID_HANDLE_VALUE ; /////////////
}/*
bool Make(unsigned (__stdcall AP_StartAddress*)(void *), void* AP_Arg=0, DWORD dwCreationFlags=0, DWORD dwStackSize=0, LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL)*/
// 쓰레드 종료시까지 메인 함수의 실행을 지연(블럭)시킨다.
int Wait(DWORD ADW_MilliSeconds=INFINITE)
{
return ::WaitForSingleObject(mh_ThreadID, ADW_MilliSeconds);
/* WaitForSingleObject(HANDLE,DWORD ADW_MilliSeconds); 는 3 종류의 반환값을 갖는다.
WAIT_OBJECT_0 : HANDLE object .
WAIT_TIMEOUT : .
WAIT_ABANDONED : */
}/*
int Wait(DWORD ADW_MilliSeconds=INFINITE)*/
static int Wait(ThreadID AI_ThreadIDVar, DWORD ADW_MilliSeconds=INFINITE)
{
return ::WaitForSingleObject(AI_ThreadIDVar, ADW_MilliSeconds);
/* WaitForSingleObject(HANDLE,DWORD ADW_MilliSeconds); 는 3 종류의 반환값을 갖는다.
WAIT_OBJECT_0 : HANDLE object .
WAIT_TIMEOUT : .
WAIT_ABANDONED : */
}/*
static int Wait(ThreadID AI_ThreadIDVar, DWORD ADW_MilliSeconds=INFINITE)*/
bool Terminate(DWORD AI_ExitCode=0)
{
return ::TerminateThread(mh_ThreadID, AI_ExitCode)==TRUE;
}/*
bool Terminate(DWORD AI_ExitCode=0)*/
/*////////////////////////////////////////////////////////
BOOL GetExitCodeThread(
HANDLE hThread,
LPDWORD lpExitCode
);
Parameters
hThread
[in] Handle to the thread.
lpExitCode
[out] Pointer to a 32-bit variable to receive the thread termination status.
Return Values
Nonzero indicates success.
Zero indicates failure.
To get extended error information, call GetLastError.
Remarks
If the specified thread has not terminated,
the termination status returned is STILL_ACTIVE.
The following termination statuses can be returned if the process has terminated:
The exit value specified in the ExitThread or TerminateThread function
The return value from the thread function
The exit value of the thread's process
////////////////////////////////////////////////////////*/
BOOL GetExitCode(DWORD& ARRDW_ExitCode)
{
return ::GetExitCodeThread(mh_ThreadID, &ARRDW_ExitCode);
}/*
BOOL GetExitCode(DWORD& ARRDW_ExitCode)*/
/*//////////////////////////////////////////////////////////////
SuspendThread
ResumeThread .
SuspendThread ResumeThread
0 .
SuspendThread ResumeThread
.
ResumeThread SuspendThread
. . -1
0
0 .
POSIX , POSIX
(, David R. Butenhof) 301 Page
suspend resume .
thr_suspend(), thr_continue() .
--
//////////////////////////////////////////////////////////////*/
DWORD Suspend()
{
return ::SuspendThread(mh_ThreadID);
}/*
DWORD Suspend()*/
DWORD Resume()
{
return ::ResumeThread(mh_ThreadID);
}/*
DWORD Resume()*/
bool Close()
{
return ::CloseHandle(mh_ThreadID)==TRUE;
}/*
bool Close()*/
bool Detach() // for compatibility with linux
{
return true;
}/*
bool Detach()*/
public:
};/*
template< typename TTypeBase=ZNsIFace::ZCThread_BASE
>/
class ZtCThread ////////////////////////////////////*/
template<> class ZtCThread<ZNsIFace::ZCThread_BASE>
{
protected:
ThreadID mh_ThreadID;
public :
ZtCThread()
{
_DEBUG_REENTRANT_CHECK_
mh_ThreadID = INVALID_HANDLE_VALUE ;
}/*
ZtCThread()*/
ZtCThread(const ZtCThread& rhs)
{
mh_ThreadID=rhs.mh_ThreadID;
}/*
ZtCThread(const ZtCThread& rhs)*/
ZtCThread& operator=(const ZtCThread& rhs)
{
return *this;
}/*
ZtCThread& operator=(const ZtCThread& rhs)*/
operator ThreadID () const
{
return mh_ThreadID;
}/*
operator ThreadID () const*/
ThreadID GetThreadID() const
{
return mh_ThreadID;
}/*
ThreadID GetThreadID() const*/
bool Make(LPTHREAD_START_ROUTINE AP_StartAddress, void* AP_Arg=0, DWORD dwCreationFlags=0, DWORD dwStackSize=0, LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL)
{
unsigned int VUI_ThreadID;
return ( mh_ThreadID = (void*)::_beginthreadex
(
lpThreadAttributes,
dwStackSize,
(unsigned int (__stdcall *)(void *))AP_StartAddress,
AP_Arg,
dwCreationFlags,
&VUI_ThreadID
)
/*****/ )!=INVALID_HANDLE_VALUE ; ///////////////
#if 0 // CreateThread() 함수를 쓰는 경우
DWORD VUI_ThreadID;
return ( mh_ThreadID = ::CreateThread
(
lpThreadAttributes,
dwStackSize,
AP_StartAddress,
AP_Arg,
dwCreationFlags,
&VUI_ThreadID
)
/*****/ )!=INVALID_HANDLE_VALUE ;
#endif
}/*
bool Make(LPTHREAD_START_ROUTINE AP_StartAddress, void* AP_Arg=0, DWORD dwCreationFlags=0, DWORD dwStackSize=0, LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL)*/
bool Make(unsigned (__stdcall *AP_StartAddress)(void *), void* AP_Arg=0, DWORD dwCreationFlags=0, DWORD dwStackSize=0, LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL)
{
unsigned int VUI_ThreadID;
return ( mh_ThreadID=(void*)::_beginthreadex
(
lpThreadAttributes ,
dwStackSize ,
AP_StartAddress ,
AP_Arg ,
dwCreationFlags ,
&VUI_ThreadID
)
/*****/ )!=INVALID_HANDLE_VALUE ; /////////////
}/*
bool Make(unsigned (__stdcall AP_StartAddress*)(void *), void* AP_Arg=0, DWORD dwCreationFlags=0, DWORD dwStackSize=0, LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL)*/
int Wait(DWORD ADW_MilliSeconds=INFINITE)
{
return ::WaitForSingleObject(mh_ThreadID, ADW_MilliSeconds);
}/*
int Wait(DWORD ADW_MilliSeconds=INFINITE)*/
static int Wait(ThreadID AI_ThreadIDVar, DWORD ADW_MilliSeconds=INFINITE)
{
return ::WaitForSingleObject(AI_ThreadIDVar, ADW_MilliSeconds);
}/*
static int Wait(ThreadID AI_ThreadIDVar, DWORD ADW_MilliSeconds=INFINITE)*/
bool Terminate(DWORD AI_ExitCode=0)
{
return ::TerminateThread(mh_ThreadID, AI_ExitCode)==TRUE;
}/*
bool Terminate(DWORD AI_ExitCode=0)*/
BOOL GetExitCode(DWORD& ARRDW_ExitCode)
{
return ::GetExitCodeThread(mh_ThreadID, &ARRDW_ExitCode);
}/*
BOOL GetExitCode(DWORD& ARRDW_ExitCode)*/
DWORD Suspend()
{
return ::SuspendThread(mh_ThreadID);
}/*
DWORD Suspend()*/
DWORD Resume()
{
return ::ResumeThread(mh_ThreadID);
}/*
DWORD Resume()*/
bool Close()
{
return ::CloseHandle(mh_ThreadID)==TRUE;
}/*
bool Close()*/
bool Detach() // for compatibility with linux
{
return true;
}/*
bool Detach()*/
public:
};/*
template<> class ZtCThread<ZNsIFace::ZCThread_BASE>*/
/*///////////////////////////////////////////////////////////////////////////////
:
: .
: .
SetEvent ,
ResetEvent .
( .)
WaitForSingleObject()
SetEvent()
.
/ lock
. .
.
, ( ) Window
. 1
.
2008-05-05 15:38:00
///////////////////////////////////////////////////////////////////////////////*/
template<typename TData=ZNsMain::ZCEmpty> class ZtCEvent : public TData
{
protected:
ZTypeID mh_TypeID;
public :
/*//////////////////////////////////////////////////////////////////////////////
CreateEvent()
A handle to the event object indicates success.
If the named event object existed before the function call,
the function returns a handle to the existing object and
GetLastError returns ERROR_ALREADY_EXISTS.
NULL indicates failure. To get extended error information, call GetLastError.
//////////////////////////////////////////////////////////////////////////////*/
bool Make(LPCTSTR AP_Name, BOOL AB_Reset=TRUE, BOOL AB_ManualReset=TRUE, LPSECURITY_ATTRIBUTES AP_SecAtt=NULL)
{
return (mh_TypeID = ::CreateEvent(AP_SecAtt, AB_Reset, AB_ManualReset, AP_Name))!=NULL;
}/*
bool Make(LPCTSTR AP_Name, BOOL AB_Reset=TRUE, BOOL AB_ManualReset=TRUE, LPSECURITY_ATTRIBUTES AP_SecAtt=NULL)*/
bool Set() const // 이벤트를 신호상태로 만든다.
{
return ::SetEvent(mh_TypeID)==TRUE;
}/*
bool Set() const*/
bool Reset() const // 이벤트를 비신호상태로 만든다.
{
return ::ResetEvent(mh_TypeID)==TRUE;
}/*
bool Reset()*/
bool Pulse() const
{
return ::PulseEvent(mh_TypeID)==TRUE;
/*//////////////////////////////////////////////////////////////////////////////////////////////////////
SetEvent() .
.
. MSDN
.
http://msdn.microsoft.com/en-us/library/ms684914(VS.85).aspx
Sets the specified event object to the signaled state and then resets it to the nonsignaled state
after releasing the appropriate number of waiting threads.
Note : This function is unreliable and should not be used.
It exists mainly for backward compatibility. For more information, see Remarks.
"수동 리셋 이벤트에서 자동 리셋 이벤트 효과를 가져다 주는 함수이다."
. ,
. ,
.
MSDN "unreliable" .
-- 2009-02-05 0:10:00
//////////////////////////////////////////////////////////////////////////////////////////////////////*/
}/*
bool Pulse() const*/
int Wait(DWORD ADW_MilliSeconds=INFINITE) const
{
return ::WaitForSingleObject(mh_TypeID, ADW_MilliSeconds);
}/*
int Wait(DWORD ADW_MilliSeconds=INFINITE) const*/
/*//////////////////////////////////////////////////////////////////////////////////////
::WaitForSingleObject()
WAIT_OBJECT_0 : The state of the specified object is signaled.
WAIT_TIMEOUT : The time-out interval elapsed, and the object's state is nonsignaled.
WAIT_FAILED : Fail
Lock ZEThread_OK ZEThread_TimeOut .
//////////////////////////////////////////////////////////////////////////////////////*/
int Lock() const
{
return ::WaitForSingleObject(mh_TypeID, INFINITE);
}/*
int Lock() const*/
int LockRaw(DWORD ADW_MilliSeconds=INFINITE) const
{
return ::WaitForSingleObject(mh_TypeID, ADW_MilliSeconds);
}/*
int LockRaw(DWORD ADW_MilliSeconds=INFINITE) const*/
int LockTime(DWORD AI_TimeOutMili)
{
return LockRaw(AI_TimeOutMili);
}/*
int LockTime(DWORD AI_TimeOutMili)*/
bool UnLock() const // 이벤트를 신호상태로 만든다.
{
return this->Set();
}/*
bool UnLock()*/
public:
};/*
template<typename TData=ZNsMain::ZCEmpty> class ZtCEvent */
template<typename TData=ZNsMain::ZCEmpty> class ZtCBarrier : public TData
{
protected:
ZTypeID mh_EventID; volatile
LONG ml_BarrCnt;
public :
ZtCBarrier()
{
mh_EventID=0;
ml_BarrCnt=0;
}/*
ZtCBarrier()*/
bool IsValid() const{return mh_EventID != 0 ; }
/*/////////////////////////////////////////////////////////////////////////////
Init() Fini() linux bool int .
if(CBarrierObj.Init(3)==ZNsEnum::ZEBarrier_OK)
.
Init() .
/////////////////////////////////////////////////////////////////////////////*/
int Init(unsigned AI_Count, LPSECURITY_ATTRIBUTES AP_SemaphoreAttributes=NULL, LPCTSTR AP_EventName=NULL)
{
if(AI_Count<1) AI_Count=1; ml_BarrCnt=AI_Count;
/*////////////////////////////////////////////////////
::CreateEvent() 3 : bInitialState
If this parameter is TRUE,
the initial state of the event object is signaled;
otherwise, it is nonsignaled
////////////////////////////////////////////////////*/
if(mh_EventID!=0) return ::ResetEvent(mh_EventID)==TRUE;
return (mh_EventID=::CreateEvent( //////////////////////
AP_SemaphoreAttributes ,
TRUE /*bManualReset */ ,
FALSE /*bInitialState*/ ,
AP_EventName)
/*/////////*/ )!=(HANDLE)ERROR_INVALID_HANDLE ; ////////
}/*
int Init(unsigned AI_Count, LPSECURITY_ATTRIBUTES AP_SemaphoreAttributes=NULL, LPCTSTR AP_EventName=NULL)*/
int Fini()
{
bool VB_IsOK=
(::CloseHandle(mh_EventID)==TRUE);
mh_EventID=0; return VB_IsOK;
}/*
int Fini()*/
bool Wait()
{
if(::InterlockedDecrement(&ml_BarrCnt)>0)
{
return ::WaitForSingleObject(mh_EventID, INFINITE) != WAIT_FAILED;
}/*
if(::InterlockedDecrement(&ml_BarrCnt)>0)*/
return ::SetEvent(mh_EventID)==TRUE ;
}/*
bool Wait()*/
/*////////////////////////////////////////////////////////////////////////////////
LONG __cdecl InterlockedDecrement(__inout LONG volatile *Addend);
Parameters : Addend [in, out] : A pointer to the variable to be decremented.
Return Value : The function returns the resulting decremented value.
The variable pointed to by the Addend parameter must be aligned on a 32-bit boundary;
otherwise, this function will behave unpredictably on multiprocessor x86 systems and any non-x86 systems.
See _aligned_malloc.
The interlocked functions provide a simple mechanism for synchronizing access to a variable
that is shared by multiple threads.
This function is atomic with respect to calls to other interlocked functions.
This function is implemented using a compiler intrinsic where possible.
For more information, see the Winbase.h header file and _InterlockedDecrement.
This function generates a full memory barrier (or fence) to ensure
that memory operations are completed in order.
Provides compiler intrinsic support for the Win32 Platform SDK InterlockedDecrement function.
long _InterlockedDecrement(
long * lpAddend
);
long _InterlockedDecrement_acq(
long * lpAddend
);
long _InterlockedDecrement_acq(
long * lpAddend
);
short _InterlockedDecrement16(
short * lpAddend
);
short _InterlockedDecrement16_acq(
short * lpAddend
);
short _InterlockedDecrement16_rel(
short * lpAddend
);
__int64 _InterlockedDecrement64(
__int64 * lpAddend
);
__int64 _InterlockedDecrement64_acq(
__int64 * lpAddend
);
__int64 _InterlockedDecrement64_rel(
__int64 * lpAddend
);
Parameters
[in, out] lpAddend
Pointer to the variable to be decremented.
Return Value
Windows 98, Windows NT 4.0, and later:
The return value is the resulting decremented value.
Windows 95, Windows NT 3.51, and earlier:
If the result of the operation is zero, the return value is zero.
If the result of the operation is less than zero, the return value is negative,
but it is not necessarily equal to the result.
If the result of the operation is greater than zero,
the return value is positive, but it is not necessarily equal to the result.
MSDN InterlockedDecrement
_InterlockedDecrement~ SDK SDK
' ' .
LONG __cdecl InterlockedIncrement(__inout LONG volatile *Addend);
.
////////////////////////////////////////////////////////////////////////////////*/
public:
};/*
template< typename TData=ZNsMain::ZCEmpty
>
class ZtCBarrier ////////////////////////*/
/*///////////////////////////////////////////////////////////////////
barrier 릿
ZtCBarrier<> .
event 2 .
.
lock .
.
-- 2009-01-22 23:06:00
///////////////////////////////////////////////////////////////////*/
template< typename TSyncExec=ZNsMain::ZCCriticSectEasy,
typename TData =ZNsMain::ZCEmpty
>
class ZtCCondBarrier : public TData /////////////////////
{
public :
typedef ZNsMain::ZtCAutoKey<TSyncExec> CAutoKey;
public :
enum EStep
{
EStep_None,
EStep_Init,
EStep_Wait,
EStep_Dead,
EStep_Fini
};/*
enum EStep*/
/*public :*/
protected:
TSyncExec mo_CSyncExec;
ZTypeID mh_EventID ;
ZTypeID mh_EWaitID ; // 대기 목적으로 사용하는 이벤트
int mi_BarrCnt ;
int mi_WaitCnt ;
EStep me_EStep ;
public :
ZtCCondBarrier( LPCTSTR AP_EventName =NULL,
LPCTSTR AP_EventName2=NULL,
LPSECURITY_ATTRIBUTES AP_SemaphoreAttributes =NULL,
LPSECURITY_ATTRIBUTES AP_SemaphoreAttributes2=NULL
/*/////////*/ )
{
me_EStep =EStep_None;
mi_BarrCnt=0 ;
mi_WaitCnt=0 ;
mh_EventID=::CreateEvent( ////////////////////
AP_SemaphoreAttributes ,
TRUE /*bManualReset*/ ,
FALSE /*bInitialState*/,
AP_EventName
/*/////////*/ ); /////////////////////////////
mh_EWaitID=::CreateEvent( ////////////////////
AP_SemaphoreAttributes2 ,
TRUE /*bManualReset*/ ,
FALSE /*bInitialState*/ ,
AP_EventName2
/*/////////*/ ); /////////////////////////////
}/*
ZtCCondBarrier( LPCTSTR AP_EventName =NULL,
LPCTSTR AP_EventName2=NULL,
LPSECURITY_ATTRIBUTES AP_SemaphoreAttributes =NULL,
LPSECURITY_ATTRIBUTES AP_SemaphoreAttributes2=NULL
///////////// ) */
~ZtCCondBarrier()
{
::CloseHandle(mh_EventID);
::CloseHandle(mh_EWaitID);
}/*
~ZtCCondBarrier()*/
EStep GetStep() const
{
return me_EStep;
}/*
EStep GetStep() const*/
bool IsValidID() const
{
return mh_EventID!=(HANDLE)ERROR_INVALID_HANDLE;
}/*
bool IsValidID() const*/
int Init(int AI_Count)
{
CAutoKey VO_CAutoKey(mo_CSyncExec);
if(me_EStep!=EStep_None && me_EStep!=EStep_Fini)
return ZNsEnum::ZEBarrier_NO;
//endif
if(AI_Count<1) AI_Count=1;
mi_BarrCnt=AI_Count ;
mi_WaitCnt=AI_Count ;
me_EStep =EStep_Init;
return ZNsEnum::ZEBarrier_OK;
}/*
int Init(int AI_Count)*/
bool Wait()
{
mo_CSyncExec.Lock();
if(me_EStep==EStep_Init)
{
me_EStep=EStep_Wait;
}
if(me_EStep!=EStep_Wait)
{
mo_CSyncExec.UnLock(); return false;
}/*
if(me_EStep!=EStep_Wait)*/
bool VB_IsOK=false;
if(--mi_BarrCnt>0)
{
#ifdef _DEBUG
cout<<"♤ Wait Barrier : mi_BarrCnt="<<mi_BarrCnt<<endl;
#endif //_DEBUG
mo_CSyncExec.UnLock();
{
VB_IsOK=(::WaitForSingleObject(mh_EventID, INFINITE)!=WAIT_FAILED); // 1)
}
mo_CSyncExec.Lock();
#ifdef _DEBUG
cout<<"♠ Wake Barrier : mi_WaitCnt="<<mi_WaitCnt<<endl;
#endif //_DEBUG
if(--mi_WaitCnt<=1)
{
::SetEvent(mh_EWaitID);
}/*
if(--mi_WaitCnt<=1)*/
}
else // mi_BarrCnt<=0
{
VB_IsOK=(::SetEvent(mh_EventID)==TRUE);
#ifdef _DEBUG
cout<<"♣ Wait mi_WaitCnt : mi_WaitCnt="<<mi_WaitCnt<<endl;
#endif //_DEBUG
if(mi_WaitCnt>1)
{
// 모든 쓰레드가 코드 1) 을 통과하기를 기다린다.
mo_CSyncExec.UnLock();
{
WaitForSingleObject(mh_EWaitID, INFINITE);
}
mo_CSyncExec.Lock();
::ResetEvent(mh_EWaitID);
}/*
if(mi_WaitCnt>1)*/
::ResetEvent(mh_EventID);
me_EStep=EStep_Dead;
}/*
else // mi_BarrCnt<=0*/
mo_CSyncExec.UnLock(); return VB_IsOK;
}/*
bool Wait()*/
int Fini()
{
CAutoKey VO_CAutoKey(mo_CSyncExec);
if(me_EStep!=EStep_Dead) return ZNsEnum::ZEBarrier_NO;
me_EStep=EStep_Fini; return ZNsEnum::ZEBarrier_OK;
}/*
int Fini()*/
public:
};/*
template< typename TSyncExec=ZNsMain::ZCCriticSectEasy,
typename TData =ZNsMain::ZCEmpty
>
class ZtCCondBarrier //////////////////////////////////*/
/*////////////////////////////////////////////////////////////
Posix .
Posix 1:n 1:1 .
WaitCond() 2 , WakeCond() 2
.
.
-- 2008-03-05 21:50:00
////////////////////////////////////////////////////////////*/
template< typename TData=ZNsMain::ZCEmpty
>
class ZtCMutexCondSema : public TData
{
protected:
ZTypeID mh_Semaphore;
public :
ZtCMutexCondSema()
{
mh_Semaphore = (HANDLE)ERROR_INVALID_HANDLE;
}/*
ZtCMutexCondSema()*/
ZTypeID GetHandle() const
{
return mh_Semaphore;
}/*
ZTypeID GetHandle() const*/
int InitCond()
{
mh_Semaphore = ::CreateSemaphore(
NULL/*AP_SemaphoreAttributes*/,
0 /*AL_InitialCnt */,
1 /*AL_MaxCnt */,
NULL/*lpSemaphoreName */ );
return mh_Semaphore!=(HANDLE)ERROR_INVALID_HANDLE ? ZNsEnum::ZEThread_OK : ZNsEnum::ZEThread_Invalid ;
}/*
int InitCond()*/
int FiniCond()
{
if(mh_Semaphore==(HANDLE)ERROR_INVALID_HANDLE)
return ZNsEnum::ZEThread_Invalid;
bool VB_IsOK = (::CloseHandle(mh_Semaphore)==TRUE);
mh_Semaphore = (HANDLE)ERROR_INVALID_HANDLE;
return VB_IsOK ? ZNsEnum::ZEThread_OK : ZNsEnum::ZEThread_Invalid ;
}/*
int FiniCond()*/
int WaitCond()
{
return ::WaitForSingleObject(mh_Semaphore, INFINITE);
}/*
int WaitCond()*/
int WaitCondTime(DWORD AI_TimeOutMili)
{
return ::WaitForSingleObject(mh_Semaphore, AI_TimeOutMili); // return ZEThread_TimeOut if timeout
}/*
int WaitCondTime(DWORD AI_TimeOutMili)*/
int WakeCond()
{
if(::ReleaseSemaphore(mh_Semaphore, 1, NULL)!=0) return ZNsEnum::ZEThread_OK;
return ::GetLastError(); /*##############################################*/
}/*
int WakeCond()*/
public:
};/*
template< typename TData=ZNsMain::ZCEmpty
>
class ZtCMutexCondSema : public TData */
/*//////////////////////////////////////////////////////////////////////
Posix Event .
ZtCMutexCondSema<> . Posix
object .
//////////////////////////////////////////////////////////////////////*/
template< typename TData=ZNsMain::ZCEmpty
>
class ZtCMutexCondEvent : public TData
{
protected:
ZTypeID mh_Event;
public :
ZTypeID GetHandle() const
{
return mh_Event;
}/*
ZTypeID GetHandle() const*/
int InitCond()
{
/*//////////////////////////////////////////////////////
HANDLE WINAPI CreateEvent(
__in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,
__in BOOL bManualReset,
__in BOOL bInitialState,
__in_opt LPCTSTR lpName
);
//////////////////////////////////////////////////////*/
return ((mh_Event=::CreateEvent(NULL, TRUE, TRUE, NULL))!=NULL)
? ZNsEnum::ZEThread_OK : ZNsEnum::ZEThread_Invalid ;
//////
}/*
int InitCond()*/
int FiniCond()
{
return ::CloseHandle(mh_Event)==TRUE ? ZNsEnum::ZEThread_OK : ZNsEnum::ZEThread_Invalid ;
}/*
int FiniCond()*/
int WaitCond()
{
// ::ResetEvent() 는 이벤트를 비신호 상태로 만든다.
if(::ResetEvent(mh_Event)==FALSE) return ZNsEnum::ZEThread_Invalid;
return ::WaitForSingleObject(mh_Event, INFINITE); /*###########*/
}/*
int WaitCond()*/
int WakeCond()
{
if(::SetEvent(mh_Event)==TRUE)
return ZNsEnum::ZEThread_OK;
else
return ::GetLastError();
//else
}/*
int WakeCond()*/
public:
};/*
template< typename TData=ZNsMain::ZCEmpty
>
class ZtCMutexCondEvent : public TData */
#if(_CODE_OLD_)
/*//////////////////////////////////////////////////////////////////
ZtCMutexCondData<> mutex .
WaitCond() WakeCond() .
TMutexCond .
SignalObjectAndWait() .
supported client : Windows 2000 Professional
supported server : Windows 2000 Server
. -- 2009-04-27 00:20:00
//////////////////////////////////////////////////////////////////*/
template< typename TMutexCond=ZNsMain::ZtCMutexCondEvent<>
>
class ZtCMutexCondData : protected TMutexCond, public ZCProcessMutex
{
public:
typedef TMutexCond CMutexCond;
public:
ZtCMutexCondData()
{
this->ZCProcessMutex::Make();
}/*
ZtCMutexCondData()*/
int Lock()
{
return this->ZCProcessMutex::LockRaw(); // 성공시에 ZEThread_OK 를 반환
}/*
int Lock()*/
int UnLock()
{
return this->ZCProcessMutex::UnLock()==true ? ZNsMain::ZNsEnum::ZEThread_OK : ZNsMain::ZNsEnum::ZEThread_Invalid ;
}/*
int UnLock()*/
int WaitCond()
{
this->ZCProcessMutex::UnLock();
{
this->CMutexCond::WaitCond();
}
this->ZCProcessMutex::Lock();
return ZNsMain::ZNsEnum::ZEThread_OK;
}/*
int WaitCond()*/
using CMutexCond::FiniCond;
using CMutexCond::InitCond;
using CMutexCond::WakeCond;
public:
};/*
template< typename TMutexCond=ZNsMain::ZtCMutexCondEvent<> //////////
>
class ZtCMutexCondData : protected TMutexCond, public ZCProcessMutex */
#endif // if(0)
#if defined(__VISUAL_CPP_VER__) && __VISUAL_CPP_VER__>=200800
/*///////////////////////////////////////////////////////////////////////
ZtCMutexCondData<> Linux 릿.
Critical Section . Critical Section
Slim Reader-Writer Lock .
Critical Section .
-- 2010-04-21 06:08:00
Linux , Windows .
-- 2015-09-16 19:59:00
///////////////////////////////////////////////////////////////////////*/
template< typename TData=ZNsMain::ZCEmpty
>
class ZtCMutexCondData : public TData
{
public :
enum{ESpinCount=100};
private:
::CRITICAL_SECTION mo_CritSect;
::CONDITION_VARIABLE mo_CondVar ;
public :
int InitCond()
{
::InitializeConditionVariable(&mo_CondVar);
if(::InitializeCriticalSectionEx(&mo_CritSect, ESpinCount, 0)==TRUE)
return ZNsEnum::ZEThread_OK ;
else return ZNsEnum::ZEThread_Invalid;
}/*
int InitCond()*/
int FiniCond()
{
::DeleteCriticalSection(&mo_CritSect); return ZNsEnum::ZEThread_OK;
}/*
int FiniCond()*/
int WaitCond(DWORD AI_Mili=INFINITE)
{
if(::SleepConditionVariableCS(&mo_CondVar, &mo_CritSect, AI_Mili)==TRUE)
{
return ZNsEnum::ZEThread_OK;
}/*
if(::SleepConditionVariableCS(&mo_CondVar, &mo_CritSect, AI_Mili)==TRUE)*/
return ::GetLastError()==ERROR_TIMEOUT ? ZNsEnum::ZEThread_TimeOut : ZNsEnum::ZEThread_Invalid ;
/*/////////////////////////////////////////////////////////////////////////////////////////////////
dwMilliseconds [in]
SleepConditionVariableCS() 3 dwMilliseconds ,
, 0 . , Critical Section lock
. . SleepConditionVariableCS() timeout lock
.
The time-out interval, in milliseconds.
If the time-out interval elapses, the function re-acquires the critical section and returns zero.
If dwMilliseconds is zero, the function tests the states of the specified objects and returns immediately.
If dwMilliseconds is INFINITE, the function's time-out interval never elapses. For more information, see Remarks.
If the function fails or the time-out interval elapses, the return value is zero.
To get extended error information, call GetLastError. Possible error codes include ERROR_TIMEOUT,
which indicates that the time-out interval has elapsed before another thread has attempted to wake
the sleeping thread.
-- 2013-11-11 20:58:00
/////////////////////////////////////////////////////////////////////////////////////////////////*/
}/*
int WaitCond(DWORD AI_Mili=INFINITE)*/
int WakeCond (){::WakeConditionVariable (&mo_CondVar ); return ZNsEnum::ZEThread_OK;}
int WakeAllCond(){::WakeAllConditionVariable(&mo_CondVar ); return ZNsEnum::ZEThread_OK;}
int Lock (){::EnterCriticalSection (&mo_CritSect); return ZNsEnum::ZEThread_OK;}
int UnLock (){::LeaveCriticalSection (&mo_CritSect); return ZNsEnum::ZEThread_OK;}
public:
};/*
template< typename TData=ZNsMain::ZCEmpty
>
class ZtCMutexCondData : public TData */
#else // !( defined(__VISUAL_CPP_VER__) && __VISUAL_CPP_VER__>=200800 )
template< typename TData=ZNsMain::ZCEmpty
>
class ZtCMutexCondData : public TData
{
private:
ZTypeID mh_MutexSync; // 동기화용 뮤텍스
ZTypeID mh_EventWait; // 대기용 이벤트
bool mb_IsOnWait ;
public :
ZtCMutexCondData()
{
mh_MutexSync=NULL ;
mh_EventWait=NULL ;
mb_IsOnWait =false;
}/*
ZtCMutexCondData()*/
int Lock(DWORD ADW_TimeOut=INFINITE)
{
DWORD VI_Return = ::WaitForSingleObject(mh_MutexSync, ADW_TimeOut); /*/////////////////////////*/
return (VI_Return!=WAIT_ABANDONED && VI_Return!=WAIT_FAILED) ? ZNsEnum::ZEThread_OK : VI_Return ;
}/*
int Lock(DWORD ADW_TimeOut=INFINITE)*/
int UnLock()
{
return (::ReleaseMutex(mh_MutexSync)==TRUE) ? ZNsEnum::ZEThread_OK : ZNsEnum::ZEThread_Invalid ;
}/*
int UnLock()*/
int InitCond()
{
mh_MutexSync = ::CreateMutex(NULL, FALSE, NULL);
if(mh_MutexSync==NULL) return ::GetLastError();
mh_EventWait = ::CreateEvent(NULL, TRUE, FALSE, NULL);
if(mh_EventWait==NULL)
return ::GetLastError();
else
return ZNsEnum::ZEThread_OK;
//else
}/*
int InitCond()*/
int WaitCond(DWORD ADW_TimeOut=INFINITE)
{
/*//////////////////////////////////////////////////////////////////
DWORD WINAPI SignalObjectAndWait(
__in HANDLE hObjectToSignal,
__in HANDLE hObjectToWaitOn,
__in DWORD dwMilliseconds ,
__in BOOL bAlertable
);
HANDLE hObjectToSignal semaphore, mutex, event .
//////////////////////////////////////////////////////////////////*/
if(mb_IsOnWait==false)
{
mb_IsOnWait=true; ::ResetEvent(mh_EventWait); // 이벤트를 비신호 상태로 만든다.
}/*
if(mb_IsOnWait==false)*/
DWORD VI_Return = ::SignalObjectAndWait
( mh_MutexSync, mh_EventWait, ADW_TimeOut, FALSE );
#if(_CODE_BAD_)
return (VI_Return==WAIT_OBJECT_0) ? Lock() : VI_Return;
#else
if(VI_Return==WAIT_OBJECT_0) return Lock();
if(VI_Return==WAIT_TIMEOUT) Lock(); return VI_Return; // -- 2013-11-11 21:10:00
#endif
/*/////////////////////////////////////////////////////////////
SignalObjectAndWait() , ,
Lock() .
pthread .
-- 2009-04-28 08:36:00
SignalObjectAndWait() WAIT_TIMEOUT lock
.
Lock() => WaitCond() => UnLock()
Lock() => WakeCond() => UnLock()
. -- 2013-11-11 21:10:00
/////////////////////////////////////////////////////////////*/
}/*
int WaitCond(DWORD ADW_TimeOut=INFINITE)*/
int WakeCond()
{
if(mb_IsOnWait==true) mb_IsOnWait=false;
return ::SetEvent(mh_EventWait)==TRUE ?
ZNsEnum::ZEThread_OK :
::GetLastError() ;
}/*
int WakeCond()*/
int FiniCond()
{
const bool CB_IsOK1=(::CloseHandle(mh_MutexSync)==TRUE);
const bool CB_IsOK2=(::CloseHandle(mh_EventWait)==TRUE);
return (CB_IsOK1 && CB_IsOK2) ? ZNsEnum::ZEThread_OK : ZNsEnum::ZEThread_Invalid ;
}/*
int FiniCond()*/
public:
};/*
template< typename TData=ZNsMain::ZCEmpty
>
class ZtCMutexCondData //////////////////*/
#endif // !(defined(__VISUAL_CPP_VER__) && __VISUAL_CPP_VER__>=200800)
typedef ZtCMutexCondData<> ZCEventCond; // for compatiblity with Linux
/*////////////////////////////////////////////////////////////////////////////////////
class ZtCAtomicIntSync<>
object
릿. volatile .
lock-free .
VOID WINAPI Sleep(__in DWORD dwMilliseconds);
dwMilliseconds :
A value of zero causes the thread to relinquish the remainder of its time slice
to any other thread of equal priority that is ready to run.
If there are no other threads of equal
relinquish :
[][VN] ~ sth (to sb) () ( ) []
LONG InterlockedCompareExchange(
IN OUT PLONG Destination, IN LONG Exchange, IN LONG Comparand);
If Comparand is equal to *Destination, then *Destination is set to equal Exchange.
Otherwise, *Destination is unchanged.
ZtCAtomicIntSync<> , atomic ,
ZtCAtomicIntSync<>::EUseAtomicInt 0 . atomic
1 .
-- 2010-04-03 18:05:00
ZtCAtomicIntSync<> object ()
, ZtCAtomicIntSync<>::TypeSync object
.
-- 2010-04-17 21:29:00
////////////////////////////////////////////////////////////////////////////////////*/
template< typename TTypeBase=ZNsMain::ZCEmpty
>
class ZtCAtomicIntSync : public TTypeBase
{
public :
typedef ZtCAtomicIntSync TypeSync;
public :
enum{EUseAtomicInt=1};
public :
enum ESync
{
ESync_Lock =0,
ESync_UnLock=1
};/*
enum ESync*/
private:
volatile LONG ml_SyncState;
public :
ZtCAtomicIntSync()
{
ml_SyncState=ESync_UnLock;
}/*
ZtCAtomicIntSync()*/
ZtCAtomicIntSync(const TTypeBase& rhs) : TTypeBase(rhs)
{
ml_SyncState=ESync_UnLock;
}/*
ZtCAtomicIntSync(const TTypeBase& rhs)*/
ZtCAtomicIntSync(const ZtCAtomicIntSync& rhs) : TTypeBase(rhs)
{
ml_SyncState=ESync_UnLock;
}/*
ZtCAtomicIntSync(const ZtCAtomicIntSync& rhs)*/
ZtCAtomicIntSync& operator=(const TTypeBase& rhs)
{
this->TTypeBase::operator=(rhs); return *this;
}/*
ZtCAtomicIntSync& operator=(const TTypeBase& rhs)*/
ZtCAtomicIntSync& operator=(const ZtCAtomicIntSync& rhs)
{
this->TTypeBase::operator=(rhs); return *this;
}/*
ZtCAtomicIntSync& operator=(const ZtCAtomicIntSync& rhs)*/
void Lock()
{
/* &ml_SyncState 과 ESync_UnLock 과 같을 때만,
ml_SyncState ESync_Lock . */
#define __INTERLOCKED_COMP_EXCHANGE__ \
::InterlockedCompareExchange(&ml_SyncState, ESync_Lock, ESync_UnLock)
while(__INTERLOCKED_COMP_EXCHANGE__==ESync_Lock)
{
// 아직 Lock 이 걸려 있는 경우이다.
::Sleep(0);
}/*
while(__INTERLOCKED_COMP_EXCHANGE__==ESync_Lock)*/
#undef __INTERLOCKED_COMP_EXCHANGE__
}/*
void Lock()*/
void UnLock()
{
ml_SyncState=ESync_UnLock;
}/*
void UnLock()*/
public:
};/*
template< typename TTypeBase=ZNsMain::ZCEmpty
>
class ZtCAtomicIntSync : public TTypeBase */
template<> class ZtCAtomicIntSync<ZNsMain::ZCEmpty>
{
public :
enum{EUseAtomicInt=1};
public :
enum ESync
{
ESync_Lock =0,
ESync_UnLock=1
};/*
enum ESync*/
private:
volatile LONG ml_SyncState;
public :
ZtCAtomicIntSync()
{
ml_SyncState=ESync_UnLock;
}/*
ZtCAtomicIntSync()*/
ZtCAtomicIntSync(const ZtCAtomicIntSync& rhs)
{
ml_SyncState=ESync_UnLock;
}/*
ZtCAtomicIntSync(const ZtCAtomicIntSync& rhs)*/
ZtCAtomicIntSync& operator=(const ZtCAtomicIntSync& rhs)
{
return *this;
}/*
ZtCAtomicIntSync& operator=(const ZtCAtomicIntSync& rhs)*/
void Lock()
{
#define __INTERLOCKED_COMP_EXCHANGE__ \
::InterlockedCompareExchange(&ml_SyncState, ESync_Lock, ESync_UnLock)
while(__INTERLOCKED_COMP_EXCHANGE__==ESync_Lock)
{
// 아직 Lock 이 걸려 있는 경우이다.
::Sleep(0);
}/*
while(__INTERLOCKED_COMP_EXCHANGE__==ESync_Lock)*/
#undef __INTERLOCKED_COMP_EXCHANGE__
}/*
void Lock()*/
void UnLock()
{
ml_SyncState=ESync_UnLock;
}/*
void UnLock()*/
public:
};/*
template<> class ZtCAtomicIntSync<ZNsMain::ZCEmpty>*/
#if defined(__VISUAL_CPP_VER__) && __VISUAL_CPP_VER__>=200800
/*//////////////////////////////////////////////////////////////////////////////
Slim Reader-Writer Lock. 'read-write lock lock' .
CriticalSection .
Reader Writer .
Recursively lock을 Owning thread를 .
-- 2013-07-13 20:56:00
//////////////////////////////////////////////////////////////////////////////*/
class ZCSRWLock
{
private:
::RTL_SRWLOCK mo_SRWLOCK;
public :
void Init (){::InitializeSRWLock (&mo_SRWLOCK);}
void LockRead (){::AcquireSRWLockShared (&mo_SRWLOCK);}
void UnLockRead (){::ReleaseSRWLockShared (&mo_SRWLOCK);}
void LockWrite (){::AcquireSRWLockExclusive(&mo_SRWLOCK);}
void UnLockWrite(){::ReleaseSRWLockExclusive(&mo_SRWLOCK);}
bool WaitCond(::PCONDITION_VARIABLE AP_Cond, ULONG AL_Flag=0, DWORD AI_MiliSec=INFINITE)
{
// AL_Flag 이 CONDITION_VARIABLE_LOCKMODE_SHARED 이면 Read Lock, 그렇지 않으면 Write Lock 이다.
return ::SleepConditionVariableSRW(AP_Cond, &mo_SRWLOCK, AI_MiliSec, AL_Flag)==TRUE;
}/*
bool WaitCond(::PCONDITION_VARIABLE AP_Cond, ULONG AL_Flag=0, DWORD AI_MiliSec=INFINITE)*/
public:
};/*
class ZCSRWLock*/
class ZCLockRW // for linux compatiblity
{
public :
enum ELockType
{
ELockType_None,
ELockType_Read,
ELockType_Write
};/*
enum ELockType*/
private:
::RTL_SRWLOCK mo_SRWLOCK ;
ELockType me_ELockType;
public :
ZCLockRW()
{
me_ELockType=ELockType_None;
}/*
ZCLockRW()*/
void Init()
{
::InitializeSRWLock(&mo_SRWLOCK);
}/*
void Init()*/
void LockRead(){
::AcquireSRWLockShared (&mo_SRWLOCK); me_ELockType=ELockType_Read ;}
void LockWrite(){
::AcquireSRWLockExclusive(&mo_SRWLOCK); me_ELockType=ELockType_Write;}
void UnLock()
{
/* me_ELockType 을 설정하는 연산은 동기화 영역에서 수행되고 있음에 주의한다. */
if(me_ELockType==ELockType_Read)
{
me_ELockType=ELockType_None; ::ReleaseSRWLockShared (&mo_SRWLOCK);
}
if(me_ELockType==ELockType_Write)
{
me_ELockType=ELockType_None; ::ReleaseSRWLockExclusive(&mo_SRWLOCK);
}/*
if(me_ELockType==ELockType_Write)*/
}/*
void UnLock()*/
bool WaitCond(::PCONDITION_VARIABLE AP_Cond, ULONG AL_Flag=0, DWORD AI_MiliSec=INFINITE)
{
// linux 의 ZCLockRW 에는 없는 멤버 함수
return ::SleepConditionVariableSRW(AP_Cond, &mo_SRWLOCK, AI_MiliSec,AL_Flag)==TRUE;
}/*
bool WaitCond(::PCONDITION_VARIABLE AP_Cond, ULONG AL_Flag=0, DWORD AI_MiliSec=INFINITE)*/
public:
};/*
class ZCLockRW*/
#endif //defined(__VISUAL_CPP_VER__) && __VISUAL_CPP_VER__>=200800
/*////////////////////////////////////////////////////////////////////////////////////////////////////
named pipe , CreateNamedPipe()
ConnectNamedPipe() . WaitNamedPipe()
' pipe' CreateFile() pipe .
CreateFile() pipe ,
.
CreateNamedPipe() , CreateFile()
. .
PIPE_ACCESS_OUTBOUND GENERIC_READ
PIPE_ACCESS_INBOUND GENERIC_WRITE
ConnectNamedPipe() pipe .
WaitNamedPipe() pipe , pipe
. .
pipe FlushFileBuffer()
. DisconnectNamedPipe() CloseHandle()
. Window API 1134 page.
////////////////////////////////////////////////////////////////////////////////////////////////////*/
class ZCPipe
{
protected:
HANDLE mh_Pipe ;
DWORD mi_ByteOfSended;
DWORD mi_ByteOfRecved;
public :
enum
{
ZEPIPE_OutBuffSize = 1024*8,
ZEPIPE_InBuffSize = 1024*8
};/*
enum*/
public :
ZCPipe()
{
InitVar();
}/*
ZCPipe()*/
void InitVar()
{
mh_Pipe =0;
mi_ByteOfSended=0;
mi_ByteOfRecved=0;
}/*
void InitVar()*/
void InitByteVar()
{
mi_ByteOfSended=0;
mi_ByteOfRecved=0;
}/*
void InitByteVar()*/
DWORD GetByteOfSended() const
{
return mi_ByteOfSended;
}/*
DWORD GetByteOfSended() const*/
DWORD GetByteOfRecved() const
{
return mi_ByteOfRecved;
}/*
DWORD GetByteOfRecved() const*/
// 이름 없는 파이프를 생성한다.
static bool Create(PHANDLE APH_ReadPipe, PHANDLE APH_WritePipe, LPSECURITY_ATTRIBUTES AP_PipeAtt, DWORD AI_Size=0)
{
return ::CreatePipe(APH_ReadPipe, APH_WritePipe, AP_PipeAtt, AI_Size)==TRUE;
}/*
static bool Create(PHANDLE APH_ReadPipe, PHANDLE APH_WritePipe, LPSECURITY_ATTRIBUTES AP_PipeAtt, DWORD AI_Size=0)*/
HANDLE CreateNamed /*######################################################*/
(
LPCTSTR AP_Name
, DWORD AI_OpenMode = PIPE_ACCESS_DUPLEX
, DWORD AI_PipeMode = PIPE_TYPE_BYTE
, DWORD AI_MaxInstance = PIPE_UNLIMITED_INSTANCES
, DWORD AI_OutBufferSize = ZEPIPE_OutBuffSize
, DWORD AI_InBufferSize = ZEPIPE_InBuffSize
, DWORD AI_DefaultTimeOut = 0
, LPSECURITY_ATTRIBUTES AP_SecAtt = NULL
)
/*#########################################################################*/
{
/*///////////////////////////////////////////////////////////////////////
AP_Name
\\\pipe\
. local "." .
MyPipe "\\\\.\\pipe\\MyPipe" .
///////////////////////////////////////////////////////////////////////*/
return mh_Pipe = ::CreateNamedPipe(
AP_Name, AI_OpenMode, AI_PipeMode, AI_MaxInstance, AI_OutBufferSize, AI_InBufferSize, AI_DefaultTimeOut, AP_SecAtt) ;
}/*
HANDLE CreateNamed /*########################################################
(
LPCTSTR AP_Name
, DWORD AI_OpenMode = PIPE_ACCESS_DUPLEX
, DWORD AI_PipeMode = PIPE_TYPE_BYTE
, DWORD AI_MaxInstance = PIPE_UNLIMITED_INSTANCES
, DWORD AI_OutBufferSize = ZEPIPE_OutBuffSize
, DWORD AI_InBufferSize = ZEPIPE_InBuffSize
, DWORD AI_DefaultTimeOut = 0
, LPSECURITY_ATTRIBUTES AP_SecAtt = NULL
)
###########################################################################*/
bool WaitConnect(LPOVERLAPPED AP_LPOVERLAPPED=0)
{
return ::ConnectNamedPipe(mh_Pipe, AP_LPOVERLAPPED)==TRUE || (::GetLastError()==ERROR_PIPE_CONNECTED);
/*///////////////////////////////////////////////////////////////////////////////////////////////
::GetLastError()==ERROR_PIPE_CONNECTED .
CreateNamedPipe() , ConnectNamedPipe() ,
, ConnectNamedPipe() FALSE
::GetLastError()==ERROR_PIPE_CONNECTED
.
///////////////////////////////////////////////////////////////////////////////////////////////*/
}/*
bool WaitConnect(LPOVERLAPPED AP_LPOVERLAPPED=0)*/
/*///////////////////////////////////////////////////////////////////////
BOOL ::WaitNamedPipe(AP_PipeName,AI_TimeOut);
.
.
. TRUE
CreateFile .
.
///////////////////////////////////////////////////////////////////////*/
static bool WaitPipe(LPCTSTR AP_PipeName, DWORD AI_TimeOut=NMPWAIT_WAIT_FOREVER)
{
return ::WaitNamedPipe(AP_PipeName, AI_TimeOut)==TRUE;
}/*
static bool WaitPipe(LPCTSTR AP_PipeName, DWORD AI_TimeOut=NMPWAIT_WAIT_FOREVER)*/
HANDLE CreateFile /*////////////////////////////////////////////////*/
(
LPCTSTR AP_PipeName
, DWORD AI_DesiredAccess = FILE_SHARE_READ | FILE_SHARE_WRITE
, DWORD AI_SharedMode = 0
, LPSECURITY_ATTRIBUTES AP_SecuAtt= NULL
, DWORD AI_CreationDisposition = OPEN_EXISTING
, DWORD AI_FlagAtt = 0
, HANDLE AH_Template = NULL
)
/*//////////////////////////////////////////////////////////////////*/
{
return mh_Pipe = ::CreateFile(
AP_PipeName, AI_DesiredAccess, AI_SharedMode, AP_SecuAtt, AI_CreationDisposition, AI_FlagAtt, AH_Template);
}/*
HANDLE CreateFile
(
LPCTSTR AP_PipeName
, DWORD AI_DesiredAccess = FILE_SHARE_READ | FILE_SHARE_WRITE
, DWORD AI_SharedMode = 0
, LPSECURITY_ATTRIBUTES AP_SecuAtt= NULL
, DWORD AI_CreationDisposition = OPEN_EXISTING
, DWORD AI_FlagAtt = 0
, HANDLE AH_Template = NULL
)
/*//////////////////////////////////////////////////////////////////*/
bool Write(LPCVOID AP_Buffer, DWORD AI_BytesToWrite, LPOVERLAPPED AP_LPOVERLAPPED=0)
{
return ::WriteFile(mh_Pipe, AP_Buffer, AI_BytesToWrite, &mi_ByteOfSended, AP_LPOVERLAPPED)==TRUE;
}/*
bool Write(LPCVOID AP_Buffer, DWORD AI_BytesToWrite, LPOVERLAPPED AP_LPOVERLAPPED=0)*/
bool Write(HANDLE AH_Pipe, LPCVOID AP_Buffer, DWORD AI_BytesToWrite, LPOVERLAPPED AP_LPOVERLAPPED=0)
{
return ::WriteFile(AH_Pipe, AP_Buffer, AI_BytesToWrite, &mi_ByteOfSended, AP_LPOVERLAPPED)==TRUE;
}/*
bool Write(HANDLE AH_Pipe, LPCVOID AP_Buffer, DWORD AI_BytesToWrite, LPOVERLAPPED AP_LPOVERLAPPED=0)*/
bool Read(LPVOID AP_Buffer, DWORD AI_BytesToRead, LPOVERLAPPED AP_LPOVERLAPPED=0)
{
return ::ReadFile(mh_Pipe, AP_Buffer, AI_BytesToRead, &mi_ByteOfRecved, AP_LPOVERLAPPED)==TRUE;
}/*
bool Read(LPVOID AP_Buffer, DWORD AI_BytesToRead, LPOVERLAPPED AP_LPOVERLAPPED=0)*/
bool Read(HANDLE AH_Pipe, LPVOID AP_Buffer, DWORD AI_BytesToRead, LPOVERLAPPED AP_LPOVERLAPPED=0)
{
return ::ReadFile(AH_Pipe, AP_Buffer, AI_BytesToRead, &mi_ByteOfRecved, AP_LPOVERLAPPED)==TRUE;
}/*
bool Read(HANDLE AH_Pipe, LPVOID AP_Buffer, DWORD AI_BytesToRead, LPOVERLAPPED AP_LPOVERLAPPED=0)*/
/*/////////////////////////////////////////////////
BOOL FlushFileBuffers(HANDLE hFile);
hFile
[in] A handle to an open file.
The file handle must have the GENERIC_WRITE access right.
For more information, see File Security and Access Rights.
If hFile is a handle to a communications device,
the function only flushes the transmit buffer.
If hFile is a handle to the server end of a named pipe,
the function does not return
until the client has read all buffered data from the pipe.
-- hFile named pipe
-- client pipe
-- .
////////////////////////////////////////////////*/
bool Flush()
{
return ::FlushFileBuffers(mh_Pipe)==TRUE;
}/*
bool Flush()*/
void CloseConnect()
{
::DisconnectNamedPipe(mh_Pipe);
}/*
void CloseConnect()*/
void CloseHandle()
{
::CloseHandle(mh_Pipe);
}/*
void CloseHandle()*/
void Close()
{
::DisconnectNamedPipe(mh_Pipe);
::CloseHandle(mh_Pipe);
}/*
void Close()*/
public:
};/*
class ZCPipe*/
}/*
namespace ZNsMain*/
/*////////////////////////////////////////////////////////////////////////////
:
_beginthread(), _beginthreadex(), _endthread(), _endthreadex()
.
:
VC++ -> Project -> Settings -> c/c++ -> Category ->
Code Generation -> Use run-time library ->
, /MT, /MD, /MTd, /MDd .
/MT
/MD
/MTd (DEBUG )
/MDd (DEBUG )
--
////////////////////////////////////////////////////////////////////////////*/
#endif //__ZCPPMAIN__PROCESS_WIN_H__