I am trying to write a thread safe logger class so that i can do the exact same as with cout but with thread safety.
here is the logger class (still working on the type of lock required)
class logger {
public:
logger(LOGGER::output_type type);
logger(const logger& orig);
virtual ~logger();
template <typename T>
logger & operator << (const T & data){
boost::mutex::scoped_lock io_mutex_lock(io_mutex);
(*out)<<data;
return *this;
}
private:
static boost::mutex io_mutex;
std::ostream * out;
};
The poblem is I cannot do the following
log<<"asdfg";
I have to instead do
log<<string("asdfg");
int i = 10;
log<<string ("i = ") << i << endl;
following is the compilation error.
gcc.compile.c++ src/simpleThread/bin/gcc-4.4.5/debug/simpleThread.o
src/simpleThread/simpleThread.cc: In function ‘int main()’:
src/simpleThread/simpleThread.cc:28: error: no match for ‘operator<<’ in ‘((logger*)logOut.logger::operator<< [with T = char [18]](((const char (&)[18])"fibonacci thread ")))->logger::operator<< [with T = int](((const int&)((const int*)(& i)))) << std::endl’
So I guess i am missing some important concept of C++. Please let me know what it is? Is my requirement even achievable
thanks, Kiran
Note that your logger class is still not thread safe:
int i = 10;
log <<string ("i = ") << i << endl;
There is nothing stopping this thread from getting preempted by another another thread printing to logger and producing something like:
i = i = 12
Instead of:
i = 1
i = 2
If you have a compiler with variadic templates, here's one way of fixing this:
#include <ostream>
#include <mutex>
inline void sub_print(std::ostream&) {}
template <class A0, class ...Args>
void
sub_print(std::ostream& os, const A0& a0, const Args& ...args)
{
os << a0;
sub_print(os, args...);
}
std::mutex&
io_mut()
{
static std::mutex m;
return m;
}
template <class ...Args>
void
log(std::ostream& os, const Args& ...args)
{
std::lock_guard<std::mutex> _(io_mut());
sub_print(os, args...);
os.flush();
}
#include <iostream>
int main()
{
int i = 10;
log(std::cout, "i = ", i, '\n');
}
I.e. the mutex is locked until all arguments for given log message are processed. std::endl is handled separately by always flushing the stream after every message.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With