--- /dev/null 2020-02-13 04:30:26.348000000 +0000 +++ new/src/hotspot/share/logging/asynclog.hpp 2020-02-24 07:47:47.217119620 +0000 @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef SHARE_LOGGING_ASYNCLOG_HPP +#define SHARE_LOGGING_ASYNCLOG_HPP +#include "logging/logLevel.hpp" +#include "logging/logPrefix.hpp" +#include "logging/logTagSet.hpp" +#include "logging/logTag.hpp" +#include "logging/logAsyncFlusher.hpp" +#include "logging/logMessageBuffer.hpp" + +#define asynclog_error(...) (!asynclog_is_enabled(Error, __VA_ARGS__)) ? (void)0 : AsyncLogImpl().write +#define asynclog_warning(...) (!asynclog_is_enabled(Warning, __VA_ARGS__)) ? (void)0 : AsyncLogImpl().write +#define asynclog_info(...) (!asynclog_is_enabled(Info, __VA_ARGS__)) ? (void)0 : AsyncLogImpl().write +#define asynclog_debug(...) (!asynclog_is_enabled(Debug, __VA_ARGS__)) ? (void)0 : AsyncLogImpl().write +#define asynclog_trace(...) (!asynclog_is_enabled(Trace, __VA_ARGS__)) ? (void)0 : AsyncLogImpl().write + +// Macros for logging that should be excluded in product builds. +// Available for levels Info, Debug and Trace. Includes test macro that +// evaluates to false in product builds. +#ifndef PRODUCT +#define asynclog_develop_info(...) (!asynclog_is_enabled(Info, __VA_ARGS__)) ? (void)0 : AsyncLogImpl().write +#define asynclog_develop_debug(...) (!asynclog_is_enabled(Debug, __VA_ARGS__)) ? (void)0 : AsyncLogImpl().write +#define asynclog_develop_trace(...) (!asynclog_is_enabled(Trace, __VA_ARGS__)) ? (void)0 : AsyncLogImpl().write +#define asynclog_develop_is_enabled(level, ...) asynclog_is_enabled(level, __VA_ARGS__) +#else +#define DUMMY_ARGUMENT_CONSUMER(...) +#define asynclog_develop_info(...) DUMMY_ARGUMENT_CONSUMER +#define asynclog_develop_debug(...) DUMMY_ARGUMENT_CONSUMER +#define asynclog_develop_trace(...) DUMMY_ARGUMENT_CONSUMER +#define asynclog_develop_is_enabled(...) false +#endif + +// Convenience macro to test if the logging is enabled on the specified level for given tags. +#define asynclog_is_enabled(level, ...) (AsyncLogImpl::is_level(LogLevel::level)) + +#define AsyncLog(...) AsyncLogImpl +#define AsyncLogTarget(level, ...) AsyncLogTargetImpl + +template +class AsyncLogTargetImpl; + +class Arena; + +template +class AsyncLogImpl { + private: + Arena* _arena; + LogMessageBuffer* _buf; + void create_async_buffer() { + Arena* arena = new (mtLogging)Arena(mtLogging, LogMessageBuffer::initial_buffer_size()); + _buf = new (mtLogging)LogMessageBuffer(arena); + _buf->set_prefix(LogPrefix::prefix); + } + + public: + // Make sure no more than the maximum number of tags have been given. + // The GuardTag allows this to be detected if/when it happens. If the GuardTag + // is not __NO_TAG, the number of tags given exceeds the maximum allowed. + STATIC_ASSERT(GuardTag == LogTag::__NO_TAG); // Number of logging tags exceeds maximum supported! + + AsyncLogImpl() : _arena(NULL), _buf(NULL) { + } + + ~AsyncLogImpl() { + if (_buf != NULL) { + LogAsyncFlusher* flusher = LogAsyncFlusher::instance(); + flusher->enqueue(&LogTagSetMapping::tagset(), _buf); + } + } + + static bool is_level(LogLevelType level) { + return LogTagSetMapping::tagset().is_level(level); + } + + ATTRIBUTE_PRINTF(3, 4) + void write(LogLevelType level, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + vwrite(level, fmt, args); + va_end(args); + } + + // to be implemented or deleted. + void write(const LogMessageBuffer& msg); + + template + ATTRIBUTE_PRINTF(2, 3) + void write(const char* fmt, ...) { + va_list args; + va_start(args, fmt); + vwrite(Level, fmt, args); + va_end(args); + } + + ATTRIBUTE_PRINTF(3, 0) + void vwrite(LogLevelType level, const char* fmt, va_list args) { + if (!_buf) create_async_buffer(); + _buf->vwrite(level, fmt, args); + } + +#define LOG_LEVEL(level, name) ATTRIBUTE_PRINTF(2, 0) \ + AsyncLogImpl& v##name(const char* fmt, va_list args) { \ + vwrite(LogLevel::level, fmt, args); \ + return *this; \ + } \ + AsyncLogImpl& name(const char* fmt, ...) ATTRIBUTE_PRINTF(2, 3) { \ + va_list args; \ + va_start(args, fmt); \ + vwrite(LogLevel::level, fmt, args); \ + va_end(args); \ + return *this; \ + } \ + static bool is_##name() { \ + return is_level(LogLevel::level); \ + } \ + static AsyncLogTargetImpl* name() { \ + return (AsyncLogTargetImpl*)NULL; \ + } + LOG_LEVEL_LIST +#undef LOG_LEVEL +}; + +// Combines logging tags and a logging level. +template +class AsyncLogTargetImpl { +public: + // Empty constructor to avoid warnings on MSVC about unused variables + // when the log instance is only used for static functions. + AsyncLogTargetImpl() { + } + + static bool is_enabled() { + return AsyncLogImpl::is_level(level); + } + + static void print(const char* fmt, ...) ATTRIBUTE_PRINTF(1, 2) { + AsyncLogImpl impl; + va_list args; + + va_start(args, fmt); + impl.vwrite(level, fmt, args); + va_end(args); + } + +}; + +#endif // SHARE_LOGGING_ASYNCLOG_HPP