C++ RAII手法实现的线程安全的日志文件写例子

#include <iostream>
#include <fstream>
#include <string>
#include <cstdarg>
#include <cstdio>
#include <pthread.h>

// MutexLock 封装互斥锁的接口
class MutexLock
{
public:
    MutexLock()
    {
        pthread_mutex_init(&mutex_, NULL);
    }
    MutexLock(const MutexLock& rx)
    {
        mutex_ = rx.mutex_;
    }
    ~MutexLock()
    {
        pthread_mutex_destroy(&mutex_);
    }
    void lock(){ pthread_mutex_lock(&mutex_);}
    void unlock(){ pthread_mutex_unlock(&mutex_);}

private:
    MutexLock& operator=(const MutexLock&);

private:
    pthread_mutex_t mutex_;
};

// MutexLockGuard  RAII手法的进入退出加锁解锁
class MutexLockGuard
{
public:
    MutexLockGuard(MutexLock& lock):mutex_lock_(lock)
    {
        mutex_lock_.lock();
    }
    ~MutexLockGuard()
    {
        mutex_lock_.unlock();
    }

private:
    MutexLockGuard();
    MutexLockGuard(const MutexLockGuard& rx);
    MutexLockGuard& operator=(const MutexLockGuard& rx);

private:
    MutexLock& mutex_lock_;
};

// FileHandle  RAII手法的文件句柄类
class FileHandle
{
public:
    FileHandle(const char* s, const char* sMode):file_name_(s)
    {
        std::cout<<file_name_<<" opened"<<std::endl;
        file_ = fopen(s, sMode);
        if (file_ == NULL)
        {
            std::cerr<<s<<" open failed"<<std::endl;
        }
    }
    FileHandle(const std::string& s, const char* sMode):file_name_(s)
    {
        std::cout<<file_name_<<" opened"<<std::endl;
        file_ = fopen(s.c_str(), sMode);
        if (file_ == NULL)
        {
            std::cerr<<s<<" open failed"<<std::endl;
        }
    }
    ~FileHandle()
    {
        std::cout<<file_name_<<" closed"<<std::endl;
        if (file_)
            fclose(file_);
    }
    FILE* get(){return file_;}
    std::string&  get_name(){return file_name_;};

private:
    FileHandle();
    FileHandle(const FileHandle& rx);
    FileHandle& operator = (const FileHandle& rx);

protected:
    FILE* file_;
    std::string  file_name_;
};

// need lock for threading 文件写类,为了兼容c语言风格所以选择了stdio.h
class Loger:public FileHandle
{
public:
    Loger(const char* s):FileHandle(s, "a+"){}
    Loger(const std::string& s):FileHandle(s, "a+"){}
    void _(const char* sFormat, ...)
    {
        MutexLockGuard lock(lock_);
        va_list sList;
        va_start(sList, sFormat);
        vfprintf(file_, sFormat, sList);
        fprintf(file_, "\n");
        fflush(file_);
        va_end(sList);
    }

private:
    Loger();
    Loger(const Loger& rx);
    Loger& operator = (const Loger& rx);
private:
    mutable MutexLock lock_;
}; 

// main 函数读写测试

void* tt(void*)
{
    vector<int> vInt(100);
    int i = 0;
    for(vector<int>::iterator iter = vInt.begin(); iter != vInt.end(); ++iter)
    {
        *iter = i++;
        log._("[%lu]--->[%d]", pthread_self(),*iter);
    }
}

Loger log("/home/chenhao/appx/src/cpp/tt");

int main()
{
    pthread_t tid1, tid2, tid3;

    pthread_create(&tid1, NULL, tt, NULL);
    pthread_create(&tid2, NULL, tt, NULL);
    pthread_create(&tid3, NULL, tt, NULL);

    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    pthread_join(tid3, NULL);
    log._("----------");
        return 0;  

}

时间: 2024-12-29 07:32:10

C++ RAII手法实现的线程安全的日志文件写例子的相关文章

log4j实现每个线程保存一个日志文件

log4j.properties: ### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.Conversion

log4j实现每一个线程保存一个日志文件

log4j.properties: ### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.Conversion

RAII手法封装互斥锁

RAII手法是 Resource Acquisition is Initialization 的缩写,意为“资源获取即初始化”,在使用智能指针时也使用,下面是针对互斥量时的实现, 1 #include <iostream> 2 #include <pthread.h> 3 4 using namespace std; 5 6 class MutexLock 7 { 8 public: 9 MutexLock() 10 { 11 pthread_mutex_init(&mut

在Win7下要通过某个 线程 来调用SavaDialog文件选择框的问题

如果 在Win7下要通过某个 线程 来调用SavaDialog文件选择框的代码  选择窗口 有时会出不来 需要设置如下:    ThreadthreadOfRec = new Thread(ReciveMsg);                threadOfRec.SetApartmentState(ApartmentState.STA);                threadOfRec.IsBackground = true;                threadOfRec.St

线程间共享数据的一个例子

[申明:本文仅限于自我归纳总结和相互交流,有纰漏还望各位指出. 联系邮箱:[email protected]] 题目:输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 求所有子数组的和的最大值.要求时间复杂度为O(n). 题目分析: 一.如果数组中全部为负数,则返回最大负数值即可 二.当既有正数也有负数的时候: (1)从左往右叠加,如果当前叠加值小于或者等于0,则放弃,叠加总和清0(加一个负数或者0是毫无意义的),从此位置继续重新叠加 (

jstack Dump日志文件中的线程状态

jstack Dump 日志文件中的线程状态 dump 文件里,值得关注的线程状态有: 死锁,Deadlock(重点关注)  执行中,Runnable 等待资源,Waiting on condition(重点关注) 等待获取监视器,Waiting on monitor entry(重点关注) 暂停,Suspended 对象等待中,Object.wait() 或 TIMED_WAITING 阻塞,Blocked(重点关注)   停止,Parked 下面我们先从第一个例子开始分析,然后再列出不同线程

死磕 java线程系列之自己动手写一个线程池(续)

(手机横屏看源码更方便) 问题 (1)自己动手写的线程池如何支持带返回值的任务呢? (2)如果任务执行的过程中抛出异常了该怎么处理呢? 简介 上一章我们自己动手写了一个线程池,但是它是不支持带返回值的任务的,那么,我们自己能否实现呢?必须可以,今天我们就一起来实现带返回值任务的线程池. 前情回顾 首先,让我们先回顾一下上一章写的线程池: (1)它包含四个要素:核心线程数.最大线程数.任务队列.拒绝策略: (2)它具有执行无返回值任务的能力: (3)它无法处理有返回值的任务: (4)它无法处理任务

为什么会有多线程?什么是线程安全?如何保证线程安全?(带详细例子)

本文将会回答这几个问题: 为什么会有多线程? 什么是线程安全? 怎么样保证线程安全? 为什么会有多线程 显然,线程安全的问题只会出现在多线程环境中,那么为什么会有多线程呢? 最早期的计算机十分原始,还没有操作系统.想要使用计算机时,人们先把计算机可以执行的指令刻在纸带上,然后让计算机从纸带上读取每一条指令,依次执行.这时候的计算机每次只能执行一个任务,是地地道道的单线程. 这种情况下就产生了三个问题: 1. 计算资源的严重浪费 计算机在执行任务时,总少不了一些输入输出操作,比如计算结果的打印等.

RAII手法封装相互排斥锁

CriticalSectionWrapper是一个接口类 class CriticalSectionWrapper { public: // Factory method, constructor disabled static CriticalSectionWrapper* CreateCriticalSection(); virtual ~CriticalSectionWrapper() {} // Tries to grab lock, beginning of a critical se