| /* |
| * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. |
| * Copyright (c) 2020 SAP SE. 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 GTEST_METASPACE_METASPACEGTESTSPARSEARRAY_HPP |
| #define GTEST_METASPACE_METASPACEGTESTSPARSEARRAY_HPP |
| |
| #include "memory/allocation.hpp" |
| #include "runtime/os.hpp" |
| #include "utilities/debug.hpp" |
| #include "metaspaceGtestCommon.hpp" |
| #include "metaspaceGtestRangeHelpers.hpp" |
| |
| /////// SparseArray<T> //////////////// |
| |
| // Throughout these tests we need to keep track of allocated items (ranges of metaspace memory, metachunks, ..) |
| // and be able to random-access them. Makes sense to have a helper for that. |
| template <class T> |
| class SparseArray : public StackObj { |
| |
| T* const _slots; |
| const int _num; |
| |
| // For convenience: a range covering all possible slot indices. |
| const IntRange _index_range; |
| |
| bool contains(int index) const { |
| return _index_range.contains(index); |
| } |
| |
| // Check slot intex for oob |
| void check_index(int i) const { |
| assert(contains(i), "Sanity"); |
| } |
| |
| // Swap the content of two slots. |
| void swap(int i1, int i2) { |
| check_index(i1); |
| check_index(i2); |
| T tmp = _slots[i1]; |
| _slots[i1] = _slots[i2]; |
| _slots[i2] = tmp; |
| } |
| |
| enum condition_t { cond_null = 0, cond_non_null = 1, cond_dontcare = 2 }; |
| |
| // Helper for next_matching_slot |
| bool slot_matches(int slot, condition_t c) const { |
| switch(c) { |
| case cond_null: return _slots[slot] == NULL; |
| case cond_non_null: return _slots[slot] != NULL; |
| case cond_dontcare: return true; |
| } |
| ShouldNotReachHere(); |
| return false; |
| } |
| |
| // Starting at (including) index, find the next matching slot. Returns index or -1 if none found. |
| int next_matching_slot(int slot, condition_t c) const { |
| while(slot < _num) { |
| if (slot_matches(slot, c)) { |
| return slot; |
| } |
| slot++; |
| } |
| return -1; |
| } |
| |
| public: |
| |
| SparseArray(int num) : |
| _slots(NEW_C_HEAP_ARRAY(T, num, mtInternal)), |
| _num(num), |
| _index_range(num) |
| { |
| for (int i = 0; i < _num; i++) { |
| _slots[i] = NULL; |
| } |
| } |
| |
| ~SparseArray() { |
| FREE_C_HEAP_ARRAY(T, _slots); |
| } |
| |
| T at(int i) { return _slots[i]; } |
| const T at(int i) const { return _slots[i]; } |
| void set_at(int i, T e) { _slots[i] = e; } |
| |
| int size() const { return _num; } |
| |
| bool slot_is_null(int i) const { check_index(i); return _slots[i] == NULL; } |
| |
| DEBUG_ONLY(void check_slot_is_null(int i) const { assert(slot_is_null(i), "Slot %d is not null", i); }) |
| DEBUG_ONLY(void check_slot_is_not_null(int i) const { assert(!slot_is_null(i), "Slot %d is null", i); }) |
| |
| // Shuffle all elements randomly |
| void shuffle() { |
| for (int i = 0; i < _num; i++) { |
| swap(i, random_slot_index()); |
| } |
| } |
| |
| // Reverse elements |
| void reverse() { |
| for (int i = 0; i < _num / 2; i++) { |
| swap(i, _num - i); |
| } |
| } |
| |
| int first_slot() const { return 0; } |
| int next_slot(int index) const { return index == _index_range.highest() ? -1 : index + 1; } |
| |
| int first_non_null_slot() const { return next_matching_slot(0, cond_non_null); } |
| int next_non_null_slot(int index) const { return next_matching_slot(index + 1, cond_non_null); } |
| |
| int first_null_slot() const { return next_matching_slot(0, cond_null); } |
| int next_null_slot(int index) const { return next_matching_slot(index + 1, cond_null); } |
| |
| // Return a random slot index. |
| int random_slot_index() const { |
| return _index_range.random_value(); |
| } |
| |
| int random_non_null_slot_index() const { |
| int i = next_non_null_slot(_index_range.random_value()); |
| if (i == -1) { |
| i = first_non_null_slot(); |
| } |
| return i; |
| } |
| |
| int random_null_slot_index() const { |
| int i = next_null_slot(_index_range.random_value()); |
| if (i == -1) { |
| i = first_null_slot(); |
| } |
| return i; |
| } |
| |
| IntRange random_slot_range() const { |
| return _index_range.random_subrange(); |
| } |
| |
| }; |
| |
| #endif // GTEST_METASPACE_METASPACEGTESTSPARSEARRAY_HPP |
| |