Blender  V3.3
BLI_linklist_lockfree_test.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0 */
2 
3 #include "testing/testing.h"
4 
5 #include "MEM_guardedalloc.h"
6 
8 #include "BLI_task.h"
9 #include "BLI_threads.h"
10 #include "BLI_utildefines.h"
11 
13 {
14  LockfreeLinkList list;
16  EXPECT_EQ(list.head, &list.dummy_node);
17  EXPECT_EQ(list.tail, &list.dummy_node);
18  BLI_linklist_lockfree_free(&list, nullptr);
19 }
20 
21 TEST(LockfreeLinkList, InsertSingle)
22 {
23  LockfreeLinkList list;
27  EXPECT_EQ(list.head, &list.dummy_node);
28  EXPECT_EQ(list.head->next, &node);
29  EXPECT_EQ(list.tail, &node);
30  BLI_linklist_lockfree_free(&list, nullptr);
31 }
32 
33 TEST(LockfreeLinkList, InsertMultiple)
34 {
35  static const int nodes_num = 128;
36  LockfreeLinkList list;
37  LockfreeLinkNode nodes[nodes_num];
39  /* Insert all the nodes. */
40  for (LockfreeLinkNode &node : nodes) {
42  }
43  /* Check head and tail. */
44  EXPECT_EQ(list.head, &list.dummy_node);
45  EXPECT_EQ(list.tail, &nodes[nodes_num - 1]);
46  /* Check rest of the nodes. */
47  int node_index = 0;
48  for (LockfreeLinkNode *node = BLI_linklist_lockfree_begin(&list); node != nullptr;
49  node = node->next, ++node_index) {
50  EXPECT_EQ(node, &nodes[node_index]);
51  if (node_index != nodes_num - 1) {
52  EXPECT_EQ(node->next, &nodes[node_index + 1]);
53  }
54  }
55  /* Free list. */
56  BLI_linklist_lockfree_free(&list, nullptr);
57 }
58 
59 namespace {
60 
61 struct IndexedNode {
62  IndexedNode *next;
63  int index;
64 };
65 
66 void concurrent_insert(TaskPool *__restrict pool, void *taskdata)
67 {
69  CHECK_NOTNULL(list);
70  IndexedNode *node = (IndexedNode *)MEM_mallocN(sizeof(IndexedNode), "test node");
71  node->index = POINTER_AS_INT(taskdata);
73 }
74 
75 } // namespace
76 
77 TEST(LockfreeLinkList, InsertMultipleConcurrent)
78 {
79  static const int nodes_num = 655360;
80  /* Initialize list. */
81  LockfreeLinkList list;
83  /* Initialize task scheduler and pool. */
85  /* Push tasks to the pool. */
86  for (int i = 0; i < nodes_num; ++i) {
87  BLI_task_pool_push(pool, concurrent_insert, POINTER_FROM_INT(i), false, nullptr);
88  }
89  /* Run all the tasks. */
91  /* Verify we've got all the data properly inserted. */
92  EXPECT_EQ(list.head, &list.dummy_node);
93  bool *visited_nodes = (bool *)MEM_callocN(sizeof(bool) * nodes_num, "visited nodes");
94  /* First, we make sure that none of the nodes are added twice. */
95  for (LockfreeLinkNode *node_v = BLI_linklist_lockfree_begin(&list); node_v != nullptr;
96  node_v = node_v->next) {
97  IndexedNode *node = (IndexedNode *)node_v;
98  EXPECT_GE(node->index, 0);
99  EXPECT_LT(node->index, nodes_num);
100  EXPECT_FALSE(visited_nodes[node->index]);
101  visited_nodes[node->index] = true;
102  }
103  /* Then we make sure node was added. */
104  for (int node_index = 0; node_index < nodes_num; ++node_index) {
105  EXPECT_TRUE(visited_nodes[node_index]);
106  }
107  MEM_freeN(visited_nodes);
108  /* Cleanup data. */
111 }
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
@ TASK_PRIORITY_HIGH
Definition: BLI_task.h:57
void * BLI_task_pool_user_data(TaskPool *pool)
Definition: task_pool.cc:525
void BLI_task_pool_work_and_wait(TaskPool *pool)
Definition: task_pool.cc:480
TaskPool * BLI_task_pool_create_suspended(void *userdata, eTaskPriority priority)
Definition: task_pool.cc:417
void BLI_task_pool_free(TaskPool *pool)
Definition: task_pool.cc:440
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
Definition: task_pool.cc:459
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
Read Guarded memory(de)allocation.
OperationNode * node
#define CHECK_NOTNULL(expression)
Definition: log.h:43
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
static ulong * next
struct LockfreeLinkNode * next