8153659: Create a CHeap backed LogStream class

Reviewed-by: brutisso, mlarsson
This commit is contained in:
Stefan Karlsson 2016-04-11 08:51:53 +02:00
parent dab21ebd4d
commit 3200059098
5 changed files with 113 additions and 64 deletions

View File

@ -361,11 +361,32 @@ static void Test_logstream_no_rm() {
Test_logstream_helper(stream);
}
static void Test_logstreamcheap_log() {
Log(gc) log;
LogStreamCHeap stream(log.debug());
Test_logstream_helper(&stream);
}
static void Test_logstreamcheap_logtarget() {
LogTarget(Debug, gc) log;
LogStreamCHeap stream(log);
Test_logstream_helper(&stream);
}
void Test_logstream() {
// Test LogStreams with embedded ResourceMark.
Test_logstream_log();
Test_logstream_logtarget();
Test_logstream_logstreamhandle();
// Test LogStreams without embedded ResourceMark.
Test_logstream_no_rm();
// Test LogStreams backed by CHeap memory.
Test_logstreamcheap_log();
Test_logstreamcheap_logtarget();
}
void Test_loghandle_on() {

View File

@ -67,13 +67,13 @@ public:
// This can be used to pass a Log instance as a parameter without
// polluting the surrounding API with template functions.
class LogTargetHandle {
friend class LogStream;
private:
const LogLevelType _level;
LogTagSet* _tagset;
public:
LogTargetHandle(LogLevelType level, LogTagSet* tagset) : _level(level), _tagset(tagset) {}
template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
LogTargetHandle(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>& type_carrier) :
_level(level),

View File

@ -24,7 +24,7 @@
#include "precompiled.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "logging/logStream.inline.hpp"
// Create a log stream without an embedded ResourceMark.
// The function is placed here to be called out-of-line in log.hpp.

View File

@ -26,23 +26,100 @@
#define SHARE_VM_LOGGING_LOGSTREAM_HPP
#include "logging/log.hpp"
#include "logging/logHandle.hpp"
#include "memory/resourceArea.hpp"
#include "utilities/ostream.hpp"
// An output stream that logs to the logging framework.
// Requires a ResourceMark on the stack.
class LogStreamNoResourceMark : public outputStream {
private:
stringStream _current_line;
LogLevelType _level;
LogTagSet* _tagset;
// The base class of an output stream that logs to the logging framework.
template <class streamClass>
class LogStreamBase : public outputStream {
streamClass _current_line;
LogTargetHandle _log_handle;
public:
LogStreamNoResourceMark(LogLevelType level, LogTagSet* tagset) : _level(level), _tagset(tagset) {}
~LogStreamNoResourceMark() {
// Constructor to support creation from a LogTarget instance.
//
// LogTarget(Debug, gc) log;
// LogStreamBase(log) stream;
template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
LogStreamBase(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>& type_carrier) :
_log_handle(level, &LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
// Constructor to support creation from typed (likely NULL) pointer. Mostly used by the logging framework.
//
// LogStreamBase stream(log.debug());
// or
// LogStreamBase stream((LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>*)NULL);
template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
LogStreamBase(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>* type_carrier) :
_log_handle(level, &LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
// Constructor to support creation from a LogTargetHandle.
//
// LogTarget(Debug, gc) log;
// LogTargetHandle(log) handle;
// LogStreamBase stream(handle);
LogStreamBase(LogTargetHandle handle) : _log_handle(handle) {}
// Constructor to support creation from a log level and tagset.
//
// LogStreamBase(level, tageset);
LogStreamBase(LogLevelType level, LogTagSet* tagset) : _log_handle(level, tagset) {}
~LogStreamBase() {
guarantee(_current_line.size() == 0, "Buffer not flushed. Missing call to print_cr()?");
}
public:
void write(const char* s, size_t len);
};
// A stringStream with an embedded ResourceMark.
class stringStreamWithResourceMark : outputStream {
private:
// The stringStream Resource allocate in the constructor,
// so the order of the fields is important.
ResourceMark _embedded_resource_mark;
stringStream _stream;
public:
stringStreamWithResourceMark(size_t initial_bufsize = 256) :
_embedded_resource_mark(),
_stream(initial_bufsize) {}
virtual void write(const char* c, size_t len) { _stream.write(c, len); }
size_t size() { return _stream.size(); }
const char* base() { return _stream.base(); }
void reset() { _stream.reset(); }
char* as_string() { return _stream.as_string(); }
};
// An output stream that logs to the logging framework.
//
// The backing buffer is allocated in Resource memory.
// The caller is required to have a ResourceMark on the stack.
typedef LogStreamBase<stringStream> LogStreamNoResourceMark;
// An output stream that logs to the logging framework.
//
// The backing buffer is allocated in CHeap memory.
typedef LogStreamBase<bufferedStream> LogStreamCHeap;
// An output stream that logs to the logging framework, and embeds a ResourceMark.
//
// The backing buffer is allocated in Resource memory.
// The class is intended to be stack allocated.
// The class provides its own ResourceMark,
// so care needs to be taken when nested ResourceMarks are used.
typedef LogStreamBase<stringStreamWithResourceMark> LogStream;
// Support creation of a LogStream without having to provide a LogTarget pointer.
#define LogStreamHandle(level, ...) LogStreamTemplate<LogLevel::level, LOG_TAGS(__VA_ARGS__)>
template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
class LogStreamTemplate : public LogStream {
public:
LogStreamTemplate() : LogStream((LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>*)NULL) {}
};
#endif // SHARE_VM_LOGGING_LOGSTREAM_HPP

View File

@ -30,11 +30,12 @@
#include "memory/resourceArea.hpp"
#include "utilities/ostream.hpp"
inline void LogStreamNoResourceMark::write(const char* s, size_t len) {
template <class streamClass>
inline void LogStreamBase<streamClass>::write(const char* s, size_t len) {
if (len > 0 && s[len - 1] == '\n') {
_current_line.write(s, len - 1);
_current_line.write("\0", 1);
_tagset->write(_level, "%s", _current_line.base());
_log_handle.print("%s", _current_line.base());
_current_line.reset();
} else {
_current_line.write(s, len);
@ -42,54 +43,4 @@ inline void LogStreamNoResourceMark::write(const char* s, size_t len) {
update_position(s, len);
}
// An output stream that logs to the logging framework, and embeds a ResourceMark.
//
// The class is intended to be stack allocated.
// Care needs to be taken when nested ResourceMarks are used.
class LogStream : public outputStream {
private:
ResourceMark _embedded_resource_mark;
LogStreamNoResourceMark _stream;
public:
// Constructor to support creation from a LogTarget instance.
//
// LogTarget(Debug, gc) log;
// LogStream(log) stream;
template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
LogStream(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>& type_carrier) :
_embedded_resource_mark(),
_stream(level, &LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
// Constructor to support creation from typed (likely NULL) pointer. Mostly used by the logging framework.
//
// LogStream stream(log.debug());
// LogStream stream((LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>*)NULL);
template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
LogStream(const LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>* type_carrier) :
_embedded_resource_mark(),
_stream(level, &LogTagSetMapping<T0, T1, T2, T3, T4>::tagset()) {}
// Constructor to support creation from a LogTargetHandle.
//
// LogTarget(Debug, gc) log;
// LogTargetHandle(log) handle;
// LogStream stream(handle);
LogStream(LogTargetHandle handle) :
_embedded_resource_mark(),
_stream(handle._level, handle._tagset) {}
// Override of outputStream::write.
void write(const char* s, size_t len) { _stream.write(s, len); }
};
// Support creation of a LogStream without having to provide a LogTarget pointer.
#define LogStreamHandle(level, ...) LogStreamTemplate<LogLevel::level, LOG_TAGS(__VA_ARGS__)>
template <LogLevelType level, LogTagType T0, LogTagType T1, LogTagType T2, LogTagType T3, LogTagType T4, LogTagType GuardTag>
class LogStreamTemplate : public LogStream {
public:
LogStreamTemplate() : LogStream((LogTargetImpl<level, T0, T1, T2, T3, T4, GuardTag>*)NULL) {}
};
#endif // SHARE_VM_LOGGING_LOGSTREAM_INLINE_HPP