This topic is 3323 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I've written a logging system based on Boost.Iostreams (I wanted to add date/time information and other stuff to log messages automatically, so I wrote a sink class which I use with boost::iostreams::stream_buffer) but there's a problem with multiple threads trying to access the stream at once. My sink class looks like this:
class log_sink
{
private:
std::string filename_;
std::ofstream outs_;

public:
typedef char char_type;
typedef io::sink_tag category;

log_sink(std::string const &filename);
log_sink(log_sink const &copy);

std::streamsize write(const char* s, std::streamsize n);
};

log_sink::log_sink(std::string const &filename)
: filename_(filename)
{
outs_.open(filename_.c_str());
}

log_sink::log_sink(log_sink const &copy)
: filename_(copy._filename)
{
outs_.open(filename_.c_str());
}

std::streamsize log_sink::write(const char *s, std::streamsize n)
{
boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();

boost::lock_guard<boost::mutex> lock(mutex);
outs_ << now << " : ";
outs_.write(s, n);
outs_.flush();

return n;
}

I've then just got a global ostream, which I use like so:
boost::iostreams::stream_buffer<log_sink> debug_buffer;
std::ostream debug(&debug_buffer);

// ...

debug << "some stuff to write to the file" << std::endl;
Now, notice I use a boost::lock_guard<> in an attempt to prevent multiple threads from writing to the file at once. However, I think the problem is that the s pointer that is passed to the write function is pointing to a buffer that's shared between threads, so the lock doesn't really do much. I've had this problem for a while, and I never really bothered to look into it too much. But then I saw the recent Simple STL Logging article and I thought it might have had a solution. Unfortunately, the author basically got around the multi-threading problem by wrapping the whole "log << stuff" thing in a mutex, like this:
boost::mutex::scoped_lock lock(CLogger::log_mutex);
debug << "some stuff to write to the file" << std::endl;
lock.unlock();

Which I thought was a bit intrusive. I was thinking one way to do it would be to put my global stream object into thread-local storage and then sort out the multi-threading stuff inside my write function, pretty much like it already does. Is there a better way? This is really stretching my knowledge of Boost/SC++L :-)

1. 1
2. 2
Rutin
19
3. 3
4. 4
5. 5

• 14
• 13
• 9
• 12
• 9
• ### Forum Statistics

• Total Topics
631437
• Total Posts
3000070
×