Skip to content
This repository was archived by the owner on Aug 27, 2022. It is now read-only.
/ lanai Public archive

Commit b08595d

Browse files
author
Xin Liu
committedFeb 26, 2020
8239066: make LinkedList<T> more generic
Reviewed-by: phh, simonis
1 parent dd393fa commit b08595d

File tree

2 files changed

+118
-12
lines changed

2 files changed

+118
-12
lines changed
 

‎src/hotspot/share/utilities/linkedlist.hpp

+40-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,25 @@ template <class E> class LinkedListNode : public ResourceObj {
4040
E _data; // embedded content
4141
LinkedListNode<E>* _next; // next entry
4242

43+
// Select member function 'bool U::equals(const U&) const' if 'U' is of class
44+
// type. This works because of the "Substitution Failure Is Not An Error"
45+
// (SFINAE) rule. Notice that this version of 'equal' will also be chosen for
46+
// class types which don't define a corresponding 'equals()' method (and will
47+
// result in a compilation error for them). It is not easily possible to
48+
// specialize this 'equal()' function exclusively for class types which define
49+
// the correct 'equals()' function because that function can be in a base
50+
// class, a dependent base class or have a compatible but slightly different
51+
// signature.
52+
template <class U>
53+
static bool equal(const U& a, const U& b, bool (U::*t)(const U&) const) {
54+
return a.equals(b);
55+
}
56+
57+
template <class U>
58+
static bool equal(const U& a, const U& b, ...) {
59+
return a == b;
60+
}
61+
4362
protected:
4463
LinkedListNode() : _next(NULL) { }
4564

@@ -51,6 +70,10 @@ template <class E> class LinkedListNode : public ResourceObj {
5170

5271
E* data() { return &_data; }
5372
const E* peek() const { return &_data; }
73+
74+
bool equals(const E& t) const {
75+
return equal<E>(_data, t, NULL);
76+
}
5477
};
5578

5679
// A linked list interface. It does not specify
@@ -59,9 +82,11 @@ template <class E> class LinkedListNode : public ResourceObj {
5982
template <class E> class LinkedList : public ResourceObj {
6083
protected:
6184
LinkedListNode<E>* _head;
85+
NONCOPYABLE(LinkedList<E>);
6286

6387
public:
6488
LinkedList() : _head(NULL) { }
89+
virtual ~LinkedList() {}
6590

6691
inline void set_head(LinkedListNode<E>* h) { _head = h; }
6792
inline LinkedListNode<E>* head() const { return _head; }
@@ -182,7 +207,7 @@ template <class E, ResourceObj::allocation_type T = ResourceObj::C_HEAP,
182207

183208
virtual LinkedListNode<E>* find_node(const E& e) {
184209
LinkedListNode<E>* p = this->head();
185-
while (p != NULL && !p->peek()->equals(e)) {
210+
while (p != NULL && !p->equals(e)) {
186211
p = p->next();
187212
}
188213
return p;
@@ -229,7 +254,7 @@ template <class E, ResourceObj::allocation_type T = ResourceObj::C_HEAP,
229254
LinkedListNode<E>* prev = NULL;
230255

231256
while (tmp != NULL) {
232-
if (tmp->peek()->equals(e)) {
257+
if (tmp->equals(e)) {
233258
return remove_after(prev);
234259
}
235260
prev = tmp;
@@ -401,16 +426,21 @@ template <class E, int (*FUNC)(const E&, const E&),
401426
// Iterates all entries in the list
402427
template <class E> class LinkedListIterator : public StackObj {
403428
private:
404-
LinkedListNode<E>* _p;
405-
bool _is_empty;
429+
mutable LinkedListNode<E>* _p;
430+
406431
public:
407-
LinkedListIterator(LinkedListNode<E>* head) : _p(head) {
408-
_is_empty = (head == NULL);
409-
}
432+
LinkedListIterator(LinkedListNode<E>* head) : _p(head) {}
433+
434+
bool is_empty() const { return _p == NULL; }
410435

411-
bool is_empty() const { return _is_empty; }
436+
E* next() {
437+
if (_p == NULL) return NULL;
438+
E* e = _p->data();
439+
_p = _p->next();
440+
return e;
441+
}
412442

413-
const E* next() {
443+
const E* next() const {
414444
if (_p == NULL) return NULL;
415445
const E* e = _p->peek();
416446
_p = _p->next();

‎test/hotspot/gtest/utilities/test_linkedlist.cpp

+78-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -58,7 +58,7 @@ static void check_list_values(const int* expected, const LinkedList<Integer>* li
5858
}
5959
}
6060

61-
const Integer one(1), two(2), three(3), four(4), five(5), six(6);
61+
const Integer one(1), two(2), three(3), four(4), five(5), six(6), notfound(404);
6262

6363
// Test regular linked list
6464
TEST(LinkedList, simple) {
@@ -85,6 +85,82 @@ TEST(LinkedList, simple) {
8585
check_list_values(expected, &ll);
8686
}
8787

88+
TEST(LinkedList, generic) {
89+
LinkedListImpl<int> il;
90+
const int N = 100;
91+
for (int i=0; i<N; ++i) {
92+
il.add(i);
93+
}
94+
EXPECT_EQ(il.size(), (size_t)N);
95+
96+
const LinkedListIterator<int> cit(il.head());
97+
for (int i=N-1; i>=0; --i) {
98+
const int* e = cit.next();
99+
EXPECT_EQ(*e, i);
100+
}
101+
EXPECT_TRUE(cit.is_empty());
102+
EXPECT_EQ(il.size(), (size_t)N);
103+
EXPECT_EQ(*(il.head()->peek()), N-1);
104+
105+
typedef LinkedListImpl<Integer, ResourceObj::C_HEAP, mtTest> list_t;
106+
LinkedList<Integer>* list = new(ResourceObj::C_HEAP, mtTest) list_t();
107+
list->add(Integer(1));
108+
list->add(Integer(2));
109+
EXPECT_EQ(list->size(), (size_t)2);
110+
list->~LinkedList<Integer>();
111+
EXPECT_EQ(list->size(), (size_t)0);
112+
113+
// copyable
114+
//list_t a;
115+
//a.add(Integer(1));
116+
//list_t b(a);
117+
//EXPECT_EQ(b.size(), (size_t)1);
118+
//EXPECT_TRUE(b.head()->peek()->equals(Integer(1)));
119+
120+
list_t lifo, dummy;
121+
const Integer* e;
122+
lifo.add(one);
123+
lifo.add(two);
124+
LinkedListIterator<Integer> it(lifo.head());
125+
126+
EXPECT_FALSE(it.is_empty());
127+
// pop 2
128+
e = it.next();
129+
EXPECT_TRUE(e->equals(two));
130+
EXPECT_FALSE(it.is_empty());
131+
// pop 1
132+
e = it.next();
133+
EXPECT_TRUE(e->equals(one));
134+
//empty
135+
EXPECT_TRUE(it.is_empty());
136+
137+
LinkedListIterator<Integer> it2(dummy.head());
138+
EXPECT_TRUE(it2.is_empty());
139+
EXPECT_EQ(it2.next(), (Integer* )NULL);
140+
}
141+
142+
TEST(LinkedList, algorithm) {
143+
LinkedListImpl<int> il;
144+
il.add(1);
145+
il.add(2);
146+
il.add(3);
147+
EXPECT_EQ(*il.find(1), 1);
148+
EXPECT_EQ(il.find(404), (int* )NULL);
149+
EXPECT_TRUE(il.remove(1));
150+
EXPECT_FALSE(il.remove(404));
151+
152+
LinkedListImpl<Integer, ResourceObj::C_HEAP, mtTest> ll;
153+
ll.add(one);
154+
155+
EXPECT_TRUE(ll.find(one));
156+
EXPECT_FALSE(ll.find(notfound));
157+
158+
EXPECT_TRUE(ll.remove(one));
159+
EXPECT_FALSE(ll.find(one));
160+
EXPECT_FALSE(ll.remove(notfound));
161+
EXPECT_FALSE(ll.find(notfound));
162+
}
163+
88164
// Test sorted linked list
89165
TEST(SortedLinkedList, simple) {
90166
LinkedListImpl<Integer, ResourceObj::C_HEAP, mtTest> ll;

0 commit comments

Comments
 (0)
This repository has been archived.