Synchronize writing to log in a multi-threading process - c++

I implemented a Logger, so it can be used like ostream.
e.g, if someone wants to write to the log - he can do something like this:
LOG << "hello world " << 6 << 8.6 << "\n";
The log will be written to the screen, to log file, and to any other source the user like to (this isn't the issue).
To achieve this goal, I created a macro for LOG:
#define LOG Logger::GetInstance()(__FILENAME__, __func__, __LINE__)
and overloaded operator () and operator <<:
template <typename T>
inline Logger& operator << (const T& msg) {
std::stringstream ss;
ss << msg;
PrintToFile(ss.str());
PrintToScreen(ss.str());
return *this;
}
Logger& Logger::operator () (const std::string& sourceFile, const std::string& funcName, int lineNumber) {
std::stringstream ss;
ss << Utilities::GetFormattedTime("%d.%m.%y %H:%M:%S") << "::" << sourceFile << "(" << lineNumber << ")::" <<
funcName << "::";
PrintToFile(level, ss.str());
PrintToScreen(level, ss.str());
return *this;
}
The problem is when I have more than one thread that is running over my process, the print may be cut, because of context switch between the threads in the middle of the example line above (LOG << "hello world... ")
Using a mutex may not help, because operator << and operator () are not the same function.
Is there any brilliant or simple solution for this problem?

Just from top of my head. If you want to keep your approach with stream io operators as is, you can use sort of proxy object that locks\unlocks mutex.
Please, don't draw attention to coding style (especially swfull and dangerous Logger implementation). Below you can find brief illustration of mentioned idea.
template<class TLogger, class TLockObject>
class LoggerProxy
{
public:
LoggerProxy(TLogger &logger, TLockObject &lockObj)
: m_logger(logger),
m_lockGuard(lockObj)
{
}
template <typename T>
inline LoggerProxy& operator << (const T& msg)
{
m_logger.Write(msg);
return *this;
}
private:
TLogger & m_logger;
std::lock_guard<typename TLockObject> m_lockGuard;
};
//Purpose of code below is just an illustration of usage LoggerProxy class. Don't use it in production code.
class Logger
{
public:
static Logger& GetInstance()
{
static Logger instance;
return instance;
}
static std::mutex& GetLockObject()
{
static std::mutex lockObj;
return lockObj;
}
template <typename T>
inline void Write (const T& msg) {
std::cout << msg << std::endl;
}
};
#define LOG LoggerProxy<Logger, std::mutex>(Logger::GetInstance(), Logger::GetLockObject())
int main()
{
LOG << 10 << "HELLO" << 1.1;
LOG << 101 << "HELLO2" << 11.1;
return 0;
}

You are right that operator<< and operator () are two different function, but that doesn't mean you cannot use a mutex.
From what i can gather from your example in both operator<< and operator() you call at the end the same two functions PrintToFile and PrintToScreen.
This makes me think that the stream common to all threads is in these two functions and not in your operator<< and operator(), so you can actually lock a mutex inside those functions and have thread safe access to the logger.
That being said it remains only to decide if you need two mutex or only one, that depends if you want the logging to be "atomic" as operation or you want to split it.
In the "atomic" version you should use a single version that holds a single mutex while writting to both screen and file thus your logs will execute sequentually.
Instead if you the splitted version you want to have two different functions with two different mutexes, one for the file logging and one for the screen loggin, this one a thread that wants to write to the file doesn't have to wait for threads that have already written to the file and are now writting to the screen. As always remember that having two mutexes has cost.

Share less, lock less.
If you're gonna synchronize on each operator<< you're going to have very lousy performance when your application is compiled with logging enabled.
This is a sketch of how I'd do it:
The Concept
namespace Logging {
struct SinkConcept { void commit(std::string const&); }; // documentation only
Let's design a narrow contract where any logging sink has just that one method.
Now, let's create a LogTx - representing a log-transaction.
LogTx should be a move-aware temporary object creates a log message locally. This means that the buffers are not shared and need not be synchronized until you commit.
Commit is done from the destructor:
// movable log transaction (using arbitrary sink)
template <typename Sink> struct LogTx {
LogTx(Sink& s) : _sink(s) {}
LogTx(LogTx&&) = default;
unique_flag _armed;
std::ostringstream _oss;
Sink& _sink;
~LogTx() { if (_armed) _sink.commit(_oss.str()); }
template <typename T> LogTx& operator<<(T&& rhs)& { return (_oss << rhs), *this; }
template <typename T> LogTx operator<<(T&& rhs)&& { return (_oss << rhs), std::move(*this); }
};
That's all. The _armed flag makes sure the destructor doesn't commit in moved-from instances.
Some Sample Sinks
Now, let's add simple sinks so we can make a demo. Let's start with the simplest:
struct NullSink { void commit(std::string const&) const {} };
Now, let's get more useful. A sink to commit log transactions to any ostream object or reference:
template <typename Impl, bool Flush = true>
struct StreamSink {
StreamSink(Impl stream_or_ref = {}) : _sor(std::move(stream_or_ref)) {}
StreamSink(StreamSink&& rhs) : StreamSink(std::move(rhs._sor)) {}
void commit(std::string const& msg) {
std::lock_guard<std::mutex> lk(_mx);
get() << msg << "\n";
if (Flush) get() << std::flush;
}
std::ostream& get() { return _sor; }
private:
mutable std::mutex _mx;
Impl _sor; // stream convertible to ostream&
};
And, because you were writing to several destinations in your example:
template <typename A, typename B> struct TeeSink { // dispatch to two sinks
A a; B b;
void commit(std::string const& msg) { a.commit(msg); b.commit(msg); }
};
Some Convenience Functions
Unless you use C++17, some factory functions will be welcome.
// factory functions (mostly not needed in c++17 with deduction guides)
template <typename A, typename B>
TeeSink<A, B> tee(A&& a, B&& b) { return { std::forward<A>(a), std::forward<B>(b) }; }
StreamSink<std::ofstream, false> log_to(std::ofstream&& file) { return {std::move(file)}; }
StreamSink<std::reference_wrapper<std::ostream>, true> log_to(std::ostream& os) { return {os}; }
Let's also add global instances of sinks for standard streams, so that you can use these to get the same synchronization everywhere:
auto& log_to_stderr() {
static StreamSink<std::reference_wrapper<std::ostream>, true> s_instance { log_to(std::cerr) };
return s_instance;
}
auto& log_to_stdout() {
static StreamSink<std::reference_wrapper<std::ostream>, true> s_instance { log_to(std::cout) };
return s_instance;
}
auto& null_sink() {
static NullSink const s_instance{};
return s_instance;
}
template <typename Sink>
LogTx<Sink> make_tx(Sink& sink) { return {sink}; }
Finally the pièce de resistance: makeTx to create a LogTx for a given sink:
template <typename Sink>
LogTx<Sink> make_tx(Sink& sink) { return {sink}; }
DEMO TIME
Now we can put it together:
#define LOG_TO(sink) (Logging::make_tx(sink) << __FILE__ << ":" << __LINE__ << "\t" << __func__ << "\t")
#ifdef NOLOGGING
#define LOG LOG_TO(Logging::null_sink())
#else
static auto _file_sink = Logging::log_to(std::ofstream("demo.log"));
static auto _both_sink = tee(_file_sink, Logging::log_to_stderr());
#define LOG LOG_TO(_both_sink)
#endif
This is pretty much what you wanted:
Live On Coliru
#include <thread>
void worker(std::string id) {
while (auto r = rand()%10) {
std::this_thread::sleep_for(std::chrono::milliseconds(r));
LOG << "Ping from " << id;
}
}
int main() {
LOG << "Hello";
{
std::thread a(worker, "A"), b(worker, "B");
a.join();
b.join();
}
LOG << "Bye";
}
Prints, to both stderr and demo.log:
main.cpp:104 main Hello
main.cpp:99 worker Ping from A
main.cpp:99 worker Ping from B
main.cpp:99 worker Ping from A
main.cpp:99 worker Ping from B
main.cpp:99 worker Ping from A
main.cpp:99 worker Ping from B
main.cpp:99 worker Ping from B
main.cpp:99 worker Ping from A
main.cpp:99 worker Ping from A
main.cpp:99 worker Ping from A
main.cpp:99 worker Ping from B
main.cpp:99 worker Ping from A
main.cpp:99 worker Ping from A
main.cpp:99 worker Ping from A
main.cpp:99 worker Ping from A
main.cpp:110 main Bye
C++11 Full Listing
Added a c++11-compatible version, of which I include the full listing as to protect against link rot:
[C++11 Live On Coliru][http://coliru.stacked-crooked.com/a/6360aad26b037df2)
#include <functional> // for std::reference_wrapper
#include <iostream>
#include <sstream>
#include <fstream>
#include <mutex>
namespace Logging {
// utility to safely implement movable log transactions
struct unique_flag {
bool value = true;
unique_flag() = default;
unique_flag(unique_flag&& rhs) : value(rhs.value) { rhs.value = false; }
operator bool() const { return value; }
};
struct SinkConcept { void commit(std::string const&); }; // documentation only
// movable log transaction (using arbitrary sink)
template <typename Sink> struct LogTx {
LogTx(Sink& s) : _sink(s) {}
LogTx(LogTx&&) = default;
unique_flag _armed;
std::ostringstream _oss;
Sink& _sink;
~LogTx() { if (_armed) _sink.commit(_oss.str()); }
template <typename T> LogTx& operator<<(T&& rhs)& { return (_oss << rhs), *this; }
template <typename T> LogTx operator<<(T&& rhs)&& { return (_oss << rhs), std::move(*this); }
};
// Some sink models
struct NullSink { void commit(std::string const&) const {} };
template <typename Impl, bool Flush = true>
struct StreamSink {
StreamSink(Impl stream_or_ref = {}) : _sor(std::move(stream_or_ref)) {}
StreamSink(StreamSink&& rhs) : StreamSink(std::move(rhs._sor)) {}
void commit(std::string const& msg) {
std::lock_guard<std::mutex> lk(_mx);
get() << std::move(msg);
if (Flush)
get() << std::endl;
else
get() << "\n";
}
std::ostream& get() { return _sor; }
private:
mutable std::mutex _mx;
Impl _sor; // stream convertible to ostream&
};
template <typename A, typename B> struct TeeSink { // dispatch to two sinks
A a; B b;
void commit(std::string const& msg) { a.commit(msg); b.commit(msg); }
};
// factory functions (mostly not needed in c++17 with deduction guides)
template <typename A, typename B>
TeeSink<A, B> tee(A&& a, B&& b) { return { std::forward<A>(a), std::forward<B>(b) }; }
StreamSink<std::ofstream, false> log_to(std::ofstream&& file) { return {std::move(file)}; }
StreamSink<std::reference_wrapper<std::ostream>, true> log_to(std::ostream& os) { return {os}; }
StreamSink<std::reference_wrapper<std::ostream>, true>& log_to_stderr() {
static StreamSink<std::reference_wrapper<std::ostream>, true> s_instance { log_to(std::cerr) };
return s_instance;
}
StreamSink<std::reference_wrapper<std::ostream>, true>& log_to_stdout() {
static StreamSink<std::reference_wrapper<std::ostream>, true> s_instance { log_to(std::cout) };
return s_instance;
}
NullSink const& null_sink() {
static NullSink const s_instance{};
return s_instance;
}
template <typename Sink>
LogTx<Sink> make_tx(Sink& sink) { return {sink}; }
}
#define LOG_TO(sink) (Logging::make_tx(sink) << __FILE__ << ":" << __LINE__ << "\t" << __func__ << "\t")
#ifdef NOLOGGING
#define LOG LOG_TO(Logging::null_sink())
#else
static auto _file_sink = Logging::log_to(std::ofstream("demo.log"));
static auto _both_sink = tee(_file_sink, Logging::log_to_stderr());
#define LOG LOG_TO(_both_sink)
#endif
#include <thread>
void worker(std::string id) {
while (auto r = rand()%10) {
std::this_thread::sleep_for(std::chrono::milliseconds(r));
LOG << "Ping from " << id;
}
}
int main() {
LOG << "Hello";
{
std::thread a(worker, "A"), b(worker, "B");
a.join();
b.join();
}
LOG << "Bye";
}

The first feeling is, that operator() and operator<< are unrelated. For that it feels better to use two mutex, one in PrintToFile and one in PrintToScreen.
But you also can use the same mutex to log both of your operator methods. As the first operator is a template function, we have not two but n functions. Each template instance is an additional one. So using a single mutex for all the functions did exactly what you want.
If your Logger is a class and the operators are members, you simply make your mutex a member variable which can be (un-)locked in each of your methods.

Use a std::mutex and lock on first use of operator() or operator<<. Then unlock if user string ends with \n. I assume you are sure that user finishes every log entry with linebreak.
class Logger {
std::mutex mux;
//...
public:
Logger& operator()(/*...*/) {
mux.lock();
// write to log
}
Logger& operator<<(const string& str) {
// write to log
if(str[str.size()-1] == '\n')
mux.unlock();
}
//...
};

Related

Template functions by index in C++

Suppose I have a class in C++11 like this:
class Something
{
...
private:
class1* a;
class2* b;
class3* c;
public:
class1* reada() { return a; }
class2* readb() { return b; }
class3* readc() { return c; }
void customFunctionForclass1();
void customFunctionForclass2();
void customFunctionForclass3();
}
}
I'd like to make the read functions templated so that if another programmer adds another member class, the corresponding read function will be template-magic created.
Something like this maybe?
class Something
{
...
private:
templateContainer = {class1*,class2*,class3*}
template<thing in templateContainer>
thing variableOfTypeThing;
public:
template<thing in templateContainer>
<thing> read() {return variableOfTypeThing<thing>;}
void customFunctionForclass1();
void customFunctionForclass2();
void customFunctionForclass3();
}
As you can tell from the example, I'm confused.
Basically, I have a class which acts as a container for guaranteed unique class variables (no class1 A; class1 B)
Some function groups for the class are almost identical some function groups are highly varied. It would be great for future people to only have to modify the different parts of the class and get the rest from the templates.
I thought maybe there would be a way by splitting this class up into lots of classes and stuffing them into an array of void pointers, but that seems unwise.
Suggestions?
I'd like to make the read functions templated so that if another programmer adds another member class, the corresponding read function will be template-magic created.
You could encapsulate the user defined classes in a thin wrapper class with a read() function that returns the contained instance. Adding a user defined class to Something would then be done by inheriting wrapper<user_defined_class>.
Basically, I have a class which acts as a container for guaranteed unique class variables
Inheriting this wrapper prevents you from including the same class twice so it could possibly be a way forward:
#include <iostream>
// the "thing" wrapper
template<typename T>
struct thing {
// forward construction arguments to the contained variable
template<class... Args>
thing(Args&&... args) : variable(std::forward<Args>(args)...) {}
// basic interface, const and non-const. I called it get() instead of read()
T const& get() const { return variable; }
T& get() { return variable; }
private:
T variable;
};
// a troublesome user defined class that is not default constructibe :-(
struct user_defined {
user_defined() = delete; // silly example really, but it's just to demonstrate
user_defined(const std::string& v) : str(v) {}
user_defined& operator=(const std::string& v) {
str = v;
return *this;
}
std::string const& say() const { return str; }
private:
std::string str;
};
std::ostream& operator<<(std::ostream& os, const user_defined& ud) {
return os << ud.say();
}
// ... and the "Something" class that inherits the wrapped types.
class Something : thing<int>,
thing<double>,
thing<user_defined>
{
public:
// add initial values for types that are not default constructible
Something(const std::string& val) : thing<user_defined>(val) {}
Something() : Something("") {} // default ctor
// access via derived class, const and non-const
template<typename T>
T const& get() const {
return thing<T>::get(); // get() from the correct base
}
template<typename T>
T& get() {
return thing<T>::get(); // get() from the correct base
}
};
void print(const Something& s) {
// using the const interface
std::cout << s.get<int>() << "\n";
std::cout << s.get<double>() << "\n";
std::cout << s.get<user_defined>() << "\n";
}
int main() {
Something foo;
// using the non-const interface to set
foo.get<int>() = 10;
foo.get<double>() = 3.14159;
foo.get<user_defined>() = "Hello world";
print(foo);
}
Edit: It doesn't fulfill the index part of your question though. You access it using the type you'd like to get() as a tag. You basically build a very rudimentary tuple I guess.
Code based on #Ted Lyngmo's answer:
#include <iostream>
#include <string>
template<typename T>
struct thing {
// forward construction arguments to the contained variable
template<class... Args>
thing(Args&&... args) : variable(std::forward<Args>(args)...) {}
// basic interface, const and non-const. I called it get() instead of read()
T const& get() const { return variable; }
T& get() { return variable; }
protected:
T variable;
};
template<typename ...Ts>
struct things : thing<Ts>... {
template<class... SubTs>
things(thing<SubTs>&&... ts) : thing<SubTs>(std::move(ts))... {}
// access via derived class, const and non-const
template<typename T>
T const& get() const {
return thing<T>::get(); // get() from the correct base
}
template<typename T>
T& get() {
return thing<T>::get(); // get() from the correct base
}
};
// a troublesome user defined class that is not default constructibe :-(
struct user_defined {
user_defined() = delete; // silly example really, but it's just to demonstrate
user_defined(const std::string& v) : str(v) {}
user_defined& operator=(const std::string& v) {
str = v;
return *this;
}
std::string const& say() const { return str; }
private:
std::string str;
};
struct non_default {
non_default() = delete;
non_default(int) {}
};
std::ostream& operator<<(std::ostream& os, const user_defined& ud) {
return os << ud.say();
}
// ... and the "Something" class that inherits the wrapped types.
class Something : public things<int, double, user_defined, non_default>
{
public:
// add initial values for types that are not default constructible
Something(const std::string& val) : things(thing<user_defined>(val), thing<non_default>(0)) {}
Something() : Something("") {} // default ctor
};
void print(const Something& s) {
// using the const interface
std::cout << s.get<int>() << "\n";
std::cout << s.get<double>() << "\n";
std::cout << s.get<user_defined>() << "\n";
}
int main() {
Something foo;
// using the non-const interface to set
foo.get<int>() = 10;
foo.get<double>() = 3.14159;
foo.get<user_defined>() = "Hello world";
print(foo);
}

Automatically wrapping values for the duration of a statement

Is it possible to automatically wrap a value in a temporary whose lifetime extends across the entire statement?
Originally I hoped a solution or alternative to my problem would present itself while writing the details for the question, unfortunately that didn't happen, so...
I have an abstract base class Logger that provides a streaming-like interface for generating log statements. Given an instance logger of this class, I want the following to be possible:
logger << "Option " << variable << " is " << 42;
Unlike regular streams, which simply generate a string from all the components (4 components in the example above), I want to generate an instance of a class Statement that manages a linked list of all the statement's components. The entire statement is then passed via pure virtual method to a class derived from Logger, which can iterate over all the components of the statement and do whatever with them, including obtaining information about their type, retrieving their value, or converting them to a string.
The tricky bit: I want to do the above without dynamic memory allocations. This means that every component of the statement must be wrapped by a temporary type that links the components into a traversable list, within the scope of the statement!
I posted a working example on ideone, with one problem: every component needs to be wrapped by a function call in order to generate an instance of the temporary type. The log statement therefore ends up looking like this:
logger << wrap("Option ") << wrap(variable) << wrap(" is ") << wrap(42);
All my attempts to get rid of the wrap function (e.g., using an implicit converting constructor for the component), have failed thus far, therefore this question.
How can the components of the log statement automatically be wrapped in their component type (e.g., using a converting constructor for the component), without the need for an explicit call to a wrapping function?
Alternatively, I would appreciate suggestions for other ways that achieve the same effect, i.e., allowing iteration over the components of the log statement in a class derived from logger, without dynamic memory allocations.
Reference: Full code on ideone:
#include <iostream>
#include <sstream>
struct Statement;
struct Logger;
struct ComponentBase;
//------------------------------------------------------------------------------
struct ComponentBase {
mutable ComponentBase *next;
ComponentBase() : next(nullptr) { }
virtual std::string toString() = 0;
};
template <typename T>
struct Component : ComponentBase {
T value;
Component(T value) : value(value) { }
~Component() { }
virtual std::string toString() {
std::stringstream ss;
ss << value;
return ss.str();
}
};
struct ComponentIterator {
ComponentBase *ptr;
ComponentIterator(ComponentBase *ptr) : ptr(ptr) { }
ComponentBase &operator*() { return *ptr; }
void operator++() { ptr = ptr->next; }
bool operator!=(ComponentIterator &other) { return (ptr != other.ptr); }
};
//------------------------------------------------------------------------------
struct Statement {
Logger *logger;
ComponentBase *front;
ComponentBase *back;
ComponentIterator begin() { return front; }
ComponentIterator end() { return nullptr; }
template <typename T>
Statement(Logger &logger, Component<T> &component)
: logger(&logger), front(&component), back(&component) { }
~Statement();
template <typename T>
Statement &operator<<(Component<T> &&component) {
back->next = &component;
back = &component;
return *this;
}
};
//------------------------------------------------------------------------------
struct Logger {
template <typename T>
Statement operator<<(Component<T> &&component) {
return {*this, component};
}
virtual void log(Statement &statement) = 0;
};
Statement::~Statement() {
logger->log(*this);
}
//------------------------------------------------------------------------------
template <typename T>
Component<T const &> wrap(T const &value) {
return value;
}
template <size_t N>
Component<char const *> wrap(char const (&value)[N]) {
return value;
}
//------------------------------------------------------------------------------
struct MyLogger : public Logger {
virtual void log(Statement &statement) override {
for(auto &&component : statement) {
std::cout << component.toString();
}
std::cout << std::endl;
}
};
int main() {
std::string variable = "string";
MyLogger logger;
logger << wrap("Option ") << wrap(variable) << wrap(" is ") << wrap(42);
}
I have some crazy but working solution.
Having component implemented like this you will get rid of templates all over your code:
struct Component
{
mutable Component *next;
typedef std::function<std::string()> ToStringFunction;
ToStringFunction toString; // <-- 1
template<typename T>
Component(const T& value)
: next(nullptr),
toString(nullptr)
{
toString = [&value](){
std::stringstream ss;
ss << value;
return ss.str();
};
}
};
Where (1) is the unction that knows what to do. This member std::function is a space for optimization.
And the rest of the code should look like:
struct ComponentIterator {
Component *ptr;
ComponentIterator(Component *ptr) : ptr(ptr) { }
Component &operator*() { return *ptr; }
void operator++() { ptr = ptr->next; }
bool operator!=(ComponentIterator &other) { return (ptr != other.ptr); }
};
//------------------------------------------------------------------------------
struct Statement {
Logger *logger;
Component *front;
Component *back;
ComponentIterator begin() { return front; }
ComponentIterator end() { return nullptr; }
Statement(Logger &logger, Component &component)
: logger(&logger), front(&component), back(&component) { }
~Statement();
Statement &operator<<(Component &&component) {
back->next = &component;
back = &component;
return *this;
}
};
//------------------------------------------------------------------------------
struct Logger {
Statement operator<<(Component &&component) {
return{ *this, component };
}
virtual void log(Statement &statement) = 0;
};
Statement::~Statement() {
logger->log(*this);
}
//------------------------------------------------------------------------------
struct MyLogger : public Logger {
virtual void log(Statement &statement) override {
for (auto &&component : statement) {
std::cout << component.toString();
}
std::cout << std::endl;
}
};
int main() {
std::string variable = "string";
MyLogger logger;
//logger << wrap("Option ") << wrap(variable) << wrap(" is ") << wrap(42);
logger << 42;
logger << variable << " is " << 42;
logger << "Option " << variable << " is " << 42;
}
this will print:
42
string is 42
Option string is 42
UPD
as dyp advised here is alternative implementation of the Component structure without lambda:
struct Component
{
mutable Component *next;
void* value;
std::string toString(){
return _toString(this);
}
template<typename T>
Component(const T& inValue)
: next(nullptr),
value((void*)&inValue),
_toString(toStringHelper<T>)
{}
private:
typedef std::string(*ToStringFunction)(Component*);
ToStringFunction _toString;
template<typename T>
static std::string toStringHelper(Component* component)
{
const T& value = *(T*)component->value;
std::stringstream ss;
ss << value;
return ss.str();
}
};
I propose a solution tuple based:
template <class... Ts> class streamTuple;
struct Logger {
template <typename T>
streamTuple<T> operator<<(const T& t);
template <typename Tuple, std::size_t ... Is>
void dispatch(const Tuple& tup, std::index_sequence<Is...>)
{
int dummy[] = {0, (void(std::cout << std::get<Is>(tup) << " "), 0)...};
static_cast<void>(dummy); // Avoid unused variable warning
}
// Logger can take generic functor to have specific dispatch
// Or you may reuse your virtual method taking ComponentBase.
};
template <class... Ts> class streamTuple
{
public:
streamTuple(Logger* logger, const std::tuple<Ts...>& tup) :
logger(logger), tup(tup) {}
streamTuple(streamTuple&& rhs) : logger(rhs.logger), tup(std::move(rhs.tup))
{
rhs.logger = nullptr;
}
~streamTuple()
{
if (logger) {
logger->dispatch(tup, std::index_sequence_for<Ts...>());
}
}
template <typename T>
streamTuple<Ts..., const T&> operator << (const T& t) &&
{
auto* moveddLogger = logger;
logger = nullptr;
return {moveddLogger, std::tuple_cat(tup, std::tie(t))};
}
private:
Logger* logger;
std::tuple<Ts...> tup;
};
template <typename T>
streamTuple<T> Logger::operator<<(const T& t) {
return {this, t};
}
Demo
And usage:
int main() {
Logger log;
std::string variable = "string";
log << variable << 42 << "hello\n";
}

Thread safe access of std::ofstream member using std::mutex member and operator<< insertion overload?

I am having the worst time trying to make a class that has a std::ofstream and a std::mutex that is locked and unlocked to control access to the ofstream.
Basically I want a class thread_safe_ofstreamwith a << operator so I can use it like:
thread_safe_ofstream ofs;
ofs << "debug info from different threads" << std::endl;
So I know I need an operator<< overload. While there is plenty of info for this operator<< for classes on the right-hand-side of <<, I cannot find any documentation for how to implement your own ostream-like << input.
I know the following code cannot work because of whatever input/output requirements << has, but this is the spirit of the class I need.
Class thread_safe_ofstream
{
std::mutex mu;
std::ofstream stream;
template<typename T>
operator<<(T& thing)
{
mu.lock();
stream << thing;
mu.unlock();
}
};
This way a single thread_safe_ofstream can be <<'d to from multiple threads without problems (my hope is).
Something like that?
template<typename T>
thread_safe_ofstream& operator<<(const T& thing)
{
std::lock_guard<std::mutex> guard(mu);
stream << thing;
return *this;
}
However, it is usually better to implement operator << as a free function, rather than class member.
You can have such implementation for instance:
class thread_safe_ofstream
{
std::mutex mu;
std::ofstream stream;
template<typename T>
void put(const T& thing) {
std::lock_guard<std::mutex> lock(mu);
stream << thing;
}
friend template<typename T>
thread_safe_ofstream& operator<<(thread_safe_ofstream& tsof, const T& value) {
tsof.put(value);
return tsof;
}
};
Here is a complete class that will print mostly-ungarbled text from commands like ts_ofs << "print this message" << std::endl except between subsequent <<s another thread may start printing. I suspect there could a fix for that but I have no idea how to do it. Inspiration is from this post.
struct ts_ofstream
{
std::ofstream ostream;
std::mutex mu;
//This is only for testing, you can initialize ostream however/wherever you like.
void init(bool test = false)
{
ostream = std::ofstream("C:/Users/Joey/Desktop/THREAD_DEBUG.txt", ios::out);
if (test)
{
ostream << "Testing stream ";
ostream << std::endl;
ostream << "Testing complete" << std::endl;
}
}
template <typename T>
friend ts_ofstream& operator<<(ts_ofstream& s, const T& x);
// function that takes a custom stream, and returns it
typedef ts_ofstream& (*MyStreamManipulator)(ts_ofstream&);
// take in a function with the custom signature
ts_ofstream& operator<<(MyStreamManipulator manip)
{
// call the function, and return it's value
return manip(*this);
}
// define the custom endl for this stream.
// note how it matches the `MyStreamManipulator`
// function signature
static ts_ofstream& endl(ts_ofstream& stream)
{
// print a new line
stream.ostream << std::endl;
return stream;
}
// this is the type of std::ofstream
typedef std::basic_ostream<char, std::char_traits<char> > CoutType;
// this is the function signature of std::endl
typedef CoutType& (*StandardEndLine)(CoutType&);
// define an operator<< to take in std::endl
ts_ofstream& operator<<(StandardEndLine manip)
{
// call the function, but we cannot return it's value
manip(this->ostream);
return *this;
}
};
template<typename T>
ts_ofstream & operator<<(ts_ofstream & s, const T & x)
{
std::lock_guard<std::mutex> lock(s.mu);
s.ostream << x;
return s;
}

How to use smart pointer for auto clean-up?

I'm making a simple logging class with a pointer to either a std::ofstream or std::cerr.
Is there any simple way to use a smart pointer for auto clean-up regardless of which stream is used?
The code must compile on clang++, g++, and VS2013.
Code
#include <iostream>
#include <fstream>
#include <string>
class Logger {
private:
std::ostream * output_stream{ nullptr };
bool using_file{ false };
public:
Logger()
{
output_stream = &std::cerr;
using_file = false;
}
Logger(std::string file)
{
output_stream = new std::ofstream(file);
using_file = true;
}
~Logger()
{
if (using_file)
{
delete output_stream;
}
}
template<typename T>
void log(T info)
{
*output_stream << info << std::endl;
}
};
class tmp {
int i{ 4 };
friend std::ostream & operator<<(std::ostream &os, const tmp& p);
};
std::ostream &operator<<(std::ostream &os, const tmp& p)
{
return os << p.i;
}
int main()
{
tmp t;
Logger logger;
logger.log(t);
system("pause");
return 0;
}
Attempts
std::unique_ptr
I can use std::unique_ptr for the file like so:
std::unique_ptr<std::ostream> p;
p = std::make_unique<std::ofstream>("file.txt");
*p << "hi there" << std::endl;
Trying this with std::cout warns me about a deleted function (assuming that's the constructor.
std::unique_ptr<std::ostream> p2;
p2 = std::make_unique<std::ostream>(std::cout);
*p2 << "hey" << std::endl;
std::shared_ptr
Because std::unique_ptr is only for owning things, and std::cout shouldn't be owned, I thought I'd try std::shared_ptr
std::shared_ptr<std::ostream> p;
p = std::make_shared<std::ostream>(std::cout);
*p << "hola" << std::endl;
It gives me the same deleted constructor error. p = &std::cout complains about a type mismatch, so it's also not working.
You can use a shared_ptr with a deleter that does not delete anything in the case of cerr and just a normally constructed shared_ptr in the case of ofstream
class Logger {
private:
std::shared_ptr<std::ostream> output_stream{ nullptr };
public:
Logger() :
output_stream(&std::cerr, [](std::ostream*){})
{ }
Logger(std::string file) :
output_stream(std::make_shared<std::ofstream>(file))
{ }
// default destructor is OK
template<typename T>
void log(T info)
{
*output_stream << info << std::endl;
}
};
I would just have two pointers, one smart and one raw.
The raw pointer is always used to refer to the stream. The smart pointer is just used for clean-up if needed.
class Logger {
private:
std::unique_ptr<std::ofstream> file_stream;
std:ostream *stream;
public:
Logger() : stream(&std::cerr) {}
Logger(const std::string& file)
: file_stream(std::make_unique<std::ofstream>(file)), stream(file_stream.get()){}
template<typename T>
void log(T info) {
*stream << info << std::endl;
}
};
I tend to try to avoid cases where I want an object to "own" such things. In the times I did not have much choice, I ended up settling with a "shouldDelete" flag or a callback.
class Logger {
public:
Logger(std::ofstream *outputStream, bool deleteOutputStream)
: outputStream(outputStream), deleteOutputStream(deleteOutputStream)
{ }
~Logger()
{
if (deleteOutputStream) delete outputStream;
}
};
Logger logger(&std::cout, false);
class Logger {
public:
typedef std::function<void(std::ostream*)> Deleter;
typedef std::unique_ptr<std::ostream, Deleter> OStreamPointer;
Logger(OStreamPointer &&outputStream)
: outputStream(std::move(outputStream))
{ }
~Logger() { }
private:
OStreamPointer outputStream;
};
Logger logger(Logger::OStreamPointer(
&std::cout,
[](std::ostream*) {})); //no-op callback
You could do this by releasing the smart pointer in the destructor (and elsewhere) in the cases where it shouldn't be deleted, but that's not worth the hassle IMO.
Instead, I'd recommend simply using two pointers: one for streams that need to be managed and one for those that don't:
class Logger {
private:
std::ostream * unmanaged_stream{ nullptr };
std::unique_ptr<std::ostream> managed_stream{ nullptr };
bool using_file{ false };
std::ostream& output_stream()
{
return using_file ? *managed_stream : *unmanaged_stream;
}
public:
Logger()
: unmanaged_stream{&std::cerr},
using_file{false}
{
}
Logger(const std::string& file)
: managed_stream{std::make_unique<std::ofstream>(file)},
using_file{true}
{
}
template<typename T>
void log(T info)
{
output_stream() << info << std::endl;
}
};
If saving space is a priority you could put them in a union, but then you'd have to explicitly call the destructor and placement new to define the active member, which again is more hassle and probably not worth it.

thread safe streams and stream manipulators

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.
Your problem is that logger isn't a stream, so the usual stream operators will not work, just the single one you have defined.
You can get endl to work by defining it yourself:
inline logger& endl(logger& log)
{
// do something to *out
return log;
}
Now log << "Hello!" << endl; will work.
To be able to chain several << operations together like the streams do, you will have to define all the operators for the logger (just like the streams do).
I think you are introducing synchronization at too low a level. To understand why, assume thread 1 executes:
log << "This is " << "my " << "log message" << endl;
while thread 2 executes:
log << "Hello, " << "World!" << endl;
In such a case, the log file (or console output) may contain interleaved messages, for example:
This is Hello, my World!
log message
To avoid this problem, your application will have to construct
an entire message as a single string, and only then pass that string to a logger object. For example:
ostringstream msg;
msg << "This is " << "my " << "log message" << endl;
log << msg.str();
If you take this approach, then your logger class does not need to overload operator<< for endl and multiple types.
I tested your program with some simplifications as follows, and it compiles and runs fine, which means that the problem is probably elsewhere:
#include <iostream>
class logger {
public:
// logger(LOGGER::output_type type);
logger(std::ostream& os): out(&os) {}
~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;
};
int main()
{
logger log(std::cout);
log << std::string("hello ");
log << "world\n";
}
After digging into iostreams and with hints from Bo Persson, I think i found a better solutions since I dont need to write a function each for each ios manipulator. So here it is
logger& operator<<(std::ostream& (*pf)(std::ostream&)) {
(*out)<<pf;
return *this;
}
For an explanation search for iostreams and applicators.
Here is the complete boost::thread safe implementation (requires some refactoring and optimization probably) using some hints from Ciaran-Mchale
/*
* File: logger.h
* Author: Kiran Mohan
*
*/
#ifndef LOGGER_H
#define LOGGER_H
#include <boost/thread.hpp>
#include <iostream>
namespace LOG {
enum output_type {
STDOUT,
STDERR
};
/**
* a thread safe logger to print to stdout or stderr
*/
class logger {
public:
logger(LOG::output_type type);
logger(const logger& orig);
virtual ~logger();
template <typename T>
logger & operator <<(T data) {
/* Takes any data type and stores in a stringstream
*/
(*oss) << data;
return *this;
}
logger & operator<<(std::ostream& (*pf)(std::ostream&)) {
// for stream manipulators
(*oss) << pf;
return *this;
}
logger & operator<<(logger & (*pf)(logger &)) {
//applicator - mainly calling the print function;
return pf(*this);
}
friend logger & flush(logger & l);
logger & print() {
boost::mutex::scoped_lock io_mutex_lock(io_mutex);
(*out) << oss->str() << std::flush;
delete oss;
oss = new std::ostringstream;
return *this;
}
private:
static boost::mutex io_mutex;
std::ostream * out;
std::ostringstream * oss;
};
logger & flush(logger & l);
};
#endif /* LOGGER_H */
/*
* File: logger.cc
* Author: aryan
*
*/
#include <boost/thread/pthread/mutex.hpp>
#include <iostream>
#include "logger.h"
using namespace LOG;
boost::mutex logger::io_mutex;
logger::logger(LOG::output_type type) {
if (type == LOG::STDOUT) {
out = &std::cout;
} else {
out = &std::cerr;
}
oss = new std::ostringstream;
}
logger::logger(const logger& orig) {
out = orig.out;
}
logger::~logger() {
delete oss;
}
logger & LOG::flush(logger & l) {
l.print();
boost::this_thread::yield();
return l;
}
use it like this
LOG::logger logOut (LOG::STDOUT);
logOut<<"Hello World\n"<<LOG::flush;