| /* |
| * Copyright (c) 2020, 2023, 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_JFR_UTILITIES_JFREPOCHQUEUE_INLINE_HPP |
| #define SHARE_JFR_UTILITIES_JFREPOCHQUEUE_INLINE_HPP |
| |
| #include "jfr/utilities/jfrEpochQueue.hpp" |
| #include "jfr/recorder/storage/jfrEpochStorage.inline.hpp" |
| #include "jfr/recorder/storage/jfrStorageUtils.inline.hpp" |
| #include "runtime/javaThread.hpp" |
| |
| template <template <typename> class ElementPolicy> |
| JfrEpochQueue<ElementPolicy>::JfrEpochQueue() : _storage(nullptr) {} |
| |
| template <template <typename> class ElementPolicy> |
| JfrEpochQueue<ElementPolicy>::~JfrEpochQueue() { |
| delete _storage; |
| } |
| |
| template <template <typename> class ElementPolicy> |
| bool JfrEpochQueue<ElementPolicy>::initialize(size_t min_buffer_size, size_t free_list_cache_count_limit, size_t cache_prealloc_count) { |
| assert(_storage == nullptr, "invariant"); |
| _storage = new JfrEpochStorage(); |
| return _storage != nullptr && _storage->initialize(min_buffer_size, free_list_cache_count_limit, cache_prealloc_count); |
| } |
| |
| template <template <typename> class ElementPolicy> |
| inline typename JfrEpochQueue<ElementPolicy>::BufferPtr |
| JfrEpochQueue<ElementPolicy>::renew(size_t size, Thread* thread) { |
| assert(thread != nullptr, "invariant"); |
| BufferPtr buffer = this->thread_local_storage(thread); |
| if (buffer != nullptr) { |
| _storage->release(buffer); |
| } |
| buffer = _storage->acquire(size, thread); |
| assert(buffer != nullptr, "invariant"); |
| assert(buffer->free_size() >= size, "invariant"); |
| this->set_thread_local_storage(buffer, thread); |
| assert(this->thread_local_storage(thread) == buffer, "invariant"); |
| return buffer; |
| } |
| |
| template <template <typename> class ElementPolicy> |
| inline typename JfrEpochQueue<ElementPolicy>::BufferPtr |
| JfrEpochQueue<ElementPolicy>::storage_for_element(JfrEpochQueue<ElementPolicy>::TypePtr t, size_t element_size) { |
| assert(this->element_size(t) == element_size, "invariant"); |
| Thread* const thread = Thread::current(); |
| BufferPtr buffer = this->thread_local_storage(thread); |
| if (buffer == nullptr) { |
| buffer = _storage->acquire(element_size, thread); |
| this->set_thread_local_storage(buffer, thread); |
| } else if (buffer->free_size() < element_size) { |
| _storage->release(buffer); |
| buffer = _storage->acquire(element_size, thread); |
| this->set_thread_local_storage(buffer, thread); |
| } |
| assert(buffer->free_size() >= element_size, "invariant"); |
| assert(this->thread_local_storage(thread) == buffer, "invariant"); |
| return buffer; |
| } |
| |
| template <template <typename> class ElementPolicy> |
| void JfrEpochQueue<ElementPolicy>::enqueue(JfrEpochQueue<ElementPolicy>::TypePtr t) { |
| assert(t != nullptr, "invariant"); |
| size_t element_size = this->element_size(t); |
| BufferPtr buffer = storage_for_element(t, element_size); |
| assert(buffer != nullptr, "invariant"); |
| this->store_element(t, buffer); |
| buffer->set_pos(element_size); |
| } |
| |
| template <template <typename> class ElementPolicy> |
| template <typename Callback> |
| JfrEpochQueue<ElementPolicy>::ElementDispatch<Callback>::ElementDispatch(Callback& callback, JfrEpochQueue<ElementPolicy>& queue) : |
| _callback(callback), _queue(queue) {} |
| |
| template <template <typename> class ElementPolicy> |
| template <typename Callback> |
| size_t JfrEpochQueue<ElementPolicy>::ElementDispatch<Callback>::operator()(const u1* element, bool previous_epoch) { |
| assert(element != nullptr, "invariant"); |
| return _queue(element, _callback, previous_epoch); |
| } |
| |
| template <template <typename> class ElementPolicy> |
| template <typename Callback> |
| void JfrEpochQueue<ElementPolicy>::iterate(Callback& callback, bool previous_epoch) { |
| typedef ElementDispatch<Callback> ElementDispatcher; |
| typedef EpochDispatchOp<ElementDispatcher> QueueDispatcher; |
| ElementDispatcher element_dispatcher(callback, *this); |
| QueueDispatcher dispatch(element_dispatcher, previous_epoch); |
| _storage->iterate(dispatch, previous_epoch); |
| DEBUG_ONLY(_storage->verify_previous_empty();) |
| } |
| |
| #endif // SHARE_JFR_UTILITIES_JFREPOCHQUEUE_INLINE_HPP |