Skip to content

Commit b2ba9fc

Browse files
jdksjolenstefank
authored andcommitted
8286180: Enable construction of LogStreamImpl from LogMessageImpl
Reviewed-by: dholmes, stefank
1 parent 0c420e0 commit b2ba9fc

File tree

6 files changed

+231
-110
lines changed

6 files changed

+231
-110
lines changed

src/hotspot/share/logging/logHandle.hpp

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -32,35 +32,35 @@
3232
// polluting the surrounding API with template functions.
3333
class LogHandle {
3434
private:
35-
LogTagSet* const _tagset;
35+
LogTagSet& _tagset;
3636

3737
public:
3838
template <LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
39-
LogHandle(const LogImpl<T0, T1, T2, T3, T4, GuardTag>& type_carrier) :
40-
_tagset(&LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
39+
LogHandle(const LogImpl<T0, T1, T2, T3, T4, GuardTag>& type_carrier)
40+
: _tagset(LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
4141

4242
bool is_level(LogLevelType level) {
43-
return _tagset->is_level(level);
43+
return _tagset.is_level(level);
4444
}
4545

46-
LogTagSet* const tagset() const {
46+
LogTagSet& tagset() const {
4747
return _tagset;
4848
}
4949

5050
#define LOG_LEVEL(level, name) ATTRIBUTE_PRINTF(2, 0) \
5151
LogHandle& v##name(const char* fmt, va_list args) { \
52-
_tagset->vwrite(LogLevel::level, fmt, args); \
52+
_tagset.vwrite(LogLevel::level, fmt, args); \
5353
return *this; \
5454
} \
5555
LogHandle& name(const char* fmt, ...) ATTRIBUTE_PRINTF(2, 3) { \
5656
va_list args; \
5757
va_start(args, fmt); \
58-
_tagset->vwrite(LogLevel::level, fmt, args); \
58+
_tagset.vwrite(LogLevel::level, fmt, args); \
5959
va_end(args); \
6060
return *this; \
6161
} \
6262
bool is_##name() { \
63-
return _tagset->is_level(LogLevel::level); \
63+
return _tagset.is_level(LogLevel::level); \
6464
}
6565
LOG_LEVEL_LIST
6666
#undef LOG_LEVEL
@@ -73,15 +73,17 @@ class LogHandle {
7373
class LogTargetHandle {
7474
private:
7575
const LogLevelType _level;
76-
LogTagSet* const _tagset;
76+
LogTagSet& _tagset;
7777

7878
public:
79-
LogTargetHandle(LogLevelType level, LogTagSet* const tagset) : _level(level), _tagset(tagset) {}
79+
LogTargetHandle(LogLevelType level, LogTagSet& tagset)
80+
: _level(level),
81+
_tagset(tagset) {}
8082

8183
template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
82-
LogTargetHandle(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>& type_carrier) :
83-
_level(level),
84-
_tagset(&LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
84+
LogTargetHandle(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>& type_carrier)
85+
: _level(level),
86+
_tagset(LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
8587

8688
template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
8789
static LogTargetHandle create() {
@@ -92,15 +94,14 @@ class LogTargetHandle {
9294
va_list args;
9395
va_start(args, fmt);
9496
if (is_enabled()) {
95-
_tagset->vwrite(_level, fmt, args);
97+
_tagset.vwrite(_level, fmt, args);
9698
}
9799
va_end(args);
98100
}
99101

100102
bool is_enabled() const {
101-
return _tagset->is_level(_level);
103+
return _tagset.is_level(_level);
102104
}
103-
104105
};
105106

106107
#endif // SHARE_LOGGING_LOGHANDLE_HPP

src/hotspot/share/logging/logMessage.hpp

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -57,19 +57,19 @@
5757
// Log outputs on debug level will see the debug message,
5858
// but not the trace message.
5959
//
60-
#define LogMessage(...) LogMessageImpl<LOG_TAGS(__VA_ARGS__)>
61-
template <LogTagType T0, LogTagType T1 = LogTag::__NO_TAG, LogTagType T2 = LogTag::__NO_TAG,
62-
LogTagType T3 = LogTag::__NO_TAG, LogTagType T4 = LogTag::__NO_TAG, LogTagType GuardTag = LogTag::__NO_TAG>
60+
#define LogMessage(...) LogMessageTemplate<LOG_TAGS(__VA_ARGS__)>
61+
6362
class LogMessageImpl : public LogMessageBuffer {
64-
private:
65-
bool _has_content;
63+
private:
6664
LogTagSet& _tagset;
67-
public:
68-
LogMessageImpl() :
69-
_has_content(false),
70-
_tagset(LogTagSetMapping<T0, T1, T2, T3, T4, GuardTag>::tagset())
71-
{}
65+
bool _has_content;
66+
67+
protected:
68+
LogMessageImpl(LogTagSet& tagset)
69+
: _tagset(tagset),
70+
_has_content(false) {};
7271

72+
public:
7373
~LogMessageImpl() {
7474
if (_has_content) {
7575
flush();
@@ -90,11 +90,15 @@ class LogMessageImpl : public LogMessageBuffer {
9090
void vwrite(LogLevelType level, const char* fmt, va_list args) {
9191
if (!_has_content) {
9292
_has_content = true;
93-
set_prefix(LogPrefix<T0, T1, T2, T3, T4>::prefix);
93+
set_prefix(_tagset.write_prefix());
9494
}
9595
LogMessageBuffer::vwrite(level, fmt, args);
9696
}
9797

98+
bool is_level(LogLevelType level) const {
99+
return _tagset.is_level(level);
100+
}
101+
98102
#define LOG_LEVEL(level, name) \
99103
bool is_##name() const { \
100104
return _tagset.is_level(LogLevel::level); \
@@ -103,4 +107,13 @@ class LogMessageImpl : public LogMessageBuffer {
103107
#undef LOG_LEVEL
104108
};
105109

110+
template <LogTagType T0, LogTagType T1 = LogTag::__NO_TAG, LogTagType T2 = LogTag::__NO_TAG, LogTagType T3 = LogTag::__NO_TAG,
111+
LogTagType T4 = LogTag::__NO_TAG, LogTagType GuardTag = LogTag::__NO_TAG>
112+
class LogMessageTemplate : public LogMessageImpl {
113+
public:
114+
LogMessageTemplate(LogMessageTemplate&&) = default;
115+
LogMessageTemplate()
116+
: LogMessageImpl(LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
117+
};
118+
106119
#endif // SHARE_LOGGING_LOGMESSAGE_HPP
Lines changed: 57 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -23,18 +23,16 @@
2323
*/
2424

2525
#include "precompiled.hpp"
26-
#include "logging/log.hpp"
2726
#include "logging/logStream.hpp"
2827
#include "runtime/os.hpp"
2928
#include "utilities/align.hpp"
3029

31-
LogStream::LineBuffer::LineBuffer()
32-
: _buf(_smallbuf), _cap(sizeof(_smallbuf)), _pos(0)
33-
{
30+
LogStreamImplBase::LineBuffer::LineBuffer()
31+
: _buf(_smallbuf), _cap(sizeof(_smallbuf)), _pos(0) {
3432
_buf[0] = '\0';
3533
}
3634

37-
LogStream::LineBuffer::~LineBuffer() {
35+
LogStreamImplBase::LineBuffer::~LineBuffer() {
3836
assert(_pos == 0, "still outstanding bytes in the line buffer");
3937
if (_buf != _smallbuf) {
4038
os::free(_buf);
@@ -43,51 +41,56 @@ LogStream::LineBuffer::~LineBuffer() {
4341

4442
// try_ensure_cap tries to enlarge the capacity of the internal buffer
4543
// to the given atleast value. May fail if either OOM happens or atleast
46-
// is larger than a reasonable max of 1 M. Caller must not assume
47-
// capacity without checking.
48-
void LogStream::LineBuffer::try_ensure_cap(size_t atleast) {
44+
// is larger than a reasonable max of 1 M.
45+
// Returns whether the capacity is at least atleast bytes.
46+
bool LogStreamImplBase::LineBuffer::try_ensure_cap(size_t atleast) {
47+
// Cap out at a reasonable max to prevent runaway leaks.
48+
const size_t reasonable_max = 1 * M;
49+
4950
assert(_cap >= sizeof(_smallbuf), "sanity");
50-
if (_cap < atleast) {
51-
// Cap out at a reasonable max to prevent runaway leaks.
52-
const size_t reasonable_max = 1 * M;
53-
assert(_cap <= reasonable_max, "sanity");
54-
if (_cap == reasonable_max) {
55-
return;
56-
}
51+
assert(_cap <= reasonable_max, "sanity");
5752

58-
const size_t additional_expansion = 256;
59-
size_t newcap = align_up(atleast + additional_expansion, additional_expansion);
60-
if (newcap > reasonable_max) {
61-
log_info(logging)("Suspiciously long log line: \"%.100s%s",
62-
_buf, (_pos >= 100 ? "..." : ""));
63-
newcap = reasonable_max;
64-
}
53+
if (_cap >= atleast) {
54+
return true;
55+
}
56+
if (_cap == reasonable_max) {
57+
return false;
58+
}
6559

66-
char* const newbuf = (char*) os::malloc(newcap, mtLogging);
67-
if (newbuf == NULL) { // OOM. Leave object unchanged.
68-
return;
69-
}
70-
if (_pos > 0) { // preserve old content
71-
memcpy(newbuf, _buf, _pos + 1); // ..including trailing zero
72-
}
73-
if (_buf != _smallbuf) {
74-
os::free(_buf);
75-
}
76-
_buf = newbuf;
77-
_cap = newcap;
60+
const size_t additional_expansion = 256;
61+
size_t newcap = align_up(atleast + additional_expansion, additional_expansion);
62+
63+
if (newcap > reasonable_max) {
64+
log_info(logging)("Suspiciously long log line: \"%.100s%s",
65+
_buf, (_pos >= 100 ? "..." : ""));
66+
newcap = reasonable_max;
67+
}
68+
69+
char* const newbuf = (char*)os::malloc(newcap, mtLogging);
70+
if (newbuf == NULL) { // OOM. Leave object unchanged.
71+
return false;
72+
}
73+
if (_pos > 0) { // preserve old content
74+
memcpy(newbuf, _buf, _pos + 1); // ..including trailing zero
7875
}
79-
assert(_cap >= atleast, "sanity");
76+
if (_buf != _smallbuf) {
77+
os::free(_buf);
78+
}
79+
_buf = newbuf;
80+
_cap = newcap;
81+
82+
return _cap >= atleast;
8083
}
8184

82-
void LogStream::LineBuffer::append(const char* s, size_t len) {
85+
void LogStreamImplBase::LineBuffer::append(const char* s, size_t len) {
8386
assert(_buf[_pos] == '\0', "sanity");
8487
assert(_pos < _cap, "sanity");
8588
const size_t minimum_capacity_needed = _pos + len + 1;
86-
try_ensure_cap(minimum_capacity_needed);
89+
const bool has_capacity = try_ensure_cap(minimum_capacity_needed);
8790
// try_ensure_cap may not have enlarged the capacity to the full requested
88-
// extend or may have not worked at all. In that case, just gracefully work
91+
// extent or may have not worked at all. In that case, just gracefully work
8992
// with what we have already; just truncate if necessary.
90-
if (_cap < minimum_capacity_needed) {
93+
if (!has_capacity) {
9194
len = _cap - _pos - 1;
9295
if (len == 0) {
9396
return;
@@ -98,28 +101,30 @@ void LogStream::LineBuffer::append(const char* s, size_t len) {
98101
_buf[_pos] = '\0';
99102
}
100103

101-
void LogStream::LineBuffer::reset() {
104+
void LogStreamImplBase::LineBuffer::reset() {
102105
_pos = 0;
103106
_buf[_pos] = '\0';
104107
}
105108

106-
void LogStream::write(const char* s, size_t len) {
109+
template <typename BackingLog>
110+
LogStreamImpl<BackingLog>::~LogStreamImpl() {
111+
if (!_current_line.is_empty()) {
112+
_backing_log.print("%s", _current_line.buffer());
113+
_current_line.reset();
114+
}
115+
}
116+
117+
template <typename BackingLog>
118+
void LogStreamImpl<BackingLog>::write(const char* s, size_t len) {
107119
if (len > 0 && s[len - 1] == '\n') {
108120
_current_line.append(s, len - 1); // omit the newline.
109-
_log_handle.print("%s", _current_line.buffer());
121+
_backing_log.print("%s", _current_line.buffer());
110122
_current_line.reset();
111123
} else {
112124
_current_line.append(s, len);
113125
}
114126
update_position(s, len);
115127
}
116128

117-
// Destructor writes any unfinished output left in the line buffer.
118-
LogStream::~LogStream() {
119-
if (_current_line.is_empty() == false) {
120-
_log_handle.print("%s", _current_line.buffer());
121-
_current_line.reset();
122-
}
123-
}
124-
125-
129+
template class LogStreamImpl<LogTargetHandle>;
130+
template class LogStreamImpl<LogMessageHandle>;

0 commit comments

Comments
 (0)