Как сделать поточно-безопасный класс журнала, который поддерживает операции `<<`?

Итак, у меня есть такой класс журнала:

#include <iostream>
#include <sstream>
#include <boost/circular_buffer.hpp>
#include <boost/foreach.hpp>

class FlushInternal;

class Log
{
public:

    static FlushInternal* endl;

    Log(int log_length)
    {
        i = 0;
        messages_buffer = new boost::circular_buffer<std::string>(log_length);
    }

    template <class T>
    Log &operator<<(const T &v)
    {
        current_message << v;
        return *this;
    }

    Log &operator<<(std::ostream&(*f)(std::ostream&)) 
    {
        current_message << *f;
        return *this;
    }

    Log &operator<<(FlushInternal*)
    {
        ++i;
        messages_buffer->push_back(current_message.str());
        clean_stringstream(current_message);
        is_filled();
        return *this;
    }

    boost::circular_buffer<std::string> *messages_buffer;

private:
    int i;
    std::stringstream current_message;

    void is_filled()
    {
        if (i >= messages_buffer->capacity())
        {
            i = 0;
            BOOST_FOREACH(std::string s, *messages_buffer)
            {
                std::cout << ++i << ": "  << s << " ;" << std::endl;
            } 
            i = 0;
        }
    }

    void clean_stringstream(std::stringstream &message)
    {
        message.flush();
        message.clear();
        message.seekp(0);
        message.str("");
    }
};

FlushInternal* Log::endl = 0;

И я могу использовать его так:

#include <log.h>
int main()
{
    Log l(2);
    l << "message one: " << 1 << Log::endl;
    l << "message two:" << " " << 2 << Log::endl;
    l << "message " << "three: " << 3 << Log::endl;
    l << "message" << " "  << "four: " << 4 << Log::endl;
    std::cin.get();
}

Это приведет к выводу:

1: message one: 1 ;
2: message two: 2 ;
1: message three: 3 ;
2: message four: 4 ;

Как видите, у меня может быть столько же << как я хочу внутри каждого сообщения журнала. Я хочу иметь возможность использовать один экземпляр класса Log из многих потоков одновременно. Итак, у меня было бы что-то вроде (псевдокод, который компилируется, запускается, но ничего не отслеживает.):

#include <boost/thread.hpp>
#include <log.h>

Log *l;

void fun_one()
{
    *l << "message one: " << 1 << Log::endl;
    *l << "message two:" << " " << 2 << Log::endl;
}

void fun_two()
{
    *l << "message " << "three: " << 3 << Log::endl;
    *l << "message" << " "  << "four: " << 4 << Log::endl;
}

int main()
{
    l = new Log(2);
    boost::thread(fun_one);
    boost::thread(fun_two);
    std::cin.get();
}

Итак, как вы можете видеть, я хочу, чтобы сообщения вставлялись в журнал с помощью многопоточной функции. Интересно, как сделать так, чтобы мой класс журнала поддерживал это?

0
задан Rella 19 August 2011 в 07:00
поделиться