1 // Copyright (c) 2017 Nuxi, https://nuxi.nl/
2 //
3 // This file is distributed under a 2-clause BSD license.
4 // See the LICENSE file for details.
5 
6 #ifndef FLOWER_UTIL_LOGGER_H
7 #define FLOWER_UTIL_LOGGER_H
8 
9 #include <iomanip>
10 #include <mutex>
11 #include <ostream>
12 #include <streambuf>
13 #include <thread>
14 
15 namespace flower {
16 namespace util {
17 namespace {
18 
19 // Log entry that is in the process of being written. This class
20 // serializes output to the stream and also ensures all entries have a
21 // trailing newline.
22 class LogTransaction : public std::ostream {
23  public:
LogTransaction(std::streambuf * streambuf,std::mutex * streambuf_lock)24   LogTransaction(std::streambuf* streambuf, std::mutex* streambuf_lock)
25       : std::ostream(streambuf), ostream_guard_(*streambuf_lock) {
26   }
27 
~LogTransaction()28   ~LogTransaction() {
29     *this << std::endl;
30   }
31 
32  private:
33   std::lock_guard<std::mutex> ostream_guard_;
34 };
35 
36 // Wrapper around std::ostream for writing log entries.
37 //
38 // C++ streams are not required to be thread-safe. This class protects
39 // an output stream with a mutex.
40 class Logger {
41  public:
Logger(std::streambuf * streambuf)42   explicit Logger(std::streambuf* streambuf) : streambuf_(streambuf) {
43   }
44 
45   // TODO(ed): Should we add support for logging severities?
Log()46   LogTransaction Log() {
47     return LogTransaction(streambuf_, &streambuf_lock_);
48   }
49 
50  private:
51   std::mutex streambuf_lock_;
52   std::streambuf* streambuf_;
53 };
54 
55 }  // namespace
56 }  // namespace util
57 }  // namespace flower
58 
59 #endif
60