From e22fc121aed56dad2eedfdc3a53f2a655c3b200b Mon Sep 17 00:00:00 2001
From: Thomas Stuefe <stuefe@openjdk.org>
Date: Mon, 10 Jun 2024 12:33:32 +0000
Subject: [PATCH] 8333775: Small improvement to outputStream auto-indentation
 mode

Reviewed-by: jsjolen, mbaesken
---
 src/hotspot/share/nmt/memReporter.cpp         |  8 +------
 src/hotspot/share/nmt/memReporter.hpp         |  2 +-
 src/hotspot/share/utilities/ostream.cpp       |  6 +++++
 src/hotspot/share/utilities/ostream.hpp       | 22 ++++++++++++++-----
 test/hotspot/gtest/utilities/test_ostream.cpp |  5 ++++-
 5 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/src/hotspot/share/nmt/memReporter.cpp b/src/hotspot/share/nmt/memReporter.cpp
index e5969bbaf8f..bd2f38acdd0 100644
--- a/src/hotspot/share/nmt/memReporter.cpp
+++ b/src/hotspot/share/nmt/memReporter.cpp
@@ -51,13 +51,7 @@ static ssize_t counter_diff(size_t c1, size_t c2) {
 }
 
 MemReporterBase::MemReporterBase(outputStream* out, size_t scale) :
-  _scale(scale), _output(out) {
-  _output->set_autoindent(true);
-}
-
-MemReporterBase::~MemReporterBase() {
-  _output->set_autoindent(false);
-}
+  _scale(scale), _output(out), _auto_indentor(out) {}
 
 size_t MemReporterBase::reserved_total(const MallocMemory* malloc, const VirtualMemory* vm) {
   return malloc->malloc_size() + malloc->arena_size() + vm->reserved();
diff --git a/src/hotspot/share/nmt/memReporter.hpp b/src/hotspot/share/nmt/memReporter.hpp
index 3f08ecbd284..c10a9979508 100644
--- a/src/hotspot/share/nmt/memReporter.hpp
+++ b/src/hotspot/share/nmt/memReporter.hpp
@@ -38,6 +38,7 @@ class MemReporterBase : public StackObj {
  private:
   const size_t  _scale;         // report in this scale
   outputStream* const _output;  // destination
+  StreamAutoIndentor _auto_indentor;
 
  public:
 
@@ -45,7 +46,6 @@ class MemReporterBase : public StackObj {
   static const size_t default_scale = K;
 
   MemReporterBase(outputStream* out, size_t scale = default_scale);
-  ~MemReporterBase();
 
   // Helper functions
   // Calculate total reserved and committed amount
diff --git a/src/hotspot/share/utilities/ostream.cpp b/src/hotspot/share/utilities/ostream.cpp
index 6057d1a7710..5d6731785a3 100644
--- a/src/hotspot/share/utilities/ostream.cpp
+++ b/src/hotspot/share/utilities/ostream.cpp
@@ -277,6 +277,12 @@ outputStream& outputStream::indent() {
   return *this;
 }
 
+bool outputStream::set_autoindent(bool value) {
+  const bool old = _autoindent;
+  _autoindent = value;
+  return old;
+}
+
 void outputStream::print_jlong(jlong value) {
   print(JLONG_FORMAT, value);
 }
diff --git a/src/hotspot/share/utilities/ostream.hpp b/src/hotspot/share/utilities/ostream.hpp
index b4ce7c32c60..bff682a3e5a 100644
--- a/src/hotspot/share/utilities/ostream.hpp
+++ b/src/hotspot/share/utilities/ostream.hpp
@@ -109,7 +109,8 @@ class outputStream : public CHeapObjBase {
    // line starts depending on the current indentation level:
    // print(), print_cr(), print_raw(), print_raw_cr()
    // Other APIs are unaffected
-   void set_autoindent(bool value) { _autoindent = value; }
+   // Returns old autoindent state.
+   bool set_autoindent(bool value);
 
    // sizing
    int position() const { return _position; }
@@ -175,17 +176,26 @@ class outputStream : public CHeapObjBase {
 extern outputStream* tty;           // tty output
 
 class streamIndentor : public StackObj {
- private:
-  outputStream* _str;
-  int _amount;
-
- public:
+  outputStream* const _str;
+  const int _amount;
+  NONCOPYABLE(streamIndentor);
+public:
   streamIndentor(outputStream* str, int amt = 2) : _str(str), _amount(amt) {
     _str->inc(_amount);
   }
   ~streamIndentor() { _str->dec(_amount); }
 };
 
+class StreamAutoIndentor : public StackObj {
+  outputStream* const _os;
+  const bool _old;
+  NONCOPYABLE(StreamAutoIndentor);
+ public:
+  StreamAutoIndentor(outputStream* os) :
+    _os(os), _old(os->set_autoindent(true)) {}
+  ~StreamAutoIndentor() { _os->set_autoindent(_old); }
+};
+
 // advisory locking for the shared tty stream:
 class ttyLocker: StackObj {
   friend class ttyUnlocker;
diff --git a/test/hotspot/gtest/utilities/test_ostream.cpp b/test/hotspot/gtest/utilities/test_ostream.cpp
index 26fd9d227c1..5d25c51f3f9 100644
--- a/test/hotspot/gtest/utilities/test_ostream.cpp
+++ b/test/hotspot/gtest/utilities/test_ostream.cpp
@@ -106,7 +106,8 @@ TEST_VM(ostream, bufferedStream_dynamic_small) {
 
 static void test_autoindent(bool on) {
   stringStream ss;
-  ss.set_autoindent(on);
+  const bool prior = ss.set_autoindent(on);
+  EXPECT_FALSE(prior);
   {
     streamIndentor si(&ss, 5);
     ss.print("ABC");
@@ -146,6 +147,8 @@ static void test_autoindent(bool on) {
         "end"
     );
   }
+  bool prior2 = ss.set_autoindent(prior);
+  EXPECT_EQ(prior2, on);
 }
 
 TEST_VM(ostream, autoindent_on)  { test_autoindent(true);  }