xref: /aosp_15_r20/external/deqp/framework/delibs/decpp/deAppendList.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements C++ Base Library
3  * -----------------------------
4  *
5  * Copyright 2015 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Fast ordered append-only container
22  *//*--------------------------------------------------------------------*/
23 
24 #include "deAppendList.hpp"
25 #include "deThread.hpp"
26 #include "deSpinBarrier.hpp"
27 #include "deSharedPtr.hpp"
28 
29 #include <vector>
30 #include <algorithm>
31 
32 namespace de
33 {
34 
35 namespace
36 {
37 
38 using std::vector;
39 
40 struct TestElem
41 {
42     uint32_t threadNdx;
43     uint32_t elemNdx;
44 
TestElemde::__anon367df1c80111::TestElem45     TestElem(uint32_t threadNdx_, uint32_t elemNdx_) : threadNdx(threadNdx_), elemNdx(elemNdx_)
46     {
47     }
48 
TestElemde::__anon367df1c80111::TestElem49     TestElem(void) : threadNdx(0), elemNdx(0)
50     {
51     }
52 };
53 
54 struct SharedState
55 {
56     uint32_t numElements;
57     SpinBarrier barrier;
58     AppendList<TestElem> testList;
59 
SharedStatede::__anon367df1c80111::SharedState60     SharedState(uint32_t numThreads, uint32_t numElements_, uint32_t numElementsHint)
61         : numElements(numElements_)
62         , barrier(numThreads)
63         , testList(numElementsHint)
64     {
65     }
66 };
67 
68 class TestThread : public Thread
69 {
70 public:
TestThread(SharedState * shared,uint32_t threadNdx)71     TestThread(SharedState *shared, uint32_t threadNdx) : m_shared(shared), m_threadNdx(threadNdx)
72     {
73     }
74 
run(void)75     void run(void)
76     {
77         const uint32_t syncPerElems = 10000;
78 
79         for (uint32_t elemNdx = 0; elemNdx < m_shared->numElements; elemNdx++)
80         {
81             if (elemNdx % syncPerElems == 0)
82                 m_shared->barrier.sync(SpinBarrier::WAIT_MODE_AUTO);
83 
84             m_shared->testList.append(TestElem(m_threadNdx, elemNdx));
85         }
86     }
87 
88 private:
89     SharedState *const m_shared;
90     const uint32_t m_threadNdx;
91 };
92 
93 typedef SharedPtr<TestThread> TestThreadSp;
94 
runAppendListTest(uint32_t numThreads,uint32_t numElements,uint32_t numElementsHint)95 void runAppendListTest(uint32_t numThreads, uint32_t numElements, uint32_t numElementsHint)
96 {
97     SharedState sharedState(numThreads, numElements, numElementsHint);
98     vector<TestThreadSp> threads(numThreads);
99 
100     for (uint32_t threadNdx = 0; threadNdx < numThreads; ++threadNdx)
101     {
102         threads[threadNdx] = TestThreadSp(new TestThread(&sharedState, threadNdx));
103         threads[threadNdx]->start();
104     }
105 
106     for (uint32_t threadNdx = 0; threadNdx < numThreads; ++threadNdx)
107         threads[threadNdx]->join();
108 
109     DE_TEST_ASSERT(sharedState.testList.size() == (size_t)numElements * (size_t)numThreads);
110 
111     {
112         vector<uint32_t> countByThread(numThreads);
113 
114         std::fill(countByThread.begin(), countByThread.end(), 0);
115 
116         for (AppendList<TestElem>::const_iterator elemIter = sharedState.testList.begin();
117              elemIter != sharedState.testList.end(); ++elemIter)
118         {
119             const TestElem &elem = *elemIter;
120 
121             DE_TEST_ASSERT(de::inBounds(elem.threadNdx, 0u, numThreads));
122             DE_TEST_ASSERT(countByThread[elem.threadNdx] == elem.elemNdx);
123 
124             countByThread[elem.threadNdx] += 1;
125         }
126 
127         for (uint32_t threadNdx = 0; threadNdx < numThreads; ++threadNdx)
128             DE_TEST_ASSERT(countByThread[threadNdx] == numElements);
129     }
130 }
131 
132 class ObjCountElem
133 {
134 public:
ObjCountElem(int * liveCount)135     ObjCountElem(int *liveCount) : m_liveCount(liveCount)
136     {
137         *m_liveCount += 1;
138     }
139 
~ObjCountElem(void)140     ~ObjCountElem(void)
141     {
142         *m_liveCount -= 1;
143     }
144 
ObjCountElem(const ObjCountElem & other)145     ObjCountElem(const ObjCountElem &other) : m_liveCount(other.m_liveCount)
146     {
147         *m_liveCount += 1;
148     }
149 
operator =(const ObjCountElem & other)150     ObjCountElem &operator=(const ObjCountElem &other)
151     {
152         m_liveCount = other.m_liveCount;
153         *m_liveCount += 1;
154         return *this;
155     }
156 
157 private:
158     int *m_liveCount;
159 };
160 
runClearTest(uint32_t numElements1,uint32_t numElements2,uint32_t numElementsHint)161 void runClearTest(uint32_t numElements1, uint32_t numElements2, uint32_t numElementsHint)
162 {
163     int liveCount = 0;
164 
165     {
166         de::AppendList<ObjCountElem> testList(numElementsHint);
167 
168         for (uint32_t ndx = 0; ndx < numElements1; ++ndx)
169             testList.append(ObjCountElem(&liveCount));
170 
171         DE_TEST_ASSERT(liveCount == (int)numElements1);
172 
173         testList.clear();
174 
175         DE_TEST_ASSERT(liveCount == 0);
176 
177         for (uint32_t ndx = 0; ndx < numElements2; ++ndx)
178             testList.append(ObjCountElem(&liveCount));
179 
180         DE_TEST_ASSERT(liveCount == (int)numElements2);
181     }
182 
183     DE_TEST_ASSERT(liveCount == 0);
184 }
185 
186 } // namespace
187 
AppendList_selfTest(void)188 void AppendList_selfTest(void)
189 {
190     // Single-threaded
191     runAppendListTest(1, 1000, 500);
192     runAppendListTest(1, 1000, 2000);
193     runAppendListTest(1, 35, 1);
194 
195     // Multi-threaded
196     runAppendListTest(2, 10000, 500);
197     runAppendListTest(2, 100, 10);
198 
199     if (deGetNumAvailableLogicalCores() >= 4)
200     {
201         runAppendListTest(4, 10000, 500);
202         runAppendListTest(4, 100, 10);
203     }
204 
205     // Dtor + clear()
206     runClearTest(1, 1, 1);
207     runClearTest(1, 2, 10);
208     runClearTest(50, 25, 10);
209     runClearTest(9, 50, 10);
210     runClearTest(10, 50, 10);
211     runClearTest(50, 9, 10);
212     runClearTest(50, 10, 10);
213 }
214 
215 } // namespace de
216