aboutsummaryrefslogtreecommitdiff
path: root/libbutl/diagnostics.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbutl/diagnostics.cxx')
-rw-r--r--libbutl/diagnostics.cxx56
1 files changed, 46 insertions, 10 deletions
diff --git a/libbutl/diagnostics.cxx b/libbutl/diagnostics.cxx
index 8525d60..6ac8192 100644
--- a/libbutl/diagnostics.cxx
+++ b/libbutl/diagnostics.cxx
@@ -17,6 +17,14 @@
#include <cstddef> // size_t
#include <iostream> // cerr
+#ifndef LIBBUTL_MINGW_STDTHREAD
+# include <mutex>
+#else
+# include <libbutl/mingw-mutex.hxx>
+#endif
+
+#include <libbutl/ft/lang.hxx> // thread_local
+
#include <libbutl/utility.hxx>
#include <libbutl/optional.hxx>
#include <libbutl/fdstream.hxx>
@@ -27,7 +35,11 @@ namespace butl
{
ostream* diag_stream = &cerr;
- static mutex diag_mutex;
+#ifndef LIBBUTL_MINGW_STDTHREAD
+ static std::mutex diag_mutex;
+#else
+ static mingw_stdthread::mutex diag_mutex;
+#endif
string diag_progress;
static string diag_progress_blank; // Being printed blanks out the line.
@@ -131,28 +143,28 @@ namespace butl
default_writer (const diag_record& r)
{
r.os.put ('\n');
- diag_stream_lock () << r.os.str ();
+
+ diag_stream_lock l;
+ (*diag_stream) << r.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.
//
- // @@ Strange: why not just hold the lock for both write and flush?
- //
diag_stream->flush ();
}
- void (*diag_record::writer) (const diag_record&) = &default_writer;
+ diag_writer* diag_record::writer = &default_writer;
void diag_record::
- flush () const
+ flush (void (*w) (const diag_record&)) const
{
if (!empty_)
{
if (epilogue_ == nullptr)
{
- if (writer != nullptr)
- writer (*this);
+ if (w != nullptr || (w = writer) != nullptr)
+ w (*this);
empty_ = true;
}
@@ -162,8 +174,8 @@ namespace butl
//
auto e (epilogue_);
epilogue_ = nullptr;
- e (*this); // Can throw.
- flush (); // Call ourselves to write the data in case it returns.
+ e (*this, w); // Can throw.
+ flush (w); // Call ourselves to write the data in case it returns.
}
}
}
@@ -186,4 +198,28 @@ namespace butl
flush ();
#endif
}
+
+ // Diagnostics stack.
+ //
+ static
+#ifdef __cpp_thread_local
+ thread_local
+#else
+ __thread
+#endif
+ const diag_frame* diag_frame_stack = nullptr;
+
+ const diag_frame* diag_frame::
+ stack () noexcept
+ {
+ return diag_frame_stack;
+ }
+
+ const diag_frame* diag_frame::
+ stack (const diag_frame* f) noexcept
+ {
+ const diag_frame* r (diag_frame_stack);
+ diag_frame_stack = f;
+ return r;
+ }
}