CLStatus CLMessageLoopManager::EnterMessageLoop(void *pContext) { CLStatus s = Initialize(); if(!s.IsSuccess()) { CLLogger::WriteLogMsg("In CLMessageLoopManager::EnterMessageLoop(), Initialize error", 0); return CLStatus(-1, 0); } while(true) { CLMessage *pMsg = WaitForMessage(); if(pMsg == 0) { CLLogger::WriteLogMsg("In CLMessageLoopManager::EnterMessageLoop(), pMsg == 0", 0); continue; } CLStatus s3 = DispatchMessage(pMsg); delete pMsg; if(s3.m_clReturnCode == QUIT_MESSAGE_LOOP) break; } CLStatus s4 = Uninitialize(); if(!s4.IsSuccess()) { CLLogger::WriteLogMsg("In CLMessageLoopManager::EnterMessageLoop(), Uninitialize() error", 0); return CLStatus(-1, 0); } return CLStatus(0, 0); }
CLStatus CLThreadForMsgLoop::Run(void *pContext) { if(m_pCoordinator == 0) return CLStatus(-1, 0); CLEvent event; CLThreadInitialFinishedNotifier notifier(&event); SLExecutiveInitialParameter para;//打包通知变量和运行参数 para.pContext = pContext; para.pNotifier = ¬ifier; CLStatus s = m_pCoordinator->Run(¶); if(!s.IsSuccess()) { CLLogger::WriteLogMesg("In CLThreadForMsgLoop::Run(), m_pThread->Run error", 0); m_bWaitForDeath = false; m_pCoordinator = 0; return CLStatus(-1, 0); } CLStatus s1 = event.Wait(); if(!s1.IsSuccess()) CLLogger::WriteLogMesg("In CLThreadForMsgLoop::Run(), event.Wait error", 0); if(notifier.IsInitialSuccess()) return CLStatus(0,0); else return CLStatus(-1,0); }
CLStatus CLEvent::Wait() { try { CLCriticalSection cs(&m_Mutex); while(m_Flag == 0) { CLStatus s = m_Cond.Wait(&m_Mutex); if(!s.IsSuccess()) { CLLogger::WriteLogMsg("In CLEvent::Wait(), m_Cond.Wait error", 0); return CLStatus(-1, 0); } } m_Flag = 0; } catch(const char* str) { CLLogger::WriteLogMsg("In CLEvent::Wait(), exception arise", 0); return CLStatus(-1, 0); } return CLStatus(0, 0); }
CLStatus CLMessageLoopManager::EnterMessageLoop(void *pContext) { SLExecutiveInitialParameter *para = (SLExecutiveInitialParameter *)pContext; CLStatus s = Initialize();//队列(管道,网络等对象)等的初始化工作 if(!s.IsSuccess()) { throw "In CLMessageLoopManager::EnterMessageLoop(), Initialize() error."; para->pNotifier->NotifyInitialFinished(false); return CLStatus(-1,0); } CLStatus s1 = m_pMessageOberver->Initialize(this,para->pContext);//初始化CLMessageOberver对象,如注册不同消息的处理方法 if(!s1.IsSuccess()) { throw "In CLMessageLoopManager::EnterMessageLoop(), m_pMessageOberver->Initialize error."; para->pNotifier->NotifyInitialFinished(false); return CLStatus(-1,0); } para->pNotifier->NotifyInitialFinished(true); while(true) { CLMessage *pMsg = WaitForMessage(); CLStatus s3 = DispatchMessage(pMsg); if(s3.m_clReturnCode == QUIT_MESSAGE_LOOP) //注意此退出返回码要与QUIT_MESSAGE_LOOP保持一致 break; delete pMsg; } delete m_pMessageOberver; //所有消息处理完毕,删除消息处理方法CLMessageOberver对象 m_pMessageOberver = 0; //这里加入了赋值语句,使得m_pMessageOberver = 0,因为在本类的析构中还释放了一次,造成segmentation fault CLStatus s4 = Uninitialize();//反初始化队列(管道,网络等对象)等 return CLStatus(0,0); }
CLStatus CLLogger::writeLog(const char *msg, long errorCode){ if(msg == 0) return CLStatus(-1,0); if(strlen(msg) == 0) return CLStatus(-1,0); if(fileFd == -1) return CLStatus(-1,0); //带缓冲区的日志类代码实现 unsigned int nLeftRoom = BUFFER_SIZE_LOG_FILE - usedByteForBuffer; unsigned int lengthOfMsg = strlen(msg); char buf[MAX_LINE]; snprintf(buf,MAX_LINE," Error code:%d\r\n",errorCode); unsigned int lengthOfCode = strlen(buf); unsigned int totalLen = lengthOfMsg + lengthOfCode; if(totalLen > BUFFER_SIZE_LOG_FILE){ CLStatus s = flush(); if(!s.isSuccess()) return CLStatus(-1,0); ssize_t r = write(fileFd,msg,lengthOfMsg); if(r == -1) return CLStatus(-1,errno); r = write(fileFd,buf,lengthOfCode); if(r == -1) return CLStatus(-1,errno); } if(totalLen > nLeftRoom){ CLStatus s = flush(); if(!s.isSuccess()) return CLStatus(-1,0); } memcpy(logBuffer + usedByteForBuffer,msg,lengthOfMsg); usedByteForBuffer += lengthOfMsg; memcpy(logBuffer + usedByteForBuffer,buf,lengthOfCode); usedByteForBuffer += lengthOfCode; /*不带缓冲区的日志类代码实现。 * ssize_t n = write(fileFd,msg,strlen(msg)); if(n < 0) return CLStatus(-1,errno); char buf[MAX_LINE]; snprintf(buf,MAX_LINE," Error code:%d\r\n",errorCode); n = write(fileFd, buf, strlen(buf)); if(n < 0){ return CLStatus(-1,errno); }*/ return CLStatus(0,0); }
static void* TestThreadForCLLogger(void *arg) { for(int j = 0; j < 1000; j++) { CLStatus s = CLLogger::GetInstance()->WriteLog("ddd", 5); EXPECT_TRUE(s.IsSuccess()); } }
CLStatus CLLogger::WriteLogMsg(const char* pstrMsg, long lErrorCode) { CLLogger* pLog = GetInstance(); if(pLog == 0) return CLStatus(-1,0); CLStatus s = pLog->WriteLog(pstrMsg, lErrorCode); if(s.IsSuccess()) return CLStatus(0,0); else return CLStatus(-1,0); }
CLStatus CLMsgLoopManagerForSTLqueue::Initialize() { if(m_pMsgReceiver == 0) return CLStatus(-1, 0); CLMessagePoster *pMsgPoster = 0; try { CLExecutiveNameServer *pNameServer = CLExecutiveNameServer::GetInstance(); if(pNameServer == 0) { CLLogger::WriteLogMsg("In CLMsgLoopManagerForSTLqueue::Initialize(), CLExecutiveNameServer::GetInstance error", 0); throw CLStatus(-1, 0); } pMsgPoster = new CLMessagePoster(new CLMsgToPointerSerializer, 0, new CLDataPostChannelBySTLqueueMaintainer(m_pSTLqueue), m_pEvent); CLStatus s2 = pMsgPoster->Initialize(new CLInitialDataPostChannelNotifier(), 0); if(!s2.IsSuccess() && (s2.m_clErrorCode == DATA_POSTER_INITIALIZE_ERROR)) { CLLogger::WriteLogMsg("In CLMsgLoopManagerForSTLqueue::Initialize(), pMsgPoster->Initialize error", 0); throw CLStatus(-1, 0); } CLStatus s = pNameServer->Register(m_strThreadName.c_str(), pMsgPoster, m_pMsgReceiver); if(!s.IsSuccess()) { CLLogger::WriteLogMsg("In CLMsgLoopManagerForSTLqueue::Initialize(), pNameServer->Register error", 0); m_pMsgReceiver = 0; return CLStatus(-1, 0); } return CLStatus(0, 0); } catch(CLStatus& s1) { if(m_pMsgReceiver) { delete m_pMsgReceiver; m_pMsgReceiver = 0; } if(pMsgPoster) delete pMsgPoster; else { delete m_pEvent; delete m_pSTLqueue; } return s1; } }
CLThreadForMsgLoop::~CLThreadForMsgLoop() { if((m_bWaitForDeath) && (m_pCoordinator != 0)) { CLStatus s = m_pCoordinator->WaitForDeath(); //注意此处,必须要调用~CLThreadForMsgLoop的析构函数能能WaitForDeath! if(!s.IsSuccess()) CLLogger::WriteLogMesg("In CLThreadForMsgLoop::~CLThreadForMsgLoop(), m_pCoordinator->WaitForDeath error", 0); } if(m_pCoordinator != 0) delete m_pCoordinator; }
CLStatus CLLogger::writeLogMessage(const char *msg, long errorCode){ CLLogger *log = CLLogger::getInstance(); if(log == 0) return CLStatus(0,0); CLStatus s = log->writeLog(msg,errorCode); if(s.isSuccess()) return CLStatus(0,0); else return CLStatus(-1,0); }
CLMessage* CLMessageQueueByNamedPipe::GetMessage() { CLStatus s = m_Event.Wait(); if(!s.IsSuccess()) { CLLogger::WriteLogMsg("In CLMessageQueueByNamedPipe::GetMessage(), m_Event.Wait error", 0); return 0; } return ReadMsgFromPipe(m_Fd); }
CLMessage* CLMessageQueueBySTLqueue::GetMessage() { CLStatus s = m_Event.Wait(); if(!s.IsSuccess()) { CLLogger::WriteLogMsg("In CLMessageQueue::GetMessage(), m_Event.Wait error", 0); return 0; } return Pop(); }
CLStatus CLLogger::WriteLog(const char *pstrMsg, long lErrorCode) { if(pstrMsg == 0) return CLStatus(-1, 0); if(strlen(pstrMsg) == 0) return CLStatus(-1, 0); if(m_pLogBuffer == 0) return CLStatus(-1, 0); unsigned int nleftroom = BUFFER_SIZE_LOG_FILE - m_nUsedBytesForBuffer; unsigned int len_strmsg = strlen(pstrMsg); char buf[MAX_SIZE]; snprintf(buf, MAX_SIZE, " Error code: %ld\r\n", lErrorCode); unsigned int len_code = strlen(buf); unsigned int total_len = len_code + len_strmsg; if(total_len > BUFFER_SIZE_LOG_FILE) { if(m_Fd == -1) return CLStatus(-1, 0); ssize_t r = write(m_Fd, pstrMsg, len_strmsg); if(r == -1) return CLStatus(-1, errno); r = write(m_Fd, buf, len_code); if(r == -1) return CLStatus(-1, errno); return CLStatus(0, 0); } if(total_len > nleftroom) { CLStatus s = Flush(); if(!s.IsSuccess()) return CLStatus(-1, 0); } memcpy(m_pLogBuffer + m_nUsedBytesForBuffer, pstrMsg, len_strmsg); m_nUsedBytesForBuffer += len_strmsg; memcpy(m_pLogBuffer + m_nUsedBytesForBuffer, buf, len_code); m_nUsedBytesForBuffer += len_code; return CLStatus(0, 0); }
virtual CLStatus RunExecutiveFunction(void* pContext) { for(int i = 0; i < count; i++) { CLStatus s = CLExecutiveNameServer::PostExecutiveMessage(test_pipe_name, new CLMsg1ForCLNonThreadForMsgLoop); if(!s.IsSuccess()) { sleep(1); CLExecutiveNameServer::PostExecutiveMessage(test_pipe_name, new CLMsg1ForCLNonThreadForMsgLoop); } } }
CLMessage * CLMessageQueueBySTLList :: GetMessage() { //Wait until the message has arrived, CLStatus s = m_Event.Wait(); if(!s.IsSuccess()) return 0; CLMessage * pMessage = 0; { CLCriticalSection cs(&m_Mutex); pMessage = m_MessageQueue.front(); m_MessageQueue.pop_front(); //message obj still exits } return pMessage; }
CLCriticalSection::CLCriticalSection(CLMutex *pMutex) { if(pMutex == 0) { CLLogger::WriteLogMesg("In CLCriticalSection::CLCriticalSection(), pMutex == 0.",0); throw "In CLCriticalSection::CLCriticalSection(), pMutex == 0."; } m_pMutex = pMutex; CLStatus s = m_pMutex->Lock(); if(!s.IsSuccess()) { CLLogger::WriteLogMesg("In CLCriticalSection::CLCriticalSection(), m_pMutex->Lock() error.",0); throw "In CLCriticalSection::CLCriticalSection(), m_pMutex->Lock error"; } }
int main() { CLExecutiveFunctionProvider *printer = new CLParaPrinter(); CLExecutive *pThread = new CLThread(printer); pThread->Run((void *)2); CLStatus s = pThread->Run(); if(!s.IsSuccess()) cout << "Run error" << endl; pThread->WaitForDeath(); delete pThread; delete printer; return 0; }
CLConditionVariable::~CLConditionVariable() { if(m_bNeededDestroy) { if(pthread_cond_destroy(m_pConditionVariable)) { throw "In CLConditionVariable::~CLConditionVariable(), pthread_cond_destroy error."; CLLogger::WriteLogMesg("In CLConditionVariable::~CLConditionVariable(), pthread_cond_destroy error.",0); } delete m_pConditionVariable; } if(m_strCondName.length() != 0) { CLStatus s = CLSharedObjectAllocator<CLSharedConditionVariableImpl,pthread_cond_t>::Release(m_strCondName.c_str()); if(!s.IsSuccess()) CLLogger::WriteLogMesg("In CLConditionVariable::~CLConditionVariable(), CLSharedConditionVariableAllocator::Release error", 0); } }
CLStatus CLMsgLoopManagerForSTLQueue::Initialize(){ CLExecutiveNameServer* pNameServer = CLExecutiveNameServer::GetInstance(); if(pNameServer == NULL){ delete m_pMsgQueue; m_pMsgQueue = NULL; CLLogger::WriteLogMsg("In CLMsgLoopManagerForMsgQueue::Initialize(), CLExecutiveNameServer::GetInstance error", 0); return CLStatus(-1,0); } CLStatus s = pNameServer->Register(m_strThreadName.c_str(),new CLThreadCommunicationBySTLQueue(m_pMsgQueue)); if(!s.IsSuccess()){ delete m_pMsgQueue; m_pMsgQueue = 0; CLLogger::WriteLogMsg("In CLMsgLoopManagerForMsgQueue::Initialize() , pNameServer->Register error", 0); return CLStatus(-1,0); } return CLStatus(0,0); }
CLStatus CLDataPosterByNamedPipe::PostData(CLIOVectors *pIOVectors) { if((pIOVectors == 0) || (pIOVectors->Size() == 0)) return CLStatus(-1, DATA_POSTER_POST_ERROR); CLStatus s = m_pNamedPipe->Write(*pIOVectors); if(!s.IsSuccess()) { if(s.m_clErrorCode == EAGAIN) return CLStatus(-1, DATA_POSTER_POST_PENDING); CLLogger::WriteLogMsg("In CLDataPosterByNamedPipe::PostData, m_pNamedPipe->Write error", 0); return CLStatus(-1, DATA_POSTER_POST_ERROR); } if(s.m_clReturnCode == 0) return CLStatus(-1, DATA_POSTER_POST_PENDING); else return s; }
CLStatus CLMessageQueueBySTLqueue::PushMessage(CLMessage * pMessage) { if(pMessage == NULL) return CLStatus(-1, 0); CLStatus s = Push(pMessage); if(!s.IsSuccess()) { CLLogger::WriteLogMsg("In CLMessageQueue::PushMessage(), Push error", 0); return CLStatus(-1, 0); } CLStatus s2 = m_Event.Set(); if(!s2.IsSuccess()) { CLLogger::WriteLogMsg("In CLMessageQueue::PushMessage(), m_Event.Set error", 0); return CLStatus(-1, 0); } return CLStatus(0, 0); }
CLStatus CLThread::Run(void *pContext) //如果新创建的线程还要创建线程,那么m_bThreadCreated会导致线程不安全吗? //不会,因为每个CLThread对象一般只会由一个线程访问,并不会共享给其他线程 { if(m_bThreadCreated) return CLStatus(-1,0); m_pContext = pContext; int r = pthread_create(&m_ThreadID,0,StartFunctionOfThread,this); if(0 != r){ CLLogger::WriteLogMesg("In CLThread::Run(), pthread_create error", r); //delete this; return CLStatus(-1,0); } m_bThreadCreated = true; if(!m_bWaitForDeath) { r = pthread_detach(m_ThreadID); if(0 != r){ CLLogger::WriteLogMesg("In CLThread::Run(), pthread_detach error", r); //delete this; return CLStatus(-1,0); } } CLStatus s = m_EventForWaitingForNewThread.Wait();//等待创建的线程发来通知,只有线程创建好了并发来通知才能主创建线程继续执行 if(!s.IsSuccess()) { CLLogger::WriteLogMesg("In CLThread::Run(), m_EventForWaitingForNewThread.Wait() error", 0); return CLStatus(-1, 0); } CLStatus s1 = m_EventForWaitingForOldThread.Set();//通知被创建线程继续执行 if(!s1.IsSuccess()) { std::cout<<"In CLThread::Run(), m_EventForWaitingForOldThread.Set() error" <<std::endl; CLLogger::WriteLogMesg("In CLThread::Run(), m_EventForWaitingForOldThread.Set() error", 0); return CLStatus(-1, 0); } return CLStatus(0,0); }
CLStatus CLExecutiveNameServer::PostExecutiveMessage(const char* pstrExecutiveName, CLMessage* pMessage){ if(pMessage == 0) return CLStatus(-1, 0); if((pstrExecutiveName == 0) || (strlen(pstrExecutiveName) == 0)){ delete pMessage; return CLStatus(-1, 0); } CLExecutiveNameServer* pNameServer = CLExecutiveNameServer::GetInstance(); if(pNameServer == NULL){ CLLogger::WriteLogMsg("In CLExecutiveNameServer::PostExecutiveMessage(), CLExecutiveNameServer::GetInstance error", 0); delete pMessage; return CLStatus(-1,0); } CLExecutiveCommunication* pComm = pNameServer->GetCommunicationPtr(pstrExecutiveName); if(pComm == NULL){ CLLogger::WriteLogMsg("In CLExecutiveNameServer::PostExecutiveMessage(), pNameServer->GetCommunicationPtr error", 0); delete pMessage; return CLStatus(-1,0); } CLStatus s = pComm->PostExecutiveMessage(pMessage); if(!s.IsSuccess()){ CLLogger::WriteLogMsg("In CLExecutiveNameServer::PostExecutiveMessage(), pComm->PostExecutiveMessage error", 0); CLStatus s = pNameServer->ReleaseCommunicationPtr(pstrExecutiveName); if(!s.IsSuccess()) CLLogger::WriteLogMsg("In CLExecutiveNameServer::PostExecutiveMessage(), pNameServer->ReleaseCommunicationPtr error", 0); return CLStatus(-1,0); } CLStatus s2 = pNameServer->ReleaseCommunicationPtr(pstrExecutiveName); if(!s2.IsSuccess()) CLLogger::WriteLogMsg("In CLExecutiveNameServer::PostExecutiveMessage(), pNameServer->ReleaseCommunicationPtr error", 0); return CLStatus(0, 0); }
CLStatus On_1(CLMessage *pm) { CLMsg1ForCLNonThreadForMsgLoopTest *p = dynamic_cast<CLMsg1ForCLNonThreadForMsgLoopTest*>(pm); EXPECT_TRUE(p != 0); CLMessagePoster *poster = CLExecutiveNameServer::GetInstance()->GetCommunicationPtr(test_pipe_name); EXPECT_TRUE(poster != 0); for(int i = 0; i < count; i++) { CLProtocolDataPoster *pd = new CLProtocolDataPoster(); CLStatus s = poster->PostMessage(new CLMsg2ForCLNonThreadForMsgLoopTest, new CLDataPostResultNotifier(bflagdestroy), pd); if(!s.IsSuccess()) { EXPECT_TRUE(s.m_clErrorCode != MSG_POST_ERROR); if(s.m_clErrorCode == MSG_POST_ERROR) break; while(true) { CLStatus s1 = poster->PostLeftMessage(pd); if(!s1.IsSuccess()) { EXPECT_TRUE(s1.m_clErrorCode != MSG_POST_ERROR); if(s1.m_clErrorCode == MSG_POST_ERROR) break; continue; } break; } } } EXPECT_TRUE(CLExecutiveNameServer::GetInstance()->ReleaseCommunicationPtr(test_pipe_name).IsSuccess()); return CLStatus(0, 0); }
CLStatus CLMsgLoopManagerForPipeQueue::Initialize() { CLPrivateMsgQueuebyNamedPipe *pQueue = dynamic_cast<CLPrivateMsgQueuebyNamedPipe *>(m_pMsgQueue); if(pQueue == 0) return CLStatus(0, 0); CLExecutiveNameServer *pNameServer = CLExecutiveNameServer::GetInstance(); if(pNameServer == 0) { CLLogger::WriteLogMsg("In CLMsgLoopManagerForPipeQueue::Initialize(), CLExecutiveNameServer::GetInstance error", 0); return CLStatus(-1, 0); } CLStatus s = pNameServer->Register(m_strThreadName.c_str(), new CLPrivateExecutiveCommunicationByNamedPipe(m_strThreadName.c_str())); if(!s.IsSuccess()) { CLLogger::WriteLogMsg("In CLMsgLoopManagerForPipeQueue::Initialize(), pNameServer->Register error", 0); return CLStatus(-1, 0); } return CLStatus(0, 0); }
CLStatus CLMsgLoopManagerForSTLqueue::WaitForMessage() { CLStatus s = m_pEvent->Wait(); if(!s.IsSuccess()) { CLLogger::WriteLogMsg("In CLMsgLoopManagerForSTLqueue::WaitForMessage(), m_Event.Wait error", 0); return CLStatus(-1, 0); } long old_size = m_MessageContainer.size(); CLStatus s1 = m_pMsgReceiver->GetMessage(m_MessageContainer); long new_size = m_MessageContainer.size(); if(new_size > old_size) { if(!(m_pEvent->ReleaseSemaphore(new_size - old_size - 1).IsSuccess())) CLLogger::WriteLogMsg("In CLMsgLoopManagerForSTLqueue::WaitForMessage(), m_pEvent->ReleaseSemaphore error; but may be made by the sequence of sendmsg.set.(wait).sendmsg(compute new_size).set", 0); } return s1; }
CLStatus CLEvent::Set() { try { CLCriticalSection cs(&m_Mutex); m_Flag = 1; } catch(const char *str) { CLLogger::WriteLogMsg("In CLEvent::Set(), exception arise", 0); return CLStatus(-1, 0); } CLStatus s = m_Cond.Wakeup(); if(!s.IsSuccess()) { CLLogger::WriteLogMsg("In CLEvent::Set(), m_Cond.Wakeup error", 0); return CLStatus(-1, 0); } return CLStatus(0, 0); }
CLCriticalSection::~CLCriticalSection() { CLStatus s = m_pMutex->Unlock(); if(!s.IsSuccess()) CLLogger::WriteLogMesg("In CLCriticalSection::~CLCriticalSection(), m_pMutex->Unlock() error.",0); }
CLStatus CLLibExecutiveInitializer::Destroy() { int r = pthread_mutex_lock(&m_MutexForInitializer); if(r != 0) { if((m_bInitialized) && (!m_bDestroyed)) CLLogger::WriteLogMsg("In CLLibExecutiveInitializer::Destroy(), pthread_mutex_lock error", r); return CLStatus(-1, r); } try { if((!m_bInitialized) || (m_bDestroyed)) throw CLStatus(-1, 0); CLStatus s1 = CLExecutiveNameServer::Destroy(); if(!s1.IsSuccess()) { CLLogger::WriteLogMsg("In CLLibExecutiveInitializer::Destroy(), CLExecutiveNameServer::Destroy error", 0); throw s1; } CLStatus s3 = CLSharedConditionVariableAllocator::Destroy(); if(!s3.IsSuccess()) { CLLogger::WriteLogMsg("In CLLibExecutiveInitializer::Destroy(), CLSharedConditionVariableAllocator::Destroy error", 0); throw s3; } CLStatus s2 = CLSharedMutexAllocator::Destroy(); if(!s2.IsSuccess()) { CLLogger::WriteLogMsg("In CLLibExecutiveInitializer::Destroy(), CLSharedMutexAllocator::Destroy error", 0); throw s2; } CLStatus s = CLLogger::Destroy(); if(!s.IsSuccess()) throw s; m_bDestroyed = true; throw CLStatus(0, 0); } catch(CLStatus& s) { r = pthread_mutex_unlock(&m_MutexForInitializer); if(r != 0) return CLStatus(-1, r); return s; } catch(...) { r = pthread_mutex_unlock(&m_MutexForInitializer); if(r != 0) return CLStatus(-1, r); return CLStatus(-1, 0); } }
A() { CLStatus s = g_logger.WriteLog("in A()", 0); if(!s.IsSuccess()) cout << "g_logger.WriteLog error" << endl; }