--- /dev/null 2019-01-28 17:48:15.000000000 +0800 +++ new/src/share/vm/jfr/utilities/jfrRefCountPointer.hpp 2019-01-28 17:48:15.000000000 +0800 @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2017, 2019, 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_VM_JFR_UTILITIES_JFRREFCOUNTPOINTER_HPP +#define SHARE_VM_JFR_UTILITIES_JFRREFCOUNTPOINTER_HPP + +#include "jfr/utilities/jfrAllocation.hpp" +#include "runtime/atomic.hpp" + +template +class RefCountHandle { + template + friend class RefCountPointer; + private: + const T* _ptr; + + RefCountHandle(const T* ptr) : _ptr(ptr) { + assert(_ptr != NULL, "invariant"); + _ptr->add_ref(); + } + + public: + RefCountHandle() : _ptr(NULL) {} + + RefCountHandle(const RefCountHandle& rhs) : _ptr(rhs._ptr) { + if (_ptr != NULL) { + _ptr->add_ref(); + } + } + + ~RefCountHandle() { + if (_ptr != NULL) { + const T* temp = _ptr; + _ptr = NULL; + temp->remove_ref(); + } + } + + // The copy-and-swap idiom upholds reference counting semantics + void operator=(RefCountHandle rhs) { + const T* temp = rhs._ptr; + rhs._ptr = _ptr; + _ptr = temp; + } + + bool operator==(const RefCountHandle& rhs) const { + return _ptr == rhs._ptr; + } + + bool operator!=(const RefCountHandle& rhs) const { + return !operator==(rhs); + } + + bool valid() const { + return _ptr != NULL; + } + + const T & operator->() const { + return *_ptr; + } + + T& operator->() { + return *const_cast(_ptr); + } +}; + +class MultiThreadedRefCounter { + private: + mutable volatile int _refs; + public: + MultiThreadedRefCounter() : _refs(0) {} + + void inc() const { + Atomic::add(1, &_refs); + } + + bool dec() const { + return 0 == Atomic::add((-1), &_refs); + } + + int current() const { + return _refs; + } +}; + +template +class RefCountPointer : public JfrCHeapObj { + template + friend class RefCountHandle; + typedef RefCountHandle > RefHandle; + private: + const T* _ptr; + mutable RefCountImpl _refs; + + // disallow multiple copies + RefCountPointer(const RefCountPointer& rhs); + void operator=(const RefCountPointer& rhs); + + ~RefCountPointer() { + assert(_refs.current() == 0, "invariant"); + delete const_cast(_ptr); + } + + void add_ref() const { + _refs.inc(); + } + + void remove_ref() const { + if (_refs.dec()) { + delete this; + } + } + + RefCountPointer(const T* ptr) : _ptr(ptr), _refs() { + assert(_ptr != NULL, "invariant"); + } + + public: + const T* operator->() const { + return _ptr; + } + + T* operator->() { + return const_cast(_ptr); + } + + static RefHandle make(const T* ptr) { + assert(ptr != NULL, "invariant"); + return RefHandle(new RefCountPointer(ptr)); + } +}; + +#endif // SHARE_VM_JFR_UTILITIES_JFRREFCOUNTPOINTER_HPP