Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/jfr/utilities/jfrDoublyLinkedList.hpp
38920 views
/*1* Copyright (c) 2016, 2018, 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_VM_JFR_UTILITIES_JFRDOUBLYLINKEDLIST_HPP25#define SHARE_VM_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);50debug_only(bool in_list(const T* const target_node) const;)51debug_only(bool 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(_count >= 0, "invariant");138assert(!in_list(node), "still in list error");139return node;140}141142template <typename T>143T* JfrDoublyLinkedList<T>::clear(bool return_tail /* false */) {144T* const node = return_tail ? tail() : head();145T** l = list_head();146*l = NULL;147l = list_tail();148*l = NULL;149_count = 0;150assert(head() == NULL, "invariant");151assert(tail() == NULL, "invariant");152return node;153}154155#ifdef ASSERT156template <typename T>157bool JfrDoublyLinkedList<T>::locate(const T* node, const T* const target) const {158assert(target != NULL, "invariant");159while (node != NULL) {160if (node == target) {161return true;162}163node = (T*)node->next();164}165return false;166}167168template <typename T>169bool JfrDoublyLinkedList<T>::in_list(const T* const target) const {170assert(target != NULL, "invariant");171return locate(head(), target);172}173174template <typename T>175inline void validate_count_param(T* node, size_t count_param) {176assert(node != NULL, "invariant");177size_t count = 0;178while (node) {179++count;180node = (T*)node->next();181}182assert(count_param == count, "invariant");183}184#endif // ASSERT185186template <typename T>187void JfrDoublyLinkedList<T>::append_list(T* const head_node, T* const tail_node, size_t count) {188assert(head_node != NULL, "invariant");189assert(!in_list(head_node), "already in list error");190assert(tail_node != NULL, "invariant");191assert(!in_list(tail_node), "already in list error");192assert(tail_node->next() == NULL, "invariant");193// ensure passed in list nodes are connected194assert(locate(head_node, tail_node), "invariant");195T** lt = list_tail();196if (*lt != NULL) {197head_node->set_prev(*lt);198(*lt)->set_next(head_node);199} else {200// no head201assert(*lt == NULL, "invariant");202T** lh = list_head();203assert(*lh == NULL, "invariant");204head_node->set_prev(NULL);205*lh = head_node;206assert(head() == head_node, "invariant");207}208*lt = tail_node;209const T* node = head_node;210debug_only(validate_count_param(node, count);)211_count += count;212assert(tail() == tail_node, "invariant");213assert(in_list(tail_node), "not in list error");214assert(in_list(head_node), "not in list error");215}216217#endif // SHARE_VM_JFR_UTILITIES_JFRDOUBLYLINKEDLIST_HPP218219220