一個生產者多消費者的應用 , 代碼裏目前就先簡單用了單生成單消費,
每一局麻將都需要記錄:每一次的發牌,抓牌,出牌 ,喫碰槓胡聽;
把所有的牌 序列化成二進制存入文件
每一局麻將生成一個key , 可隨意自己組合
下面代碼思路僅供參考, 還未測試過; 可修改成多線程日誌
主線程唯一需要在開始的時候調用一次 start , 記錄用push;
2種模式可選, 一種不關閉文件handle, 直到一局遊戲結束,再關閉
一種每次打開,寫入,關閉;
2種寫入方式, 一種寫入2進制流 ,
一種把2進制流轉成一個個unsigned long儲存在文件
[ 14張牌從 0x01 ~ 0x48 ] 0x48需要 7 位,因此每張牌用7位來儲存,最多 98 位,
對於一個unsigned long 最多儲存 4 張牌, 因此有14張牌時需要 4個unsigned long
class ErrorInfo{
static const SIZE_T ERR_MSG_SIZE = 1 << 13;
static CRITICAL_SECTION err_cs;
static std::once_flag oneflag;
public:
static void init(){
std::call_once(ErrorInfo::oneflag,&ErrorInfo::init_cs);
}
static void init_cs(){
InitializeCriticalSectionAndSpinCount(&ErrorInfo::err_cs, 4000);
}
static std::string getError(DWORD err){
EnterCriticalSection(&ErrorInfo::err_cs);
static HANDLE g_heap = HeapCreate(0, ERR_MSG_SIZE, 0);
static char *buf = (char*)HeapAlloc(g_heap, 0, ERR_MSG_SIZE);
static std::string errstr;
static std::stringstream ss;
ss.str("");
ss.clear();
errstr.clear();
DWORD syslocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
DWORD ret = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, err, syslocale, buf, ERR_MSG_SIZE, NULL);
if (!ret){
static HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);
if (hDll){
//如果在dll中查找,FORMAT_MESSAGE_FROM_HMODULE 添加上去, 第2個參數填寫句柄
ret = FormatMessageA(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
hDll, err, syslocale, buf, ERR_MSG_SIZE, NULL);
}
}
if (ret && buf){
buf[ret] = 0;
errstr = buf;
LeaveCriticalSection(&ErrorInfo::err_cs);
return errstr;
}
ss << err;
ss >> errstr;
LeaveCriticalSection(&ErrorInfo::err_cs);
return errstr;
}
};
CRITICAL_SECTION ErrorInfo::err_cs;
std::once_flag ErrorInfo::oneflag;
#include <bitset>
struct FileHandleData{
HANDLE hFile;
volatile bool inUse;
std::string filepath;
FileHandleData(HANDLE file = INVALID_HANDLE_VALUE, bool inUse = false):hFile(file),inUse(inUse){}
};
struct storeData{
std::string key; //隨意的key
std::string data; //數據
int type; //類型[抓牌,出牌,喫碰槓等]
int seat; //座位號
storeData(const char * key, const char *data , int nDataLen , int type, int seat):key(key),data(data,nDataLen) , type(type) , seat(seat){}
storeData(storeData && obj) throw() : key(std::move(obj.key)),data(std::move(obj.data)) , type(obj.type) , seat(obj.seat){}
storeData & operator=(storeData && obj) throw(){
if(this != &obj){
key = std::move(obj.key);
data = std::move(obj.data);
type = obj.type;
seat = obj.seat;
}
return *this;
}
};
struct restoreData{
int nLen;
int type;
int seat;
char handCards[14];
char buf[0];
};
class RecordFile
{
CRITICAL_SECTION write_cs;
CRITICAL_SECTION prepare_cs;
CRITICAL_SECTION errlog_cs;
CONDITION_VARIABLE write_cond;
HANDLE hSem;
deque<storeData> prepare_queue;
deque<std::string> wait_for_close_queue;
deque<storeData> write_queue;
std::unordered_map<std::string,FileHandleData> write_map;
HANDLE hThreadProducer;
unsigned tid_producer;
HANDLE hThreadConsumers[4];
unsigned tid_consumers[4];
bool bStopPrepare;
bool bStopProcess;
bool bAllDone;
bool bStarted;
int m_writeThreadCcount;
int m_operate;
int m_writeMode;
std::string cur_dir_name;
HANDLE hErrorLog;
std::string errorLogPath;
std::list<restoreData*> m_restoreList;
public:
enum eOperate { OPENFILE = 1, CLOSEFILE = 2};
enum eSpinCount { SpinCountMin = 1000, SpinCountNormal = 2000, SpinCountMax = 4000};
enum eSemaphoreCount{ SemMin = 200 , SemNormal = 1000 , SemMax = 2000};
enum eWriteMode{ WriteModeStream = 1, WriteModeLong = 2};
RecordFile(int operate =CLOSEFILE ,int writeMode = WriteModeStream, int writeThreadCount = 1):bAllDone(false),
bStarted(false),
bStopProcess(false),
bStopPrepare(false),
m_operate(operate),m_writeMode(writeMode),
m_writeThreadCcount(writeThreadCount)
{
cur_dir_name = std::string(typeid(*this).name()).substr(6);
errorLogPath = cur_dir_name + "/errorlog.log";
ErrorInfo::init();
}
void push(const char * key, const char * data , int nDataLen, int type , int seat){
EnterCriticalSection(&prepare_cs);
prepare_queue.emplace_back(key,data,nDataLen, type , seat);
LeaveCriticalSection(&prepare_cs);
ReleaseSemaphore(hSem,1,0);
}
void start(){
if(bStarted)
return;
if(!(OPENFILE == m_operate || CLOSEFILE == m_operate )){
return;
}
bStarted = true;
bAllDone = false;
bStopProcess = false;
bStopPrepare = false;
hThreadProducer = NULL;
memset(hThreadConsumers,0,sizeof(hThreadConsumers));
InitializeCriticalSectionAndSpinCount(&write_cs , SpinCountMax);
InitializeCriticalSectionAndSpinCount(&prepare_cs , SpinCountMax);
InitializeCriticalSectionAndSpinCount(&errlog_cs , SpinCountMax);
InitializeConditionVariable(&write_cond);
hSem = CreateSemaphoreW(0,0,SemMax,NULL);
if(!RecordFile::pathExists(cur_dir_name.c_str())){
CreateDirectoryA(cur_dir_name.c_str(),NULL);
}
hErrorLog = CreateFileA(errorLogPath.c_str(),GENERIC_WRITE|GENERIC_READ,FILE_SHARE_READ ,
NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if(hErrorLog != INVALID_HANDLE_VALUE){
setAppendFileHandle(hErrorLog);
}
hThreadProducer = (HANDLE)_beginthreadex(0,0,&RecordFile::mem_func_prepare,(void*)this,0,&tid_producer);
for(int i = 0 ; i <m_writeThreadCcount; ++i)
hThreadConsumers[i] = (HANDLE)_beginthreadex(0,0,&RecordFile::mem_func_process ,(void*)this,0,&tid_consumers[i]);
}
virtual ~RecordFile(){
stop();
}
void log_error(const std::string &str){
if(hErrorLog == INVALID_HANDLE_VALUE){
return;
}
DWORD recv= 0 ;
EnterCriticalSection(&errlog_cs);
if(WriteFile(hErrorLog,str.c_str(),str.size() * sizeof(char),&recv,0)){
FlushFileBuffers(hErrorLog);
}
LeaveCriticalSection(&errlog_cs);
}
static bool pathExists(const char * path){
WIN32_FILE_ATTRIBUTE_DATA attr = { 0 };
return 0 != GetFileAttributesExA(path, GetFileExInfoStandard, &attr);
}
void stop(){
if(bAllDone || !bStarted)
return;
bAllDone = true;
bStarted = false;
EnterCriticalSection(&prepare_cs);
bStopPrepare = true;
LeaveCriticalSection(&prepare_cs);
ReleaseSemaphore(&hSem,1,0);
EnterCriticalSection(&write_cs);
bStopProcess = true;
LeaveCriticalSection(&write_cs);
WakeAllConditionVariable(&write_cond);
if(hThreadProducer){
WaitForSingleObject(hThreadProducer,INFINITE);
CloseHandle(hThreadProducer);
hThreadProducer = 0;
}
WaitForMultipleObjects(m_writeThreadCcount,hThreadConsumers,TRUE,INFINITE);
for(int i = 0 ; i < m_writeThreadCcount ; ++i){
if(hThreadConsumers[i]){
CloseHandle(hThreadConsumers[i]);
hThreadConsumers[i] = 0;
}
}
CloseHandle(hSem);
hSem = NULL;
DeleteCriticalSection(&write_cs);
DeleteCriticalSection(&prepare_cs);
DeleteCriticalSection(&errlog_cs);
}
bool setAppendFileHandle(HANDLE fileHandle){
LARGE_INTEGER pos = {0};
if(fileHandle != INVALID_HANDLE_VALUE){
return SetFilePointerEx(fileHandle,pos,0,FILE_END);
}
return false;
}
static unsigned int mem_func_prepare(void * arg){
RecordFile * p = (RecordFile * )arg;
if( OPENFILE == p->m_operate)
return p->__prepareOpenFileMode__();
else if(CLOSEFILE == p->m_operate)
return p->__prepareCloseFileEachTime__();
}
static unsigned int mem_func_process(void * arg){
RecordFile * p = (RecordFile * )arg;
if(OPENFILE == p->m_operate)
return p->__processOpenFileMode__();
else if(CLOSEFILE == p->m_operate)
return p->__processCloseFileEachTime__();
}
std::string getFileName(const char * key){
char filepath[MAX_PATH] = {0};
SYSTEMTIME lt = {0};
GetLocalTime(<);
int len = cur_dir_name.size();
memcpy(filepath,cur_dir_name.c_str(),len* sizeof(char));
sprintf_s(filepath+len,MAX_PATH - len,"/%04d.%02d.%02d %02d.%02d.%02d.%04d-%s.txt",
lt.wYear,lt.wMonth,lt.wDay,lt.wHour,lt.wMinute,lt.wSecond,lt.wMilliseconds,
key);
return filepath;
}
std::list<restoreData *> * restore(const char * key){
std::string filepath = findFile(key);
if(filepath.empty())
return NULL;
if(m_writeMode == WriteModeStream){
readStreamBin(filepath);
}
else if(m_writeMode == WriteModeLong){
readLong(filepath);
}
return &m_restoreList;
}
void readLong(const std::string & filepath){
DWORD nBytesRead;
BOOL bResult;
HANDLE hFile = CreateFileA(filepath.c_str(),GENERIC_READ,
FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile == INVALID_HANDLE_VALUE)
return;
string sbuf;
unsigned long storeArr[4] = {0};
int metaData[3] = {0};
while(1){
int nLen = 0;
int type =0 ;
int seat = 0;
sbuf.clear();
memset(storeArr,0,sizeof(storeArr));
memset(metaData,0,sizeof(metaData));
bResult = ReadFile(hFile,&metaData,sizeof(metaData) , &nBytesRead, 0);
if (bResult && nBytesRead == 0)
break;
nLen = metaData[0];
type = metaData[1];
seat = metaData[2];
cout << "nlen:" << nLen << "," << type<< "," << seat <<endl;
ReadFile(hFile,storeArr,nLen * sizeof(unsigned long ) ,&nBytesRead,0);
if (bResult && nBytesRead == 0)
break;
int needBytesLen = nLen > 3 ? 98 : nLen * 28;
cout << "needBytesLen:" << needBytesLen << endl;
restoreData * pData = (restoreData *)malloc(sizeof(restoreData) + needBytesLen);
memset(pData->buf,0,needBytesLen);
memset(pData->handCards,0,14*sizeof(char));
for(int i = 0 ; i < nLen; ++i){
if(3 == i){
bitset<14> bs14(storeArr[i]);
sbuf.append(bs14.to_string());
}
else{
bitset<28> bs28(storeArr[i]);
sbuf.append(bs28.to_string());
}
}
memcpy(pData->buf,sbuf.c_str(),needBytesLen);
for(int i = 0 ; i < needBytesLen / 7 ; ++i){
bitset<7> bs(sbuf.substr(i*7,7)) ;
pData->handCards[i] = (char)bs.to_ulong();
cout << (int)pData->handCards[i] << " ";
}
m_restoreList.push_back(pData);
cout << endl;
}
}
void readStreamBin(const std::string & filepath){
DWORD nBytesRead;
BOOL bResult;
HANDLE hFile = CreateFileA(filepath.c_str(),GENERIC_READ,
FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile == INVALID_HANDLE_VALUE)
return;
std::string sbuf;
while(1){
int nLen = 0;
int type =0 ;
int seat = 0;
sbuf.clear();
bResult = ReadFile(hFile,&nLen,sizeof(nLen) , &nBytesRead, 0);
if (bResult && nBytesRead == 0)
break;
bResult = ReadFile(hFile,&type,sizeof(type) , &nBytesRead, 0);
if (bResult && nBytesRead == 0)
break;
bResult = ReadFile(hFile,&seat,sizeof(seat) , &nBytesRead, 0);
if (bResult && nBytesRead == 0)
break;
restoreData * pData = (restoreData *)malloc(sizeof(restoreData) + nLen);
memset(pData->buf,0,nLen);
memset(pData->handCards,0,14*sizeof(char));
pData->nLen = nLen;
pData->type = type;
pData->seat = seat;
bResult = ReadFile(hFile,pData->buf,nLen,&nBytesRead,0);
if (bResult && nBytesRead == 0)
break;
sbuf.assign(pData->buf , nLen);
cout << sbuf << endl;
for(int i = 0 ; i < nLen / 7 ; ++i){
bitset<7> bis(sbuf.substr(i * 7, 7));
pData->handCards[i] = bis.to_ulong();
cout << (int)pData->handCards[i] << " ";
}
cout << endl;
m_restoreList.push_back(pData);
}
}
std::string findFile(const char * key){
char filepath[MAX_PATH] = {0};
memcpy(filepath , cur_dir_name.c_str(),cur_dir_name.size());
sprintf_s(filepath+ cur_dir_name.size(), MAX_PATH-cur_dir_name.size(),
"/*%s*",key);
WIN32_FIND_DATAA FindFileData;
HANDLE hFind;
hFind = FindFirstFileA(filepath,&FindFileData);
if(hFind == INVALID_HANDLE_VALUE)
return "";
FindClose(hFind);
return cur_dir_name + "/"+ string(FindFileData.cFileName);
}
virtual unsigned int __prepareCloseFileEachTime__(){
std::string filepath;
bool bInsert_ok = false;
std::string errmsg;
while(true){
bInsert_ok = false;
WaitForSingleObject(hSem,INFINITE);
EnterCriticalSection(&prepare_cs);
if(bStopPrepare){
LeaveCriticalSection(&prepare_cs);
break;
}
storeData data = std::move(prepare_queue.front());
prepare_queue.pop_front();
LeaveCriticalSection(&prepare_cs);
EnterCriticalSection(&write_cs);
auto iter_find = write_map.find(data.key);
auto iter_end = write_map.end();
if(iter_find == iter_end){
filepath = getFileName(data.key.c_str());
FileHandleData fileInfo;
fileInfo.filepath = filepath;
fileInfo.inUse = false;
bInsert_ok = write_map.insert(std::make_pair(data.key,fileInfo)).second;
if(bInsert_ok){
write_queue.push_back(std::move(data));
LeaveCriticalSection(&write_cs);
WakeConditionVariable(&write_cond);
}
else{
LeaveCriticalSection(&write_cs);
errmsg = __FUNCTION__;
errmsg += " insert " + data.key + " failed\r\n";
log_error(errmsg);
}
}
else{
write_queue.push_back(std::move(data));
LeaveCriticalSection(&write_cs);
WakeConditionVariable(&write_cond);
}
}
return 0;
}
virtual unsigned int __processCloseFileEachTime__(){
std::string errmsg;
bool bFind = false;
std::string filepath;
DWORD lastError = 0;
DWORD dwWriten = 0;
bool hasError = false;
int totalSize = 0;
static ostringstream oss;
static const int bufLen = sizeof(int) * 3+ (98 * sizeof(char) );
static char buf[bufLen] = {0};
while(true){
bFind = false;
hasError = false;
oss.clear();
oss.str("");
EnterCriticalSection(&write_cs);
while(!bStopProcess && write_queue.empty()){
SleepConditionVariableCS(&write_cond,&write_cs,INFINITE);
}
if(bStopProcess){
LeaveCriticalSection(&write_cs);
break;
}
storeData data = std::move(write_queue.front());
write_queue.pop_front();
auto iter_find = write_map.find(data.key);
bFind = (iter_find != write_map.end());
if(!bFind){
LeaveCriticalSection(&write_cs);
errmsg = __FUNCTION__;
errmsg += " write_map find error\r\n";
log_error(errmsg);
continue;
}
volatile bool * pInUse = &iter_find->second.inUse;
if(*pInUse == true){
write_queue.push_back(std::move(data));
LeaveCriticalSection(&write_cs);
WakeConditionVariable(&write_cond);
continue;
}
*pInUse = true;
filepath = iter_find->second.filepath;
LeaveCriticalSection(&write_cs);
HANDLE hFile = CreateFileA(filepath.c_str(),GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ,0,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile != INVALID_HANDLE_VALUE){
setAppendFileHandle(hFile);
totalSize = 0 ;
if(WriteModeStream == m_writeMode)
totalSize = transferDataToBin(buf,bufLen,oss,data);
else {
totalSize = transferDataToLong(buf,bufLen, oss,data);
}
cout << "total : " << totalSize << endl;
if(WriteFile(hFile,buf,totalSize,&dwWriten,0)){
FlushFileBuffers(hFile);
CloseHandle(hFile);
}
else{
lastError = GetLastError();
hasError = true;
}
}
else{
lastError = GetLastError();
hasError = true;
}
EnterCriticalSection(&write_cs);
*pInUse = false;
LeaveCriticalSection(&write_cs);
if(hasError){
errmsg = ErrorInfo::getError(lastError);
errmsg += "\r\n";
log_error(errmsg);
}
}
return 0;
}
int transferDataToLong(char * target_buf, int target_buf_len , std::ostringstream &transferStream, const storeData & data){
if(NULL == target_buf || 0 == target_buf_len){
return 0;
}
transferStream.clear();
transferStream.str("");
memset(target_buf,0,target_buf_len);
int nDataLen = data.data.size();
for(int i = 0 ; i < nDataLen ; ++i){
bitset<7> bs(data.data[i]);
transferStream << bs.to_string();
}
std::string str = transferStream.str();
cout << "trase:" << transferStream.str() << ", size:" << transferStream.str().size() << endl;
int needLongCount = 1;
int nLen = transferStream.str().size();
if(nLen <= 28)
needLongCount = 1;
else if(nLen / 28 >= 1)
needLongCount += nLen / 28;
cout << "long count :" << needLongCount << endl;
int seat = data.seat;
int type = data.type;
char * pbuf = target_buf;
memcpy(pbuf,&needLongCount,sizeof(needLongCount));
pbuf+= sizeof(needLongCount);
memcpy(pbuf,&type,sizeof(type));
pbuf += sizeof(type);
memcpy(pbuf, &seat , sizeof(seat));
pbuf += sizeof(seat);
unsigned long bit_long;
for(int i = 0; i < needLongCount ; ++i){
if( 3== i){
bitset<14> bs(str.substr(i*28,14));
bit_long = bs.to_ulong();
memcpy(pbuf, &bit_long , sizeof(bit_long));
cout << "long:" << bs.to_ulong() << ",str:" << bs.to_string() << ",size:" << bs.to_string().size()<< endl;
}
else{
bitset<28> bs(str.substr(i*28,28));
bit_long = bs.to_ulong();
memcpy(pbuf, &bit_long , sizeof(bit_long));
pbuf+= sizeof(bit_long);
cout << "long : " << bs.to_ulong() << ", str:" << bs.to_string() << ",size:" << bs.to_string().size() << endl;
}
cout << endl;
}
cout << (target_buf - pbuf)<< endl;
int totalSize = sizeof(type) + sizeof(needLongCount) + sizeof(seat) + needLongCount * sizeof(unsigned long);
cout << "total: " << totalSize << endl;
return totalSize;
}
int transferDataToBin(char * target_buf, int target_buf_len , std::ostringstream &transferStream, const storeData & data){
if(NULL == target_buf || 0 == target_buf_len){
return 0;
}
transferStream.clear();
transferStream.str("");
memset(target_buf,0,target_buf_len);
int nDataLen = data.data.size();
for(int i = 0 ; i < nDataLen ; ++i){
bitset<7> bs(data.data[i]);
transferStream << bs.to_string();
}
int seat = data.seat;
int type = data.type;
int nLen = transferStream.str().size();
char * pbuf = target_buf;
memcpy(pbuf,&nLen,sizeof(nLen));
pbuf+= sizeof(nLen);
memcpy(pbuf,&type,sizeof(type));
pbuf += sizeof(type);
memcpy(pbuf, &seat , sizeof(seat));
pbuf += sizeof(seat);
memcpy(pbuf,transferStream.str().c_str(),nLen);
return sizeof(seat) + sizeof(type) + sizeof(nLen) + nLen * sizeof(char);
}
virtual unsigned int __prepareOpenFileMode__(){
bool bFind = false;
std::string filepath;
bool bInsert_ok = false;
std::string errmsg;
DWORD errorNo =0;
while(1){
bFind = false;
bInsert_ok = false;
WaitForSingleObject(hSem,INFINITE);
EnterCriticalSection(&prepare_cs);
if(bStopPrepare){
LeaveCriticalSection(&prepare_cs);
break;
}
storeData data = std::move(prepare_queue.front());
prepare_queue.pop_front();
LeaveCriticalSection(&prepare_cs);
EnterCriticalSection(&write_cs);
auto iter = write_map.find(data.key);
if(iter != write_map.end()){
bFind = true;
}
if(!bFind){
filepath = getFileName(data.key.c_str());
HANDLE hFile = CreateFileA(filepath.c_str(),GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ,0,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile != INVALID_HANDLE_VALUE){
FileHandleData fileinfo;
fileinfo.hFile = hFile;
fileinfo.filepath = filepath;
fileinfo.inUse = false;
bInsert_ok = write_map.insert(make_pair(data.key , fileinfo)).second;
if(bInsert_ok){
write_queue.push_back(std::move(data));
LeaveCriticalSection(&write_cs);
WakeConditionVariable(&write_cond);
}
else{
LeaveCriticalSection(&write_cs);
errmsg = __FUNCTION__;
errmsg += " write_map insert failed \r\n";
log_error(errmsg);
}
}
else{
errorNo = GetLastError();
LeaveCriticalSection(&write_cs);
errmsg = ErrorInfo::getError(errorNo);
log_error(errmsg);
}
}
else{
write_queue.push_back(std::move(data));
LeaveCriticalSection(&write_cs);
WakeConditionVariable(&write_cond);
}
}
return 0;
}
virtual unsigned int __processOpenFileMode__(){
bool bFind = false;
std::string errmsg;
DWORD errorNo = 0;
DWORD dwWriten = 0;
bool hasError = false;
int totalSize = 0;
static ostringstream oss;
static const int bufLen = sizeof(int) *3+ 98 * sizeof(char) ;
static char buf[bufLen] = {0};
while (true) {
bFind = false;
hasError = false;
EnterCriticalSection(&write_cs);
while(!bStopProcess && write_queue.empty()){
SleepConditionVariableCS(&write_cond,&write_cs,INFINITE);
}
if(bStopProcess){
LeaveCriticalSection(&write_cs);
break;
}
storeData data = std::move(write_queue.front());
write_queue.pop_front();
auto iter = write_map.find(data.key);
if(iter != write_map.end())
bFind = true;
if(!bFind){
LeaveCriticalSection(&write_cs);
errmsg = __FUNCTION__;
errmsg += " write_map find error \r\n";
log_error(errmsg);
continue;
}
if(iter->second.inUse){
write_queue.push_back(std::move(data));
LeaveCriticalSection(&write_cs);
WakeConditionVariable(&write_cond);
continue;
}
volatile bool *pInUse = &iter->second.inUse;
*pInUse = true;
HANDLE hFile = iter->second.hFile;
LeaveCriticalSection(&write_cs);
if( INVALID_HANDLE_VALUE == hFile){
errmsg = __FUNCTION__;
errmsg += " hFile : INVALID_HANDLE_VALUE\r\n";
log_error(errmsg);
continue;
}
totalSize = 0;
if(RecordFile::WriteModeStream == m_writeMode)
totalSize = transferDataToBin(buf,bufLen,oss,data);
else {
totalSize = transferDataToLong(buf,bufLen ,oss,data);
}
if(WriteFile(hFile,buf, totalSize,&dwWriten,0)){
FlushFileBuffers(hFile);
}
else{
hasError= true;
errorNo = GetLastError();
}
EnterCriticalSection(&write_cs);
*pInUse = false;
LeaveCriticalSection(&write_cs);
if(hasError){
errmsg = __FUNCTION__;
errmsg += ErrorInfo::getError(errorNo);
errmsg += "\r\n";
log_error(errmsg);
}
}
return 0;
}
private:
RecordFile(const RecordFile&);
RecordFile& operator=(const RecordFile &);
};