I'm trying to write a really simple thread-safe logger. Ideally, I wanted it to work just like std::cout, wherein you could just overload the << operator and have everything magically show up in the log. I'm on a Windows machine, so here's the approach I tried:
// Threadsafe logger
class Logger
{
public:
Logger()
{
InitializeCriticalSection(&s);
}
~Logger()
{
DeleteCriticalSection(&s);
}
void Log(std::ostream const& os)
{
EnterCriticalSection(&s);
//std::cout << static_cast<std::stringstream const&>(os).str();
std::cout << os.rdbuf();
LeaveCriticalSection(&s);
}
private:
CRITICAL_SECTION s;
};
Notice that I've tried two approaches to the Log() function. The reason I accept an ostream is because that's what a stringstream seems to produce after the << operator is called. Both variants of the Log() function fail in the same way when I run this code:
#include <iostream>
#include <sstream>
#include <Windows.h>
int main(int argc, char* argv[])
{
Logger logger;
//logger.Log(std::stringstream("Test"));
logger.Log(std::stringstream("Another ") << "test");
std::cin.get();
}
Outputting the first line ("Test") works correctly and displays properly using both variants of the Log function. The second line outputs a mangled output:
testher
which is obviously test written over Another. What am I missing about the way these streams work? I tried making a flush call hoping that would fix things, but it did nothing.
How can I get this attempt at a thread-safe logger working correctly with the streams?
Using variadic templates:
void Log_impl(std::ostream &os) {} // recursion base case
template<typename T,typename... Us>
void Log_impl(std::ostream &os,T &&t,Us &&... us) {
os << std::forward<T>(t);
Log_impl(os,std::forward<Us>(us)...);
}
template<typename... Ts> void Log(Ts &&... ts) {
std::stringstream ss;
Log_impl(ss,std::forward<Ts>(ts)...);
fprintf(stdout,"%s\n",ss.str().c_str()); // thread safe output
}
usage:
Log("Another"," test ",100);
I haven't actually tested this code...
At least in my opinion, this approach to the problem is at least somewhat clumsy to use, since it requires you to create an auxiliary ostream object of some sort, stream data into it, and then pass that to your log. That doesn't seem to fit very closely with what you've said you'd really prefer.
I'm also a bit less than excited about how you've done your thread-locking code. Just for example, if you get an exception during your std::cout << os.rdbuf();, you can exit the scope without leaving the critical section.
I think I'd start with a thin wrapper around a critical section, add an RAII-style class to lock the critical section (and automatically unlock it when it goes out of scope), then use those in implementing the Log class. Further, I'd cheat and have the Log class use a template member function to accept almost any type of output in one fell swoop:
Edit: After some more thought, I've decided to embrace the notion that every problem can be solved with another level of indirection. To do that, I've added an intermediate transaction that encapsulates chaining the output of a number of items into a stringstream, then writing out that result as a thread-safe transaction.
#include <windows.h>
#include <iostream>
#include <sstream>
class crit_sect {
CRITICAL_SECTION cs;
void lock() { EnterCriticalSection(&cs); }
void unlock() { LeaveCriticalSection(&cs); }
friend class lock;
crit_sect(crit_sect const &); /* = delete; */
crit_sect &operator=(crit_sect const &other); /* = delete; */
public:
crit_sect() { InitializeCriticalSection(&cs); }
~crit_sect() { DeleteCriticalSection(&cs); }
};
class lock {
crit_sect &cs;
public:
lock(crit_sect &c) : cs(c) { cs.lock(); }
~lock() { cs.unlock(); }
};
class transaction {
std::ostringstream buffer;
public:
transaction(std::string const &s="") : buffer(s, std::ios::out | std::ios::ate) {}
template <class T>
transaction &operator<<(T const &t) {
buffer << t;
return *this;
}
friend std::ostream &operator<<(std::ostream &os, transaction const &t) {
return os << t.buffer.str();
}
};
class Log {
std::ostream &out;
crit_sect mutex;
public:
Log(std::ostream &sink) : out(sink) { }
template <class T>
void operator<<(T const &t) {
lock l(mutex);
out << t;
}
};
int main() {
Log l(std::cout);
l << "This is a string\n";
l << (transaction("Another ") << "Test");
return 0;
}
Since the log type doesn't support chaining, any attempt at chaining the output without using a transaction will fail (won't compile). Compared to the original, usage is still a bit cleaner though -- the extra parameters needed for the ostringstream ctor are hidden, and the name transaction clarifies what is being done, or rather, accomplished.
The problem isn't with the logger, rather it's with your use of stringstream.
When std::stringstream is initialized, the stream's position indicator is positioned at the beginning of the stream.
Now when you start writing to the string using '<<', you start writing at the position indicator, replacing whatever was there before.
To work around this, you can initialize the stringstream with
std::stringstream("Another ", stringstream::in | stringstream::out | std::stringstream::ate)
(as per http://www.cplusplus.com/reference/iostream/stringstream/stringstream/ )
<< doesn't send the null byte at the end of "test" into the temporary stringstream("Another ") you created, which is why you see "testher".
Related
The relevant code is :
std::fstream fout("Logs.txt");
class Logs;
typedef std::ostream& (*ostream_manipulator2)(std::ostream&);
class LogsOutput
{
public:
LogsOutput() {}
~LogsOutput() {}
Logs * pLogs;
friend LogsOutput& operator<<(LogsOutput &logsClass, std::string &strArg);
friend LogsOutput& operator<<(LogsOutput &logsClass, const char *strArg);
friend LogsOutput& operator<<(LogsOutput &logsClass, ostream_manipulator2 pf);
friend LogsOutput& operator<<(LogsOutput &logsClass, uint64_t number);
};
LogsOutput *pLogsOutput;
template <typename T>
T& LOUToutput()
{
if (pLogsOutput)
{
return (*pLogsOutput);
}
else
return fout;
}
I would like to call this function as such :
LOUToutput () << "Print this line " << std::endl;
Sometimes however the LogsOutput class isn't created, therefore dereferencing its pointer would crash in which case i would rather output to file instead.
I understand that the compiler cannot tell at compile time whether the LogsOutput class will be instantiated or not and thus cannot deduce the type of the template, but I don't see any other way I could make it work.
So my question is how can my function return a different type based on a run time condition ?
The complex solution to this is to use inheritance. If you were to inherit from std::ostream, you could return a common base class (Here is a discussion if you are interested: How to inherit from std::ostream?)
The simpler solution, imo., is to return a proxy class that redirects output as necessary.
struct LogProxy {
LogsOutput *pLog;
// ...
LogProxy &operator<<(std::string &o) {
if(pLogsOutput) {
*pLog << o;
} else {
// Assuming this is available as a global.. You probably don't want to do that
fout << o;
}
return *this;
}
// ....
};
LogProxy LOUToutput() {
return LogProxy { pLogsOutput; };
}
A few other general comments:
If you want to use templates you would need to make this a compile time condition. You could use something like std::enable_if<> to provide multiple template overloads of LOUToutput() which choose at compile time where to log to.
I'm guessing it was just for the purposes of posting to SO, but your code has multiple globals declared in a header file. You'll need to fix that.
There are no const declarations on your code. A lot of those operators look like they should at least be declared const on their output (string,.etc.) parameters.
EDIT: Here is a working (compiles correctly) sample of this idea:
#include <iostream>
struct PRXY {
bool cond;
const PRXY &operator<<(const std::string &t) const {
if(cond) {
std::cout << t;
} else {
std::cerr << t;
}
return *this;
}
};
PRXY pr(bool cond) {
return PRXY { cond };
}
void test() {
pr(false) << "Hello";
}
I have a struct like
struct log {
boost::mutex mut;
std::stringstream a_stringstream;
//...
};
and in my code I have a vector of those and frequently do
{
boost::lock_guard <boost::mutex> lock(logs[AN_ENUM].mut);
logs[AN_ENUM].a_stringstream << "something" << a_double << a_string << etc;
}
It seems verbose to have the lock guard and brackets every time I want to log something. At first I thought maybe I could overload the << operator for my struct, but I read about it and I don't think that can work. Is there a good way that I can condense this into a method call?
You can create a variadic template function (say log_it) that takes AN_ENUM plus a variable number of items to log, locks the mutex once, and then streams everything to a_stringstream. For example:
#include <mutex>
#include <sstream>
#include <vector>
class save_stream
{
std::ostream& os_;
char fill_;
std::ios::fmtflags flags_;
std::streamsize precision_;
public:
~save_stream()
{
os_.fill(fill_);
os_.flags(flags_);
os_.precision(precision_);
}
save_stream(const save_stream&) = delete;
save_stream& operator=(const save_stream&) = delete;
explicit save_stream(std::ostream& os)
: os_(os)
, fill_(os.fill())
, flags_(os.flags())
, precision_(os.precision())
{}
};
struct log
{
std::mutex mut;
std::stringstream a_stringstream;
};
std::vector<log> logs(10);
enum : std::size_t {AN_ENUM};
void
log_one(std::size_t)
{
}
template <class Arg0, class ...Args>
void
log_one(std::size_t log, Arg0 const& arg0, Args const& ...args)
{
logs[log].a_stringstream << arg0;
log_one(log, args...);
}
template <class ...Args>
void
log_it(std::size_t log, Args const& ...args)
{
std::lock_guard<std::mutex> lock(logs[log].mut);
save_stream s{logs[log].a_stringstream};
logs[log].a_stringstream << "log " << log << " says : ";
log_one(log, args...);
logs[log].a_stringstream << '\n';
}
This isn't a huge amount of code. log_it takes an integral constant, uses that to index into logs to lock the mutex, spits out the prefix string, and then calls log_one with the constant log index and the variable number of arguments to log out.
log_one then simply logs the first argument, and then recursively calls log_one on the rest of the pack.
It can be used like this:
log_it(AN_ENUM, std::fixed, std::setprecision(3), "i = ", 4.5);
log_it(AN_ENUM, "j = ", 4.5);
which results in logs[0].a_stringstream holding:
log 0 says : i = 4.500
log 0 says : j = 4.5
I'm sure the syntax can be finessed to something even prettier, but this gets the basic idea across: Pass a variable number of args, lock at the top of the call stack, and then process each arg one by one.
"Log levels" could be just another argument to log_it.
I can't think of any reason why this template overload<< member won't work:
template<typename param>
auto operator<<(param &&Param)
{
boost::lock_guard <boost::mutex> lock(mut);
a_stringstream << std::forward<param>(Param);
return *this;
}
I have no idea what you read that might suggest that this kind of an approach won't work, but whatever you read, it's wrong. My example might need a few tweaks, here and there, depending on your actual class, but theoretically it should be eminently doable.
Is there a way to create an ostream instance which basically doesn't do anything ?
For example :
std::ostream dummyStream(...);
dummyStream << "Nothing will be printed";
I could just create an ostringstream, but data will be buffered (and I really don't want to make anything with them, so it adds a useless overhead).
Any idea ?
[edit] Found this related question which suits my needs. However, I think it could be useful to have a answer saying how to create a valid (no badbit) output stream with standard c++.
You need a custom streambuf.
class NullBuffer : public std::streambuf
{
public:
int overflow(int c) { return c; }
};
You can then use this buffer in any ostream class
NullBuffer null_buffer;
std::ostream null_stream(&null_buffer);
null_stream << "Nothing will be printed";
streambuf::overflow is the function called when the buffer has to output data to the actual destination of the stream. The NullBuffer class above does nothing when overflow is called so any stream using it will not produce any output.
If this is to disable logging output, your dummyStream would still cause arguments to be evaluated. If you want to minimize impact when logging is disabled, you can rely on a conditional, such as:
#define debugStream \
if (debug_disabled) {} \
else std::cerr
So if you have code like:
debugStream << "debugging output: " << foo() << std::endl;
No arguments will be evaluated if debug_disabled is true.
The basic method voor new stream classes is:
Derive a class from std::streambuf;
Override the virtual functions in that class. This is where the real work is done. In your case, empty implementations should be good enough.
Derive a class from std::ostream with one member, your streambuf class.
The constructor of your streamclass should forward the pointer to that member to the base constructor of std::ostream.
I'm afraid you won't get rid of the formatting step, though.
Hopefully this gives you some pointers; I don't have the time to expand this into a full answer, sorry.
Update: See john's answer for details.
For runtime-controllable redirection of log messages, a self-contained solution combining the ideas of john and Sjoerd:
class DebugStream {
private:
class NullStream : public std::ostream {
private:
class NullBuffer : public std::streambuf {
public:
int overflow(int c) override { return c; }
} buffer_;
public:
NullStream() : std::ostream(&buffer_) {}
} null_;
std::ostream &output_;
bool enabled_;
public:
DebugStream(std::ostream &output = std::cout) : output_(output), enabled_(false) {}
void enable(const bool enable) { enabled_ = enable; }
template <typename T> std::ostream& operator<<(const T &arg) {
if (enabled_) return output_ << arg;
else return null_ << arg;
}
};
extern DebugStream debug_stream;
#define TRACE_ENABLE(x) debug_stream.enable(x)
#define TRACELN(x) debug_stream << x << std::endl
#define TRACE(x) debug_stream << x
Then you can do stuff like:
TRACELN("The value of x is " << x " and the value of y is " << y);
It would also be easy to just remove the trace statements from a release version completely with #define the trace macros to empty statements.
You still need to define debug_stream somewhere global, though.
If you are concerned about the overhead of your debugger then you can write a very simple code to void out your debug messages on compilation. This is what I use for my c++ programs.
#include <iostream>
#define DEBUGGING // Define this in your config.h or not.
#ifdef DEBUGGING
/*
* replace std::cout with your stream , you don't need to
* worry about the context since macros are simply search
* and replace on compilation.
*/
#define LOG_START std::cout <<
#define LOG_REDIR <<
#define LOG_END << std::endl;
#else
#define LOG_START if(0){(void)
#define LOG_REDIR ;(void)
#define LOG_END ;}
#endif // DEBUGGING
int main(){
LOG_START "This is a log message " LOG_REDIR "Still a log message." LOG_END;
return 0;
}
Now when making your project , check if the user wants to disable the logging , if so , just undefine the DEBUGGING macro or whatever macro you choose to check for.
Now your code will be optimized by the compiler , Because when anything is voided , it will not be included in the resulting binary(most of the time) , making the binary production ready.
I needed a null stream that was of type ostream so I did something like this:
struct NullStream: public stringstream {
NullStream(): stringstream() {}
};
template<typename T>
void operator<<(const NullStream&, const T&) {}
Application code:
NullStream ns;
ostream &os = ns;
os << "foo";
The real issue is all the public methods that I inherited but don't care about so I just didn't bother overriding them.
I want to throw an exception in my constructor so that I don't have to deal with zombie objects. However I also want to provide a validation method upfront so that people can avoid "dealing with exceptions" where there is no cause to. In a GUI it's not exceptional to expect invalid data. However I also want to avoid code duplication and overhead. Is GCC / Microsoft Visual C++ compiler smart enough to remove this inefficiency of validating an input twice and if not, is there a subtle change that could please?
An example code block illustrating my point is below:
#include <string>
#include <exception>
#include <iostream>
using std::string;
using std::cout;
using std::endl;
using std::exception;
// a validation function
bool InputIsValid(const string& input) {
return (input == "hello");
}
// a class that uses the validation code in a constructor
class MyObject {
public:
MyObject(string input) {
if (!InputIsValid(input)) //since all instances of input
throw exception(); //has already been validated
//does this code incur an overhead
//or get optimised out?
cout << input << endl;
};
};
int main() {
const string valid = "hello";
if (InputIsValid(valid)) {
MyObject obj_one(valid);
MyObject obj_two(valid);
}
return 0;
}
I anticipate this may not be possibly if the object file for the class is generated alone as the object file has no way to ensure people will validate before calling the constructor, but when an application is compiled and linked together in a single application, is it possible please?
Is there an overhead of validating in a constructor if all data may already be valid?
Yes, if the data is already validated, then you would incur the cost of validating it again
Is GCC / Microsoft Visual C++ compiler smart enough to remove this inefficiency of validating an input twice and if not, is there a subtle change that could please?
You could encapsulate your input in an object, and that object would remember the result of validation.
template <typename INPUT_TYPE>
class InputObject {
INPUT_TYPE input_;
bool valid_;
public:
typedef <typename VALIDATE>
InputObject (INPUT_TYPE in, VALIDATE v) : input(in), valid_(v(in)) {}
const INPUT_TYPE & input () const { return input_; }
bool isValid () const { return valid_; }
};
typedef InputObject<std::string> MyInput;
class MyObject {
public:
MyObject (const MyInput &input) {
if (!input.isValid()) throw exception();
//...
}
};
The constructor to InputObject calls the validator function for you, and stores the result of validation in a flag. Then MyObject just checks the flag, and doesn't have to do the validation again.
int main () {
MyInput input("hello", InputIsValid);
try {
MyObject obj_one(input);
MyObject obj_two(input);
}
catch (...) {
//...
}
}
As suggested by DeadMG, stronger type checking can be achieved by insisting that MyObject only accept validated input. Then, it would not need to throw in the constructor at all. Such a scheme could be accomplished by making NonValidatedInput and ValidatedInput two different types.
template <typename> class NonValidatedInput;
template <typename T>
class ValidatedInput {
friend class NonValidatedInput<T>;
T input;
ValidatedInput (const T &in) : input(in) {}
public:
operator const T & () const { return input; };
};
template <typename T>
class NonValidatedInput {
T input;
public:
operator ValidatedInput<T> () const { return ValidatedInput<T>(input); }
template <typename V>
NonValidatedInput (const T &in, V v) : input(in) {
if (v(input) == false) throw exception();
}
};
NonValidatedInput accepts non-validated input, and performs the validation, and can be converted to a ValidatedInput object if the validation succeeds. If the validation fails, NonValidatedInput throws an exception. Thus, MyObject has no need to check for validation at all, because it's constructor only accepts ValidatedInput.
typedef ValidatedInput<std::string> MyInput;
class MyObject {
public:
MyObject (MyInput input) {
std::string v = input;
std::cout << v << std::endl;
}
};
int main () {
try {
MyInput input = NonValidatedInput<std::string>("hello", InputIsValid);
MyObject obj_one(input);
MyObject obj_two(input);
}
catch (...) {
//...
}
}
The type safety here is quite strong, because only NonValidatedInput can create a ValidatedInput, and only if the validation succeeded.
the optimizer may inline the function InputIsValid(), however that's about as far as it will go. You also need to document your constructor as throwing, with the types of exceptions its going to throw. As far as the performance costs of calling that function,it's negligible, the cost of a strcmp(). Suffice to says though unless that constructor is used in an extremely tight loop that the costs should be negligible.
This question already has answers here:
Standard no-op output stream
(6 answers)
Closed 2 years ago.
I'd like to send data to nowhere, I mean that I don't want to print data in console nor in file, but I need some std::ostream object. How to do that?
I've used:
std::ostream bitBucket(0);
recently without problems, although it was flagged as having some potential problems if you looked at it from a certain angle (see the link below).
Aside: From what I understand (and I'm not entirely sure of this), that call above eventually ends up calling basic_ios::init(0) and, because that's a NULL pointer being passed in, it sets the stream state, as returned by the rdstate() function, to the badbit value.
This in turn prevents the stream from outputting any more information, instead just tossing it away.
The following program shows it in action:
#include <iostream>
int main (void) {
std::ostream bitBucket(0);
bitBucket << "Hello, there!" << std::endl;
return 0;
}
The page where I got it from also had this as a probably-cleaner solution (slightly modified to remove the duplication of my first solution above):
#include <iostream>
class null_out_buf : public std::streambuf {
public:
virtual std::streamsize xsputn (const char * s, std::streamsize n) {
return n;
}
virtual int overflow (int c) {
return 1;
}
};
class null_out_stream : public std::ostream {
public:
null_out_stream() : std::ostream (&buf) {}
private:
null_out_buf buf;
};
null_out_stream cnul; // My null stream.
int main (void) {
std::cout << std::boolalpha;
//testing nul
std::cout << "Nul stream before: " << cnul.fail() << std::endl;
cnul << "Goodbye World!" << std::endl;
std::cout << "Nul stream after: " << cnul.fail() << std::endl;
}
The simplest solution is just to output to an unopened std::ofstream
(or any other output stream in an error state). This will result in the
stream being permanently in an error state. This could be an advantage
(<< operators will skip the formatting), but if any code that you
can't control checks for errors, and does something particular if they
occur, you'll likely have problems.
Otherwise, it's pretty simple to implement a null stream; the only
streambuf function you really have to override is overflow.
Something like the following should do the trick:
class NulStreambuf : public std::streambuf
{
char dummyBuffer[64];
protected:
virtual int overflow( int c )
{
setp( dummyBuffer, dummyBuffer + sizeof( dummyBuffer ) ) ;
return (c == EOF) ? '\0' : c ;
}
};
(The buffer will avoid some unnecessary virtual function calls. On some
platforms, this makes a significant difference.)
Then create an output stream which uses it:
class NulOStream : public NulStreambuf, public std::ostream
{
public:
NulOStream() : std::ostream( this ) {}
};
(The use of inheritance, rather than containment, ensures that the
streambuf is fully constructed before being passed to the ostream.
This generally isn't necessary in practice, but the standard doesn't
seem to authorize passing a not yet constructed streambuf to the
constructor of ostream.)
Simplest solution: Use a std::stringstream.
#include <sstream>
#include <iostream>
void func(std::ostream& o){
o << "blatest\n";
}
int main(){
std::stringstream black_hole;
func(std::cout);
func(black_hole);
}
The stringstream will contain the output, but if you don't use it, it's the same as if it was never filled.
Since nobody mentioned it, if it's about suppressing std or error output, you can simply close the corresponding file descriptors (e.g. fclose (stdout) or fclose (stderr)).
That will shup up everything, including things like printf or fprintf (stderr, ...)
So you will indeed keep using the usual cout or cerr, but they will be turned into bit buckets.
Some suggestions here: http://bytes.com/topic/c/answers/589209-std-null-stream
A good answer from that site:
Use ordinary std::fstream, open it only for writing to required file
"/dev/null". It should work.
If you really want to create own stream, just derive it from
basic_ostream and simply define your own operator<< to be function
which only returns stream reference. You will have to write dummy
'write' and 'put' method too (and all other methods for output).
#include <streambuf>
#include <ostream>
template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
typename traits::int_type overflow(typename traits::int_type c)
{
return traits::not_eof(c); // indicate success
}
};
template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
public:
basic_onullstream():
std::basic_ios<cT, traits>(&m_sbuf),
std::basic_ostream<cT, traits>(&m_sbuf)
{
init(&m_sbuf);
}
private:
basic_nullbuf<cT, traits> m_sbuf;
};
typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;
From http://bytes.com/topic/c/answers/428285-null-ostream