aboutsummaryrefslogtreecommitdiff
path: root/libbutl/diagnostics.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2017-05-01 16:08:43 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2017-05-01 16:59:24 +0300
commit61377c582e0f2675baa5f5e6e30a35d1a4164b33 (patch)
tree11cdca992834d7f7f197f72856712fbcb3020e3d /libbutl/diagnostics.cxx
parent442c1a6790e52baa0c081f310d4d9e9b6f1ff638 (diff)
Add hxx extension for headers and lib prefix for library dir
Diffstat (limited to 'libbutl/diagnostics.cxx')
-rw-r--r--libbutl/diagnostics.cxx80
1 files changed, 80 insertions, 0 deletions
diff --git a/libbutl/diagnostics.cxx b/libbutl/diagnostics.cxx
new file mode 100644
index 0000000..e73412b
--- /dev/null
+++ b/libbutl/diagnostics.cxx
@@ -0,0 +1,80 @@
+// file : libbutl/diagnostics.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <libbutl/diagnostics.hxx>
+
+#include <mutex>
+#include <iostream> // cerr
+
+using namespace std;
+
+namespace butl
+{
+ ostream* diag_stream = &cerr;
+
+ static mutex diag_mutex;
+
+ diag_lock::diag_lock ()
+ {
+ diag_mutex.lock ();
+ }
+
+ diag_lock::~diag_lock ()
+ {
+ diag_mutex.unlock ();
+ }
+
+ void diag_record::
+ flush () const
+ {
+ if (!empty_)
+ {
+ if (epilogue_ == nullptr)
+ {
+ os.put ('\n');
+
+ {
+ diag_lock l;
+ *diag_stream << os.str ();
+ }
+
+ // We can endup flushing the result of several writes. The last one may
+ // possibly be incomplete, but that's not a problem as it will also be
+ // followed by the flush() call.
+ //
+ diag_stream->flush ();
+
+ empty_ = true;
+ }
+ else
+ {
+ // Clear the epilogue in case it calls us back.
+ //
+ auto e (epilogue_);
+ epilogue_ = nullptr;
+ e (*this); // Can throw.
+ flush (); // Call ourselves to write the data in case it returns.
+ }
+ }
+ }
+
+ diag_record::
+ ~diag_record () noexcept (false)
+ {
+ // Don't flush the record if this destructor was called as part of the
+ // stack unwinding.
+ //
+#ifdef __cpp_lib_uncaught_exceptions
+ if (uncaught_ == std::uncaught_exceptions ())
+ flush ();
+#else
+ // Fallback implementation. Right now this means we cannot use this
+ // mechanism in destructors, which is not a big deal, except for one
+ // place: exception_guard. Thus the ugly special check.
+ //
+ if (!std::uncaught_exception () || exception_unwinding_dtor ())
+ flush ();
+#endif
+ }
+}