S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

实现了一个写LOG类

Posted on 2009-01-16 09:42 S.l.e!ep.¢% 阅读(3541) 评论(9)  编辑 收藏 引用 所属分类: C++
//  tracelog.h: interface for the CTraceLog class.
//
///////////////////////////////////////////////////////////////////// /

#if  !defined(TRACELOG_H__B46BAA60_61F0_4CEC_8DEE_E8CC9EF26BA8__INCLUDED_)
#define  TRACELOG_H__B46BAA60_61F0_4CEC_8DEE_E8CC9EF26BA8__INCLUDED_

#if  _MSC_VER > 1000
#pragma once
#endif   //  _MSC_VER > 1000
#pragma warning(disable:
4786 )
#include 
< windows.h >
#include 
< process.h >
#include 
< vector >
#include 
< string >

#pragma warning(disable:
4786 )

#include 
< stdio.h >

class  CTraceLog  
{
public :
    CTraceLog()
    
{
        m_hSemaphore 
=  NULL;
        m_hThread    
=  NULL;
        m_bEndThread 
=   false ;
    }


    
virtual   ~ CTraceLog()
    
{

    }


    
bool  init()
    
{
        
if ( m_hSemaphore  !=  NULL )
            
return   false ;

        m_hSemaphore 
=  ::CreateSemaphore(NULL,  0 0xFFFF , NULL);

        
//  If the function fails, the return value is NULL.
         if ( m_hSemaphore  ==  NULL )
            
return   false ;
        
        
//  the function returns a handle to the existing object and GetLastError returns ERROR_ALREADY_EXISTS.
         if  ( ::GetLastError()  ==  ERROR_ALREADY_EXISTS )
            
return   false ;

        ::InitializeCriticalSection(
& m_CriticalSection);

        
if  ( m_hThread  !=  NULL )
            
return   false ;

        unsigned 
int  nThreadId  =   0 ;
        m_hThread 
=  (HANDLE)_beginthreadex(NULL,  0 , _ThreadProc, ( void * ) this 0 & nThreadId);

        
if ( m_hThread  ==   0  )
            
return   false ;

        
return   true ;
    }


    
bool  uninit()
    
{
        m_bEndThread 
=   true ;
        ::ReleaseSemaphore(m_hSemaphore, 
1 , NULL);

        DWORD dwRet 
=  ::WaitForSingleObject(m_hThread, INFINITE);

        
if  ( dwRet  ==  WAIT_FAILED )
            
return   false ;

        ::CloseHandle(m_hSemaphore);
        m_hSemaphore 
=  NULL;

        ::DeleteCriticalSection(
& m_CriticalSection);

        
return   true ;
    }


    
void  log( const   char *  pszBuf)
    
{
        ::EnterCriticalSection(
& m_CriticalSection);
        
        m_Log.push_back(pszBuf);
        ::ReleaseSemaphore(m_hSemaphore, 
1 , NULL);

        ::LeaveCriticalSection(
& m_CriticalSection);            
    }



protected :

    
virtual   void  _logFile( const   char *  pszBuf)  =   0 ;

    
static  unsigned __stdcall _ThreadProc( void *  pVoid)
    
{
        CTraceLog
*  pThis  =  (CTraceLog * )pVoid;

        
while ( true )
        
{
            DWORD dwRet 
=  ::WaitForSingleObject(pThis -> m_hSemaphore, INFINITE);

            
if  ( dwRet  ==  WAIT_FAILED )
                
break ;

            std::vector
< std:: string >  m_LogCopy;
            
            ::EnterCriticalSection(
& pThis -> m_CriticalSection);
            m_LogCopy.resize(pThis
-> m_Log.size());
            std::copy(pThis
-> m_Log.begin(), pThis -> m_Log.end(), m_LogCopy.begin());
            pThis
-> m_Log.clear();
            ::LeaveCriticalSection(
& pThis -> m_CriticalSection);

            std::vector
< std:: string > ::iterator iter_t;

            
for  ( iter_t  =  m_LogCopy.begin(); iter_t  !=  m_LogCopy.end(); iter_t ++  )
                pThis
-> _logFile(iter_t -> c_str());
                        
            
if  ( pThis -> m_bEndThread )
                
break ;

        }
//  while(true)

        
return   0 ;
    }

        
private :
    std::vector
< std:: string >  m_Log;           //  Log 信息队列
    HANDLE                   m_hSemaphore;       //  信号量
    CRITICAL_SECTION         m_CriticalSection;  //  队列访问互斥量
    HANDLE                   m_hThread;          //  线程 Handle
     bool                      m_bEndThread;       //  结束线程标志
}
;



#endif   //  !defined(TRACELOG_H__B46BAA60_61F0_4CEC_8DEE_E8CC9EF26BA8__INCLUDED_)

Feedback

# re: 实现了一个写LOG类  回复  更多评论   

2009-01-16 11:06 by true
一个线程在调用uninit,另一个线程可能在调用log,这样就有问题,假若 m_bEndThread = true,ThreadProc退出了,这时log对信号量递增计数,有泄露。当然,日志结束一般也是进程结束的时候,无所谓了

# re: 实现了一个写LOG类  回复  更多评论   

2009-01-16 13:02 by abettor
为嘛不用log4c呢?

# re: 实现了一个写LOG类  回复  更多评论   

2009-01-16 13:44 by sleepwom
@true
感谢, uninit 修改为这样
bool uninit()
{
m_bEndThread = true ;
DWORD dwRet = ::WaitForSingleObject(m_hThread, INFINITE);

if ( dwRet == WAIT_FAILED )
return false ;

::ReleaseSemaphore(m_hSemaphore, 1 , NULL);
::CloseHandle(m_hSemaphore);
m_hSemaphore = NULL;

::DeleteCriticalSection( & m_CriticalSection);

return true ;
}

# re: 实现了一个写LOG类  回复  更多评论   

2009-01-16 13:44 by sleepwom
@abettor
log4c 感觉太庞大了,我只需要实现单条线程去写LOG信息,如此而已!

# re: 实现了一个写LOG类  回复  更多评论   

2009-01-16 16:00 by Matrixcoding
@sleepwom
修改后的还是不对的:if ( dwRet == WAIT_FAILED )
return false ; 中途返回的话,m_CriticalSection就泄漏了。

# re: 实现了一个写LOG类  回复  更多评论   

2009-01-16 22:18 by Sleepwom
@Matrixcoding
楼上的,我还真的不知道怎么改

# re: 实现了一个写LOG类  回复  更多评论   

2009-01-16 22:19 by 陈梓瀚(vczh)
critical section在构造函数申请,析构函数释放。
创建log的线程负责释放log
其他线程负责使用log
log自己操作critical section

永不泄漏

# re: 实现了一个写LOG类  回复  更多评论   

2009-01-18 13:41 by tangxinfa
写一个完善的LOG类是很困难的,我觉得有可以使用和一些日志库同样的接口,可能实现时只是输出到cout,而后如有必要可方便地引入庞大的日志库(如:log4cxx),用日志库其实一点都不麻烦,只是多了一点初始化的工作,真正记日志的接口是很简单的,发行时带上1MB的运行时库通常不是大问题,重要的是你不必担心日志相关的代码会有问题。

# re: 实现了一个写LOG类  回复  更多评论   

2009-01-19 10:16 by matrixcoding@gmail.com
@sleepwom
简单点,return false之前把m_CriticalSection也释放了。复杂点的就包装一个良好界面的锁机制。

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理