Path: blob/master/src/hotspot/share/jfr/utilities/jfrDoublyLinkedList.hpp
41149 views
/*1* Copyright (c) 2016, 2020, 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*/2324#ifndef SHARE_JFR_UTILITIES_JFRDOUBLYLINKEDLIST_HPP25#define SHARE_JFR_UTILITIES_JFRDOUBLYLINKEDLIST_HPP2627#include "memory/allocation.hpp"2829template <typename T>30class JfrDoublyLinkedList {31private:32T* _head;33T* _tail;34size_t _count;3536T** list_head() { return &_head; }37T** list_tail() { return &_tail; }3839public:40typedef T Node;41JfrDoublyLinkedList() : _head(NULL), _tail(NULL), _count(0) {}42T* head() const { return _head; }43T* tail() const { return _tail; }44size_t count() const { return _count; }45T* clear(bool return_tail = false);46T* remove(T* const node);47void prepend(T* const node);48void append(T* const node);49void append_list(T* const head_node, T* const tail_node, size_t count);50bool in_list(const T* const target_node) const;51bool locate(const T* start_node, const T* const target_node) const;52};5354template <typename T>55inline void JfrDoublyLinkedList<T>::prepend(T* const node) {56assert(node != NULL, "invariant");57node->set_prev(NULL);58assert(!in_list(node), "already in list error");59T** lh = list_head();60if (*lh != NULL) {61(*lh)->set_prev(node);62node->set_next(*lh);63} else {64T** lt = list_tail();65assert(*lt == NULL, "invariant");66*lt = node;67node->set_next(NULL);68assert(tail() == node, "invariant");69assert(node->next() == NULL, "invariant");70}71*lh = node;72++_count;73assert(head() == node, "head error");74assert(in_list(node), "not in list error");75assert(node->prev() == NULL, "invariant");76}7778template <typename T>79void JfrDoublyLinkedList<T>::append(T* const node) {80assert(node != NULL, "invariant");81node->set_next(NULL);82assert(!in_list(node), "already in list error");83T** lt = list_tail();84if (*lt != NULL) {85// already an existing tail86node->set_prev(*lt);87(*lt)->set_next(node);88} else {89// if no tail, also update head90assert(*lt == NULL, "invariant");91T** lh = list_head();92assert(*lh == NULL, "invariant");93node->set_prev(NULL);94*lh = node;95assert(head() == node, "invariant");96}97*lt = node;98++_count;99assert(tail() == node, "invariant");100assert(in_list(node), "not in list error");101assert(node->next() == NULL, "invariant");102}103104template <typename T>105T* JfrDoublyLinkedList<T>::remove(T* const node) {106assert(node != NULL, "invariant");107assert(in_list(node), "invariant");108T* const prev = (T*)node->prev();109T* const next = (T*)node->next();110if (prev == NULL) {111assert(head() == node, "head error");112if (next != NULL) {113next->set_prev(NULL);114} else {115assert(next == NULL, "invariant");116assert(tail() == node, "tail error");117T** lt = list_tail();118*lt = NULL;119assert(tail() == NULL, "invariant");120}121T** lh = list_head();122*lh = next;123assert(head() == next, "invariant");124} else {125assert(prev != NULL, "invariant");126if (next == NULL) {127assert(tail() == node, "tail error");128T** lt = list_tail();129*lt = prev;130assert(tail() == prev, "invariant");131} else {132next->set_prev(prev);133}134prev->set_next(next);135}136--_count;137assert(!in_list(node), "still in list error");138return node;139}140141template <typename T>142T* JfrDoublyLinkedList<T>::clear(bool return_tail /* false */) {143T* const node = return_tail ? tail() : head();144T** l = list_head();145*l = NULL;146l = list_tail();147*l = NULL;148_count = 0;149assert(head() == NULL, "invariant");150assert(tail() == NULL, "invariant");151return node;152}153154template <typename T>155bool JfrDoublyLinkedList<T>::locate(const T* node, const T* const target) const {156assert(target != NULL, "invariant");157while (node != NULL) {158if (node == target) {159return true;160}161node = (T*)node->next();162}163return false;164}165166template <typename T>167bool JfrDoublyLinkedList<T>::in_list(const T* const target) const {168assert(target != NULL, "invariant");169return locate(head(), target);170}171172template <typename T>173inline void validate_count_param(T* node, size_t count_param) {174assert(node != NULL, "invariant");175size_t count = 0;176while (node) {177++count;178node = (T*)node->next();179}180assert(count_param == count, "invariant");181}182183template <typename T>184void JfrDoublyLinkedList<T>::append_list(T* const head_node, T* const tail_node, size_t count) {185assert(head_node != NULL, "invariant");186assert(!in_list(head_node), "already in list error");187assert(tail_node != NULL, "invariant");188assert(!in_list(tail_node), "already in list error");189assert(tail_node->next() == NULL, "invariant");190// ensure passed in list nodes are connected191assert(locate(head_node, tail_node), "invariant");192T** lt = list_tail();193if (*lt != NULL) {194head_node->set_prev(*lt);195(*lt)->set_next(head_node);196} else {197// no head198assert(*lt == NULL, "invariant");199T** lh = list_head();200assert(*lh == NULL, "invariant");201head_node->set_prev(NULL);202*lh = head_node;203assert(head() == head_node, "invariant");204}205*lt = tail_node;206const T* node = head_node;207debug_only(validate_count_param(node, count);)208_count += count;209assert(tail() == tail_node, "invariant");210assert(in_list(tail_node), "not in list error");211assert(in_list(head_node), "not in list error");212}213214#endif // SHARE_JFR_UTILITIES_JFRDOUBLYLINKEDLIST_HPP215216217