Path: blob/master/src/hotspot/share/logging/logOutputList.hpp
40930 views
/*1* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/23#ifndef SHARE_LOGGING_LOGOUTPUTLIST_HPP24#define SHARE_LOGGING_LOGOUTPUTLIST_HPP2526#include "logging/logLevel.hpp"27#include "memory/allocation.hpp"28#include "utilities/globalDefinitions.hpp"2930class LogOutput;3132// Data structure to keep track of log outputs for a given tagset.33// Essentially a sorted linked list going from error level outputs34// to outputs of finer levels. Keeps an index from each level to35// the first node in the list for the corresponding level.36// This allows a log message on, for example, info level to jump37// straight into the list where the first info level output can38// be found. The log message will then be printed on that output,39// as well as all outputs in nodes that follow in the list (which40// can be additional info level outputs and/or debug and trace outputs).41//42// Each instance keeps track of the number of current readers of the list.43// To remove a node from the list the node must first be unlinked,44// and the memory for that node can be freed whenever the removing45// thread observes an active reader count of 0 (after unlinking it).46class LogOutputList {47private:48struct LogOutputNode : public CHeapObj<mtLogging> {49LogOutput* _value;50LogOutputNode* _next;51LogLevelType _level;52};5354LogOutputNode* _level_start[LogLevel::Count];55volatile jint _active_readers;5657LogOutputNode* find(const LogOutput* output) const;58void remove_output(LogOutputNode* node);59void add_output(LogOutput* output, LogLevelType level);60void update_output_level(LogOutputNode* node, LogLevelType level);6162// Bookkeeping functions to keep track of number of active readers/iterators for the list.63jint increase_readers();64jint decrease_readers();6566public:67LogOutputList() : _active_readers(0) {68for (size_t i = 0; i < LogLevel::Count; i++) {69_level_start[i] = NULL;70}71}7273// Test if the outputlist has an output for the given level.74bool is_level(LogLevelType level) const {75return _level_start[level] != NULL;76}7778LogLevelType level_for(const LogOutput* output) const {79LogOutputNode* node = this->find(output);80if (node == NULL) {81return LogLevel::Off;82}83return node->_level;84}8586// Set (add/update/remove) the output to the specified level.87void set_output_level(LogOutput* output, LogLevelType level);8889// Removes all outputs. Equivalent of set_output_level(out, Off)90// for all outputs.91void clear();92void wait_until_no_readers() const;9394class Iterator {95friend class LogOutputList;96private:97LogOutputNode* _current;98LogOutputList* _list;99Iterator(LogOutputList* list, LogOutputNode* start) : _current(start), _list(list) {100}101102public:103Iterator(const Iterator &itr) : _current(itr._current), _list(itr._list){104itr._list->increase_readers();105}106107Iterator& operator=(const Iterator& rhs) {108_current = rhs._current;109if (_list != rhs._list) {110rhs._list->increase_readers();111_list->decrease_readers();112_list = rhs._list;113}114return *this;115}116117~Iterator() {118_list->decrease_readers();119}120121LogOutput* operator*() {122return _current->_value;123}124125void operator++(int) {126_current = _current->_next;127}128129bool operator!=(const LogOutputNode *ref) const {130return _current != ref;131}132133LogLevelType level() const {134return _current->_level;135}136};137138Iterator iterator(LogLevelType level = LogLevel::Last) {139increase_readers();140return Iterator(this, _level_start[level]);141}142143LogOutputNode* end() const {144return NULL;145}146};147148#endif // SHARE_LOGGING_LOGOUTPUTLIST_HPP149150151