简单线程日志

线程池日志

最近需要写日志,我们都知道,日志这东西如果影响了主线程的执行,那么从性能上讲就得不偿失了。所以想起来了弄个线程日志。简单的,直接上代码

#include <iostream>
#include <map>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <unistd.h>


namespace log {



class TaskLog
{
    std::string _fileName;
    std::string _log;
public:
    TaskLog() {}

    void setData(const std::string& fileName, const std::string& log )
    {
        this->_fileName = fileName;
        this->_log = log + "\n";
    }

    std::string fileName()
    {
        return this->_fileName;
    }
    std::string log()
    {
        return this->_log;
    }
};


class ThreadLog
{
    std::atomic<bool> _startLog;
    std::thread* _thread;
    std::condition_variable _condition;
    std::mutex _taskQueueMutex;
    std::queue<TaskLog> _taskQueue;
    std::map<std::string , std::FILE*> _mapFiles;
private:
    ThreadLog() :_startLog(true){

        this->_thread = new std::thread(&ThreadLog::workLog,this);
        sleep(1);
    }
public:
    static ThreadLog * getInst()
    {
        static ThreadLog log;
        return &log;
    }
    ~ThreadLog() {
        std::cout<<" logthread is start exit  \n";
        this->_startLog = false;
        this->_condition.notify_all();
        if(this->_thread)
        {
            std::cout<<" logthread is exit safety \n";
            this->_thread->join();
        }

    }

    void addTask(const TaskLog& task)
    {
        {
            std::unique_lock<std::mutex> lock(this->_taskQueueMutex);
            this->_taskQueue.push(task);
        }
        this->_condition.notify_one();
    }
    void workLog()
    {
        while (this->_startLog) {

            std::atomic<bool> isEmpty(false);
            TaskLog tl;
            {
                std::unique_lock<std::mutex> lock(this->_taskQueueMutex);
                this->_condition.wait(lock, [this] { return !this->_startLog || !this->_taskQueue.empty(); });
                //                if (!this->_startLog && this->_taskQueue.empty())
                //                    return;
                if(this->_taskQueue.empty())
                {
                    isEmpty = true;
                }
                else
                {
                    tl = this->_taskQueue.front();
                    this->_taskQueue.pop();
                }

            }

            if(!isEmpty)
            {
                std::FILE * file = NULL;
                auto iter = this->_mapFiles.find(tl.fileName());
                if(iter != this->_mapFiles.end())
                {
                    file = iter->second;
                }
                else
                {
                    file = fopen(tl.fileName().c_str(),"a+");
                    if(file == NULL)
                    {
                        std::cout<<tl.fileName()<<" is open failed!\n";
                    }
                    else
                    {
                        this->_mapFiles.insert(std::make_pair(tl.fileName(),file));
                    }
                }

                fwrite(tl.log().c_str(),sizeof (char),tl.log().length(),file);
                fflush(file);
            }
        }

                for(const auto &fl : this->_mapFiles)
                {
                    fclose(fl.second);
                    std::cout<<fl.first<<" file is closed safety \n";
                }

//        auto iterfile = this->_mapFiles.begin();
//        while (iterfile != this->_mapFiles.end()) {
//            fclose(iterfile->second);
//            iterfile->second = NULL;
//            std::cout<<iterfile->first<<" file is closed safety \n";
//            iterfile++;
//        }
    }

};

#define LOGINFO(x)  log::TaskLog taskInfo; taskInfo.setData("loginfo.log",x); log::ThreadLog::getInst()->addTask(taskInfo);

#define LOGDEBUG(x) log::TaskLog taskDebug; taskDebug.setData("logdebug.log",x); log::ThreadLog::getInst()->addTask(taskDebug);
}

void logTest()
{
    for (size_t index = 0;index < 100;index++)
    {

        std::string str = "logs" + std::to_string(index);
        LOGINFO(str);
        LOGDEBUG(str);
    }
}

void testlogMutiThread( int thread = 8)
{
    std::vector<std::thread*> vth;
    for (int i = 0; i < thread;i++)
    {
        std::thread * th = new std::thread(logTest);
        sleep(1);
        vth.push_back(th);
    }

    for (const auto t : vth)
    {
        t->join();
    }


}


int main(int argc, char *argv[])
{

    testlogMutiThread();
    //logTest();
    //sleep(100);
    std::cout<<" main(int argc, char *argv[]) over \n";
    return 0;
}

觉得还有的优化,所以就有了下面这个版本

#include <iostream>
#include <map>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <unistd.h>


namespace log {



class TaskLog
{
    std::string _fileName;
    std::string _log;
public:
    TaskLog() {}
    TaskLog(const std::string& fileName, const std::string& log )
    {
        this->_fileName = fileName;
        this->_log = log + "\n";
    }
    void setData(const std::string& fileName, const std::string& log )
    {
        this->_fileName = fileName;
        this->_log = log + "\n";
    }

    std::string fileName()
    {
        return this->_fileName;
    }
    std::string log()
    {
        return this->_log;
    }
};


class ThreadLog
{
    std::atomic<bool> _startLog;
    std::thread* _thread;
    std::condition_variable _condition;
    std::mutex _taskQueueMutex;
    std::queue<TaskLog> _taskQueue;
    std::map<std::string , std::FILE*> _mapFiles;
private:
    ThreadLog() :_startLog(true){

        this->_thread = new std::thread(&ThreadLog::workLog,this);
        sleep(1);
    }
public:
    static ThreadLog * getInst()
    {
        static ThreadLog log;
        return &log;
    }
    ~ThreadLog() {
        std::cout<<" logthread is start exit  \n";
        this->_startLog = false;
        this->_condition.notify_all();
        if(this->_thread)
        {
            std::cout<<" logthread is exit safety \n";
            this->_thread->join();
        }

    }

    template <typename T>
    using FormatFunc =  std::string (*)(const T &);

    template <typename T>
    void addLog(FormatFunc<T> func,const T& data,const std::string& fileName)
    {
        this->addLog(fileName,func(data));
    }

    void addLog(const std::string& fileName, const std::string&  log )
    {
        TaskLog task(fileName,log);
        this->addTask(task);
    }
    void addTask(const TaskLog& task)
    {
        {
            std::unique_lock<std::mutex> lock(this->_taskQueueMutex);
            this->_taskQueue.push(task);
        }
        this->_condition.notify_one();
    }
    void workLog()
    {
        while (this->_startLog) {

            std::atomic<bool> isEmpty(false);
            TaskLog tl;
            {
                std::unique_lock<std::mutex> lock(this->_taskQueueMutex);
                this->_condition.wait(lock, [this] { return !this->_startLog || !this->_taskQueue.empty(); });
                //                if (!this->_startLog && this->_taskQueue.empty())
                //                    return;
                if(this->_taskQueue.empty())
                {
                    isEmpty = true;
                }
                else
                {
                    tl = this->_taskQueue.front();
                    this->_taskQueue.pop();
                }

            }

            if(!isEmpty)
            {
                std::FILE * file = NULL;
                auto iter = this->_mapFiles.find(tl.fileName());
                if(iter != this->_mapFiles.end())
                {
                    file = iter->second;
                }
                else
                {
                    file = fopen(tl.fileName().c_str(),"a+");
                    if(file == NULL)
                    {
                        std::cout<<tl.fileName()<<" is open failed!\n";
                    }
                    else
                    {
                        this->_mapFiles.insert(std::make_pair(tl.fileName(),file));
                    }
                }

                fwrite(tl.log().c_str(),sizeof (char),tl.log().length(),file);
                fflush(file);
            }
        }

                for(const auto &fl : this->_mapFiles)
                {
                    fclose(fl.second);
                    std::cout<<fl.first<<" file is closed safety \n";
                }

//        auto iterfile = this->_mapFiles.begin();
//        while (iterfile != this->_mapFiles.end()) {
//            fclose(iterfile->second);
//            iterfile->second = NULL;
//            std::cout<<iterfile->first<<" file is closed safety \n";
//            iterfile++;
//        }
    }

};

#define LOGINFO(x) log::ThreadLog::getInst()->addLog("loginfo.log",x);
#define LOGDEBUG(x) log::ThreadLog::getInst()->addLog("logdebug.log",x);


}

void logTest()
{
    for (size_t index = 0;index < 100;index++)
    {

        std::string str = "logs" + std::to_string(index);
        LOGINFO(str);
        LOGDEBUG(str);
    }
}

void testlogMutiThread( int thread = 8)
{
    std::vector<std::thread*> vth;
    for (int i = 0; i < thread;i++)
    {
        std::thread * th = new std::thread(logTest);
        sleep(1);
        vth.push_back(th);
    }

    for (const auto t : vth)
    {
        t->join();
    }


}


int main(int argc, char *argv[])
{

    testlogMutiThread();
    //logTest();
    //sleep(100);
    std::cout<<" main(int argc, char *argv[]) over \n";
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值