⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nltsappender.h

📁 一些unix下的c/c++的util包
💻 H
字号:
#ifndef _NL_TS_APPENDER_H
#define _NL_TS_APPENDER_H

#include "nlkit/NLAppender.h"
#include "nlkit/NLTime.h"
#include <queue>
#include <iostream>

#include "nlkit/ThreadManager.h"

namespace nlkit
{

class NLTSAppender : public NLAppender
{
class ThreadSafeWriter
{
    typedef ThreadSafeWriter this_class;
    typedef std::basic_ostream<char> ostream_type;
    typedef std::basic_string<char> string_type;

    // forward declaration
    struct thread_info;
    friend struct thread_info;

    // thread-related definitions
    typedef DEFAULT_THREAD_MANAGER thread_manager;
    typedef thread_manager::thread_obj_base thread_obj_base;
    typedef thread_manager::critical_section critical_section;
    typedef thread_manager::auto_lock_unlock auto_lock_unlock;
    // so that from our thread we know the object we're manipulating
    struct thread_info : public thread_obj_base
    {
        thread_info() : m_bHasFinished( false ), m_pThis( NULL )
        {
        }

        /* virtual */ void operator()()
        {
            while ( true )
            {
            	m_pThis->doCheck();/////////////////////
                string_type* pstr = NULL;
                {
                    auto_lock_unlock locker( m_pThis->m_cs );
                    // get the string
                    if ( m_pThis->m_astrMessages.size() > 0 )
                    {
                        pstr = m_pThis->m_astrMessages.front();
                        m_pThis->m_astrMessages.pop();
                    }
                    // ... only when there are no more messages,
                    //    will we ask if we should be destructed
                    else if ( m_pThis->m_bShouldBeDestructed )
                    {
                        // signal to the other thread we've finished
                        m_bHasFinished = true;
                        return;
                    }
                }
                // write the string
                if ( pstr )
                {
                    fprintf( m_pThis->m_pFile, pstr->c_str() );
                    fflush( m_pThis->m_pFile );
                    delete pstr;
                    sem_post( &(m_pThis->sem) );
                }
                else   // nothing to write - wait
                {
                    thread_manager::sleep( 1 );
                }
            }
        }

        this_class* m_pThis;
        volatile bool m_bHasFinished;
    };

public:
    void add_message( const string_type& str )
    {
    	sem_wait( &sem );
        auto_lock_unlock locker( m_cs );
        m_astrMessages.push( new string_type( str ) );
    }

    ThreadSafeWriter( FILE* & pFILE, NLTSAppender* pOwner, int maxQueueSize)
    	: m_maxQueueSize( maxQueueSize ),
          m_pFile( pFILE ),
          m_bShouldBeDestructed( false ),
          m_pOwner( pOwner ),
          m_astrMessages()
    {
        m_info.m_pThis = this;
        sem_init( &sem, 0, m_maxQueueSize );
        thread_manager::create_thread( m_info );
    }

    ~ThreadSafeWriter()
    {
        // signal to the other thread we're about to be
        // destructed
        {
            auto_lock_unlock locker( m_cs );
            m_bShouldBeDestructed = true;
        }
        // wait while the other thread writes all messages
        while ( true )
        {
            auto_lock_unlock locker( m_cs );
            if ( m_info.m_bHasFinished )
                // the other thread has finished
            {
                break;
            }
        }
        sem_destroy( &sem );
    }

    critical_section& cs() const
    {
        return m_cs;
    }
protected:
	void doCheck()
	{
		if ( NLTime::getCalculateBeginTime(NLTime::gettimeofday(), m_pOwner->m_schedule) >= m_pOwner->m_nextRolloverTime )
		{
			m_pOwner->rollover(NLTSAppender::TIME_SWITCH);
			return;
		}

		if ( ftell(m_pFile) > m_pOwner->m_maxFileSize )
		{
			m_pOwner->rollover(NLTSAppender::SIZE_SWITCH);
			return;
		}
	}
private:
    // the critical section used for thread-safe locking
    mutable critical_section m_cs;
    int m_maxQueueSize;
    sem_t sem;

    // needed to create the other thread
    thread_info m_info;
    volatile bool m_bShouldBeDestructed;

    FILE* & m_pFile;
    std::queue<string_type*> m_astrMessages;
    NLTSAppender* m_pOwner;
};
friend class ThreadSafeWriter;

public:
	/**
	 * 构造函数
	 * @param filename:	文件名
	 * @param schedule:	计划,默认按天
	 * @param immediateFlush:	是否立即刷新,默认立即
	 * @param maxFileSize:	最大文件尺寸,默认10M
	 * @param maxBackupIndex:	最大备份索引值,默认10000
	 * @param withAdorn:	是否带装饰语,默认带
	 * @return 无
	 */
	NLTSAppender(const std::string& filename,
			NLDailyRollingSchedule schedule = DAILY,
			bool immediateFlush = true,
			long long maxFileSize = NLLOG_MAX_FILE_SIZE,
			int maxBackupIndex = NLLOG_MAX_INDEX,
			bool withAdorn = true,
			int maxQueueSize = 1000);

	/**
	 * 虚拟析构函数
	 * @param 无
	 * @return 无
	 */
	virtual ~NLTSAppender();

	/**
	 * 关闭文件附加器
	 * @param 无
	 * @return 无
	 */
	virtual void close();

protected:
	/**
	 * 切换类型
	 */
	enum switchtype
	{
		TIME_SWITCH,							/**< 时间造成切换 */
		SIZE_SWITCH,							/**< 文件大小造成切换 */
		CLOSE_SWITCH							/**< 关闭造成切换 */
	};

	/**
	 * 文件附加器处理事件
	 * @param event:	事件
	 * @return 无
	 */
	virtual void append(const NLEvent& event);

	/**
	 * 重新打开文件,并删除原文件
	 * @param filename:	文件名
	 * @param mode:	打开模式
	 * @return 无
	 */
	void reopen(const std::string& filename, const char* type);

	/**
	 * 切换处理
	 * @param type:	切换类型
	 * @return 无
	 */
	void rollover(switchtype type);

	/**
	 * 取切换时的文件名
	 * @param t:	当前时间
	 * @return string:	文件名
	 */
	std::string getFilename(const NLTime& t) const;

	bool m_immediateFlush;						/**< 是否立即刷新 */
	bool m_withAdorn;							/**< 是否带装饰语 */
	FILE* m_out;								/**< 文件输出流 */
	std::string m_filename;							/**< 文件名 */
	ThreadSafeWriter* m_pTSWriter;				/**< 线程安全写 */

	NLDailyRollingSchedule m_schedule;          /**< 循环类型 */
	std::string m_scheduledFilename;					/**< 循环问文件名 */
	NLTime m_nextRolloverTime;					/**< 下一次切换时间 */
	int m_maxBackupIndex;						/**< 最大备份索引值 */

	long long m_maxFileSize;					/**< 最大文件尺寸,单位:字节 */

private:
	/**
	 * 初始化
	 * @param filename:	文件名
	 * @param type:	打开模式
	 * @param maxQueueSize: 写线程队列的最大长度
	 * @return 无
	 */
	void init(const std::string& filename, const char* type, int maxQueueSize);

	/**
	 * 取当前的索引值
	 * @param 无
	 * @return int:	索引值
	 */
	int getCurIdx();

	int m_curIdx;								/**< 当前索引 */

	NLTSAppender(const NLTSAppender&);
	NLTSAppender& operator=(const NLTSAppender&);
};
}

#endif //_NL_TS_APPENDER_H

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -