Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
FORMUS3IC_LAS3
/
embb
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
56a22c45
authored
Mar 31, 2015
by
Tobias Fuchs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
containers_cpp: split LLX/SCX into core implementation and convenience interface
parent
746bd2fc
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
246 additions
and
419 deletions
+246
-419
containers_cpp/include/embb/containers/internal/llx_scx-inl.h
+33
-77
containers_cpp/include/embb/containers/internal/llx_scx.h
+19
-252
containers_cpp/include/embb/containers/internal/multiword_ll_sc-inl.h
+145
-0
containers_cpp/include/embb/containers/multiword_ll_sc.h
+0
-0
containers_cpp/test/llx_scx_test.cc
+47
-84
containers_cpp/test/llx_scx_test.h
+0
-1
containers_cpp/test/main.cc
+1
-4
containers_cpp/test/multiset_test.h
+1
-1
No files found.
containers_cpp/include/embb/containers/internal/llx_scx-inl.h
View file @
56a22c45
...
...
@@ -31,8 +31,6 @@
#include <embb/base/thread.h>
#include <embb/base/atomic.h>
#include <embb/base/memory_allocation.h>
#include <vector>
#include <stdarg.h>
namespace
embb
{
namespace
containers
{
...
...
@@ -124,61 +122,7 @@ bool LlxScx<UserData, ValuePool>::TryLoadLinked(
}
template
<
typename
UserData
,
typename
ValuePool
>
bool
LlxScx
<
UserData
,
ValuePool
>::
TryLoadLinked
(
DataRecord_t
*
const
data_record
,
UserData
&
user_data
)
{
bool
finalized
;
return
TryLoadLinked
(
data_record
,
user_data
,
finalized
);
}
template
<
typename
UserData
,
typename
ValuePool
>
template
<
typename
FieldType
>
bool
LlxScx
<
UserData
,
ValuePool
>::
TryStoreConditional
(
embb
::
base
::
Atomic
<
FieldType
>
*
field
,
FieldType
value
,
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
linked_deps
,
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
finalize_deps
)
{
embb
::
base
::
Atomic
<
cas_t
>
*
cas_field
=
reinterpret_cast
<
embb
::
base
::
Atomic
<
cas_t
>
*>
(
field
);
cas_t
cas_value
=
static_cast
<
cas_t
>
(
value
);
return
TryStoreConditionalCAS
(
cas_field
,
cas_value
,
linked_deps
,
finalize_deps
);
}
template
<
typename
UserData
,
typename
ValuePool
>
template
<
typename
FieldType
>
bool
LlxScx
<
UserData
,
ValuePool
>::
TryStoreConditional
(
embb
::
base
::
Atomic
<
FieldType
*>
*
field
,
FieldType
*
value
,
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
linked_deps
,
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
finalize_deps
)
{
embb
::
base
::
Atomic
<
cas_t
>
*
cas_field
=
reinterpret_cast
<
embb
::
base
::
Atomic
<
cas_t
>
*>
(
field
);
cas_t
cas_value
=
reinterpret_cast
<
cas_t
>
(
value
);
return
TryStoreConditionalCAS
(
cas_field
,
cas_value
,
linked_deps
,
finalize_deps
);
}
template
<
typename
UserData
,
typename
ValuePool
>
template
<
typename
FieldType
>
bool
LlxScx
<
UserData
,
ValuePool
>::
TryStoreConditional
(
embb
::
base
::
Atomic
<
FieldType
>
*
field
,
FieldType
value
,
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
linked_deps
)
{
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
finalize_deps
(
0
);
return
TryStoreConditional
(
field
,
value
,
linked_deps
,
finalize_deps
);
}
template
<
typename
UserData
,
typename
ValuePool
>
template
<
typename
FieldType
>
bool
LlxScx
<
UserData
,
ValuePool
>::
TryStoreConditional
(
embb
::
base
::
Atomic
<
FieldType
*>
*
field
,
FieldType
*
value
,
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
linked_deps
)
{
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
finalize_deps
(
0
);
return
TryStoreConditional
(
field
,
value
,
linked_deps
,
finalize_deps
);
}
template
<
typename
UserData
,
typename
ValuePool
>
bool
LlxScx
<
UserData
,
ValuePool
>::
TryStoreConditionalCAS
(
embb
::
base
::
Atomic
<
cas_t
>
*
cas_field
,
cas_t
cas_value
,
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
linked_deps
,
...
...
@@ -193,28 +137,40 @@ bool LlxScx<UserData, ValuePool>::TryStoreConditionalCAS(
// any I_r was linearized.
unsigned
int
thread_id
=
ThreadId
();
// Let info_fields be a table in shared memory containing for each r in V,
// a copy of r's info value in this threads local table of LLX results:
// a copy of r's info value in this threads local table of LLX results.
// Will be freed in Help() once the SCX operation has been completed.
scx_op_list_t
*
info_fields
=
scx_record_list_pool_
.
Allocate
(
max_links_
);
if
(
info_fields
==
NULL
)
{
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Could not allocate SCX record list"
);
}
dr_list_t
::
const_iterator
it
;
dr_list_t
::
const_iterator
end
;
end
=
linked_deps
.
end
();
// for each r in linked_deps ...
// Copy SCX operation of all LLX results of link dependencies into a list.
// For each r in linked_deps ...
for
(
it
=
linked_deps
.
begin
();
it
!=
end
;
++
it
)
{
typedef
embb
::
containers
::
internal
::
FixedSizeList
<
LlxResult
>
llx_result_list
;
llx_result_list
::
iterator
l_it
=
thread_llx_results_
[
thread_id
]
->
begin
();
llx_result_list
::
iterator
l_end
=
thread_llx_results_
[
thread_id
]
->
end
();
llx_result_list
::
iterator
llx_result_it
;
llx_result_list
::
iterator
llx_result_end
;
llx_result_end
=
thread_llx_results_
[
thread_id
]
->
end
();
// Find LLX result of r in thread-local LLX results:
for
(;
l_it
!=
l_end
&&
l_it
->
data_record
!=
*
it
;
++
l_it
);
if
(
l_it
==
l_end
)
{
for
(
llx_result_it
=
thread_llx_results_
[
thread_id
]
->
begin
();
llx_result_it
!=
llx_result_end
&&
llx_result_it
->
data_record
!=
*
it
;
++
llx_result_it
);
if
(
llx_result_it
==
llx_result_end
)
{
// Missing LLX result for given linked data record, user did not
// load-link a data record this SCX depends on.
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Missing preceding LLX on a data record used
for SCX
"
);
"Missing preceding LLX on a data record used
as SCX dependency
"
);
}
// Copy SCX operation from LLX result of link dependency into list:
info_fields
->
PushBack
(
l_it
->
data_record
->
ScxInfo
().
Load
());
l
lx_result
_it
->
data_record
->
ScxInfo
().
Load
());
}
// Clear thread-local list of LLX results
thread_llx_results_
[
thread_id
]
->
clear
();
// Announce SCX operation. Lists linked_deps and finalize_dep are
// guaranteed to remain on the stack until this announced operation
...
...
@@ -267,24 +223,24 @@ bool LlxScx<UserData, ValuePool>::Help(
ScxRecord
<
DataRecord_t
>
*
rinfo_old
=
*
scx_op_it
;
// Try to freeze the data record by setting its SCX info field
// to this SCX operation description:
if
(
!
r
->
ScxInfo
().
CompareAndSwap
(
rinfo_old
,
scx
))
{
if
(
r
->
ScxInfo
().
CompareAndSwap
(
rinfo_old
,
scx
))
{
// Do not try to delete the sentinel scx record:
if
(
rinfo_old
!=
&
DataRecord_t
::
DummyScx
)
{
scx_record_list_pool_
.
Free
(
rinfo_old
->
scx_ops_
);
scx_record_pool_
.
Free
(
rinfo_old
);
}
}
else
{
if
(
r
->
ScxInfo
().
Load
()
!=
scx
)
{
// could not freeze r because it is frozen for another SCX:
if
(
scx
->
all_frozen_
)
{
// SCX already completed:
// SCX already completed
by any other thread
:
return
true
;
}
// Atomically unfreeze all nodes frozen for this SCX (see LLX):
scx
->
state_
=
ScxRecord_t
::
Aborted
;
return
false
;
}
}
else
{
// Do not try to delete the sentinel scx record:
if
(
rinfo_old
->
field_
!=
0
)
{
scx_record_list_pool_
.
Free
(
rinfo_old
->
scx_ops_
);
scx_record_pool_
.
Free
(
rinfo_old
);
}
}
}
}
// finished freezing data records
assert
(
scx
->
state_
==
ScxRecord_t
::
InProgress
||
...
...
@@ -313,7 +269,7 @@ bool LlxScx<UserData, ValuePool>::Help(
template
<
typename
UserData
>
LlxScxRecord
<
UserData
>::
LlxScxRecord
()
:
marked_for_finalize_
(
false
)
{
scx_op_
.
Store
(
&
dummy_s
cx
);
scx_op_
.
Store
(
&
DummyS
cx
);
}
template
<
typename
UserData
>
...
...
@@ -321,13 +277,13 @@ LlxScxRecord<UserData>::LlxScxRecord(
const
UserData
&
user_data
)
:
user_data_
(
user_data
),
marked_for_finalize_
(
false
)
{
scx_op_
.
Store
(
&
dummy_s
cx
);
scx_op_
.
Store
(
&
DummyS
cx
);
}
template
<
typename
UserData
>
ScxRecord
<
LlxScxRecord
<
UserData
>
>
LlxScxRecord
<
UserData
>::
dummy_scx
=
ScxRecord
<
LlxScxRecord
<
UserData
>
>
();
LlxScxRecord
<
UserData
>::
DummyScx
=
ScxRecord
<
LlxScxRecord
<
UserData
>
>
();
}
// namespace internal
}
// namespace containers
...
...
containers_cpp/include/embb/containers/internal/llx_scx.h
View file @
56a22c45
This diff is collapsed.
Click to expand it.
containers_cpp/include/embb/containers/internal/multiword_ll_sc-inl.h
0 → 100644
View file @
56a22c45
/*
* Copyright (c) 2014, Siemens AG. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef EMBB_CONTAINERS_INTERNAL_MULTIWORD_LL_SC_INL_H_
#define EMBB_CONTAINERS_INTERNAL_MULTIWORD_LL_SC_INL_H_
#include <embb/containers/internal/multiword_ll_sc-inl.h>
#include <embb/containers/internal/fixed_size_list.h>
#include <embb/base/thread.h>
#include <embb/base/atomic.h>
namespace
embb
{
namespace
containers
{
namespace
internal
{
template
<
typename
UserData
,
typename
ValuePool
>
MultiwordLLSC
<
UserData
,
ValuePool
>::
MultiwordLLSC
(
size_t
max_links
)
:
llx_scx_
(
max_links
)
{
}
template
<
typename
UserData
,
typename
ValuePool
>
MultiwordLLSC
<
UserData
,
ValuePool
>::~
MultiwordLLSC
()
{
}
template
<
typename
UserData
,
typename
ValuePool
>
bool
MultiwordLLSC
<
UserData
,
ValuePool
>::
TryLoadLinked
(
DataRecord_t
*
const
data_record
,
UserData
&
user_data
,
bool
&
finalized
)
{
return
llx_scx_
.
TryLoadLinked
(
data_record
,
user_data
,
finalized
);
}
template
<
typename
UserData
,
typename
ValuePool
>
bool
MultiwordLLSC
<
UserData
,
ValuePool
>::
TryLoadLinked
(
DataRecord_t
*
const
data_record
,
UserData
&
user_data
)
{
bool
finalized
;
return
llx_scx_
.
TryLoadLinked
(
data_record
,
user_data
,
finalized
);
}
template
<
typename
UserData
,
typename
ValuePool
>
template
<
typename
FieldType
>
bool
MultiwordLLSC
<
UserData
,
ValuePool
>::
TryStoreConditional
(
Link
&
linked_dep
,
embb
::
base
::
Atomic
<
FieldType
>
*
field
,
FieldType
value
)
{
embb
::
containers
::
internal
::
FixedSizeList
<
Link
*>
linked_deps
(
1
);
linked_deps
.
PushBack
(
&
linked_dep
);
embb
::
containers
::
internal
::
FixedSizeList
<
Link
*>
finalize_deps
(
0
);
embb
::
base
::
Atomic
<
cas_t
>
*
cas_field
=
reinterpret_cast
<
embb
::
base
::
Atomic
<
cas_t
>
*>
(
field
);
cas_t
cas_value
=
ToCASValue
(
value
);
return
llx_scx_
.
TryStoreConditional
(
cas_field
,
cas_value
,
linked_deps
,
finalize_deps
);
}
template
<
typename
UserData
,
typename
ValuePool
>
template
<
typename
FieldType
>
bool
MultiwordLLSC
<
UserData
,
ValuePool
>::
TryStoreConditional
(
Link
&
linked_dep_1
,
Link
&
linked_dep_2
,
embb
::
base
::
Atomic
<
FieldType
>
*
field
,
FieldType
value
)
{
embb
::
containers
::
internal
::
FixedSizeList
<
Link
*>
linked_deps
(
2
);
linked_deps
.
PushBack
(
&
linked_dep_1
);
linked_deps
.
PushBack
(
&
linked_dep_2
);
embb
::
containers
::
internal
::
FixedSizeList
<
Link
*>
finalize_deps
(
0
);
embb
::
base
::
Atomic
<
cas_t
>
*
cas_field
=
reinterpret_cast
<
embb
::
base
::
Atomic
<
cas_t
>
*>
(
field
);
cas_t
cas_value
=
ToCASValue
(
value
);
return
llx_scx_
.
TryStoreConditional
(
cas_field
,
cas_value
,
linked_deps
,
finalize_deps
);
}
#if 0
template< typename UserData, typename ValuePool >
template< typename FieldType >
bool MultiwordLLSC<UserData, ValuePool>::TryStoreConditional(
embb::base::Atomic<FieldType> * field,
FieldType value,
embb::containers::internal::FixedSizeList<DataRecord_t *> & linked_deps) {
embb::containers::internal::FixedSizeList<DataRecord_t *> finalize_deps(0);
return TryStoreConditional(field, value, linked_deps, finalize_deps);
}
template< typename UserData, typename ValuePool >
template< typename FieldType >
bool MultiwordLLSC<UserData, ValuePool>::TryStoreConditional(
embb::base::Atomic<FieldType*> * field,
FieldType * value,
embb::containers::internal::FixedSizeList<DataRecord_t *> & linked_deps,
embb::containers::internal::FixedSizeList<DataRecord_t *> & finalize_deps) {
embb::base::Atomic<cas_t> * cas_field =
reinterpret_cast<embb::base::Atomic<cas_t> *>(field);
cas_t cas_value = reinterpret_cast<cas_t>(value);
return llx_scx_.TryStoreConditional(cas_field, cas_value, linked_deps, finalize_deps);
}
template< typename UserData, typename ValuePool >
template< typename FieldType >
bool MultiwordLLSC<UserData, ValuePool>::TryStoreConditional(
embb::base::Atomic<FieldType*> * field,
FieldType * value,
embb::containers::internal::FixedSizeList<DataRecord_t *> & linked_deps) {
embb::containers::internal::FixedSizeList<DataRecord_t *> finalize_deps(0);
return TryStoreConditional(field, value, linked_deps, finalize_deps);
}
#endif
template
<
typename
UserData
,
typename
ValuePool
>
bool
MultiwordLLSC
<
UserData
,
ValuePool
>::
TryValidateLink
(
const
DataRecord_t
&
field
)
{
return
llx_scx_
.
TryValidateLink
(
field
);
}
}
// namespace internal
}
// namespace containers
}
// namespace embb
#endif // EMBB_CONTAINERS_INTERNAL_MULTIWORD_LL_SC_INL_H_
containers_cpp/include/embb/containers/multiword_ll_sc.h
0 → 100644
View file @
56a22c45
This diff is collapsed.
Click to expand it.
containers_cpp/test/llx_scx_test.cc
View file @
56a22c45
...
...
@@ -27,6 +27,7 @@
#include <llx_scx_test.h>
#include <embb/containers/internal/fixed_size_list.h>
#include <embb/containers/internal/llx_scx.h>
// #include <embb/containers/multiword_ll_sc.h>
namespace
embb
{
namespace
containers
{
...
...
@@ -44,11 +45,11 @@ LlxScxTest::LlxScxTest() :
head
(
0
,
'-'
),
tail_llx
(
tail
),
head_llx
(
head
)
{
CreateUnit
(
"SerialArrayTest"
)
.
Add
(
&
LlxScxTest
::
SerialArrayTest
,
this
);
CreateUnit
(
"SerialListTest"
).
Add
(
&
LlxScxTest
::
SerialList
Test
,
this
);
//
CreateUnit("ParallelTest")
//
.Add(&LlxScxTest::ParallelTest, this)
//
.Post(&LlxScxTest::ParallelTestPost, this);
CreateUnit
(
"SerialArrayTest"
)
.
Add
(
&
LlxScxTest
::
SerialArray
Test
,
this
);
CreateUnit
(
"ParallelTest"
)
.
Add
(
&
LlxScxTest
::
ParallelTest
,
this
)
.
Post
(
&
LlxScxTest
::
ParallelTestPost
,
this
);
}
void
LlxScxTest
::
ParallelTest
()
{
...
...
@@ -56,7 +57,6 @@ void LlxScxTest::ParallelTest() {
int
return_val
=
embb_internal_thread_index
(
&
thread_index
);
if
(
return_val
!=
EMBB_SUCCESS
)
EMBB_THROW
(
embb
::
base
::
ErrorException
,
"Could not get thread id!"
);
// Threads try to append n nodes to a linked list in parallel
for
(
char
value
=
'a'
;
value
<=
'z'
;)
{
// Find node to append new element on:
...
...
@@ -67,25 +67,36 @@ void LlxScxTest::ParallelTest() {
next
=
next
->
Data
().
next_
;
}
Node
n
;
llxscx_
.
TryLoadLinked
(
node
,
n
);
bool
finalized
;
// LLX on node the new element will be appended to:
llxscx_
.
TryLoadLinked
(
node
,
n
,
finalized
);
if
(
n
.
next_
==
next
)
{
// Pointer still valid after LLX,
call SCX(node, node.next, new_node)
// Pointer still valid after LLX,
try to append new node
internal
::
FixedSizeList
<
LlxScxRecord
<
Node
>
*>
linked_deps
(
1
);
internal
::
FixedSizeList
<
LlxScxRecord
<
Node
>
*>
finalize_deps
(
0
);
linked_deps
.
PushBack
(
node
);
// Create new node:
Node
new_node
(
static_cast
<
int
>
(
thread_index
),
value
);
internal
::
LlxScxRecord
<
Node
>
*
new_node_ptr
=
new
internal
::
LlxScxRecord
<
Node
>
(
new_node
);
// Convert node pointer to size_t:
size_t
new_cas_value
=
reinterpret_cast
<
size_t
>
(
new_node_ptr
);
// Convert target field pointer to size_t*:
embb
::
base
::
Atomic
<
size_t
>
*
field_cas_ptr
=
reinterpret_cast
<
embb
::
base
::
Atomic
<
size_t
>
*
>
(
&
(
node
->
Data
().
next_
));
// Call SCX:
bool
element_inserted
=
llxscx_
.
TryStoreConditional
(
&
(
node
->
Data
().
next_
),
new_node_ptr
,
linked_deps
);
field_cas_ptr
,
new_cas_value
,
linked_deps
,
finalize_deps
);
if
(
element_inserted
)
{
// Value has been added to list, continue with next value
++
value
;
}
}
}
}
}
...
...
@@ -109,88 +120,40 @@ void LlxScxTest::SerialArrayTest() {
// a specialization for atomics that uses a.Store(b.Load()).
AtomicField
field
(
23
);
LlxScxRecord
<
Payload
>
*
my_list
=
new
LlxScxRecord
<
Payload
>
[
10
];
for
(
int
i
=
0
;
i
!=
10
;
++
i
)
{
my_list
[
i
]
=
i
;
}
LlxScxRecord
<
Payload
>
r1
(
100
);
LlxScxRecord
<
Payload
>
r2
(
200
);
LlxScxRecord
<
Payload
>
r3
(
300
);
Payload
l1
,
l2
;
PT_ASSERT
(
llxscx
.
TryLoadLinked
(
&
my_list
[
0
],
l1
));
PT_ASSERT
(
llxscx
.
TryLoadLinked
(
&
my_list
[
5
],
l2
));
Payload
l1
,
l2
,
l3
;
bool
finalized
;
PT_ASSERT
(
llxscx
.
TryLoadLinked
(
&
r1
,
l1
,
finalized
));
PT_ASSERT_EQ
(
100
,
l1
);
PT_ASSERT
(
llxscx
.
TryLoadLinked
(
&
r2
,
l2
,
finalized
));
PT_ASSERT_EQ
(
200
,
l2
);
PT_ASSERT
(
llxscx
.
TryLoadLinked
(
&
r3
,
l3
,
finalized
));
PT_ASSERT_EQ
(
300
,
l3
);
// links = { dr1, dr2, dr3 }
FixedSizeList
<
LlxScxRecord
<
Payload
>
*
>
links
(
2
);
links
.
PushBack
(
&
my_list
[
0
]);
links
.
PushBack
(
&
my_list
[
5
]);
links
(
3
);
links
.
PushBack
(
&
r1
);
links
.
PushBack
(
&
r2
);
links
.
PushBack
(
&
r3
);
FixedSizeList
<
LlxScxRecord
<
Payload
>
*
>
finalize_links
(
1
);
finalize_links
.
PushBack
(
&
r3
);
// Try to store new value depending on links:
size_t
a
=
42
;
PT_ASSERT
(
llxscx
.
TryStoreConditional
(
&
field
,
a
,
links
));
PT_ASSERT
(
llxscx
.
TryStoreConditional
(
&
field
,
a
,
links
,
finalize_links
));
// New value should have been changed successfully:
PT_ASSERT_EQ
(
field
.
Load
(),
a
);
}
void
LlxScxTest
::
SerialListTest
()
{
typedef
LlxScxTest
::
Node
Node
;
// Global:
LlxScx
<
Node
>
llxscx
(
3
);
// Multiset { a, b, b, c }
Node
n1
(
1
,
'a'
);
Node
n2
(
2
,
'b'
);
Node
n3
(
1
,
'c'
);
// V = { dr1, dr2, dr3 }
// R = { dr1, dr2 }
LlxScxRecord
<
Node
>
dr1
(
n1
);
LlxScxRecord
<
Node
>
dr2
(
n2
);
LlxScxRecord
<
Node
>
dr3
(
n3
);
dr1
->
next_
.
Store
(
&
dr2
);
dr2
->
next_
.
Store
(
&
dr3
);
// Thread-local:
Node
l1
,
l2
,
l3
;
bool
finalized
;
PT_ASSERT
(
llxscx
.
TryLoadLinked
(
&
dr1
,
l1
,
finalized
));
PT_ASSERT
(
!
finalized
);
PT_ASSERT_EQ
(
l1
.
value_
,
dr1
->
value_
);
PT_ASSERT
(
llxscx
.
TryLoadLinked
(
&
dr2
,
l2
,
finalized
));
PT_ASSERT
(
!
finalized
);
PT_ASSERT_EQ
(
l2
.
value_
,
dr2
->
value_
);
PT_ASSERT
(
llxscx
.
TryLoadLinked
(
&
dr3
,
l3
,
finalized
));
PT_ASSERT
(
!
finalized
);
PT_ASSERT_EQ
(
l3
.
value_
,
dr3
->
value_
);
FixedSizeList
<
LlxScxRecord
<
Node
>
*
>
linked_deps
(
3
);
linked_deps
.
PushBack
(
&
dr1
);
linked_deps
.
PushBack
(
&
dr2
);
linked_deps
.
PushBack
(
&
dr3
);
FixedSizeList
<
LlxScxRecord
<
Node
>
*
>
finalize_deps
(
2
);
finalize_deps
.
PushBack
(
&
dr2
);
finalize_deps
.
PushBack
(
&
dr3
);
typedef
LlxScxRecord
<
Node
>
*
field_t
;
LlxScxRecord
<
Node
>
new_node
(
n3
);
PT_ASSERT
(
llxscx
.
TryStoreConditional
(
&
n2
.
next_
,
// fld: field to update
&
new_node
,
// new value
linked_deps
,
// V: dependencies, must be LL'd before
finalize_deps
// R: Subsequence of V to be finalized
));
// Following LLX calls on finalized data records are
// expected to fail:
PT_ASSERT
(
!
llxscx
.
TryLoadLinked
(
&
dr2
,
l2
,
finalized
));
PT_ASSERT
(
finalized
);
PT_ASSERT
(
!
llxscx
.
TryLoadLinked
(
&
dr3
,
l3
,
finalized
));
PT_ASSERT
(
finalized
);
}
}
// namespace test
}
// namespace containers
}
// namespace embb
containers_cpp/test/llx_scx_test.h
View file @
56a22c45
...
...
@@ -89,7 +89,6 @@ class LlxScxTest : public partest::TestCase {
private
:
void
SerialArrayTest
();
void
SerialListTest
();
void
ParallelTest
();
void
ParallelTestPost
();
...
...
containers_cpp/test/main.cc
View file @
56a22c45
...
...
@@ -41,7 +41,6 @@
#include "./hazard_pointer_test.h"
#include "./object_pool_test.h"
#include "./llx_scx_test.h"
// #include "./multiset_test.h"
#define COMMA ,
...
...
@@ -58,7 +57,6 @@ using embb::containers::test::QueueTest;
using
embb
::
containers
::
test
::
StackTest
;
using
embb
::
containers
::
test
::
ObjectPoolTest
;
using
embb
::
containers
::
test
::
LlxScxTest
;
// using embb::containers::test::MultisetTest;
PT_MAIN
(
"Data Structures C++"
)
{
unsigned
int
max_threads
=
static_cast
<
unsigned
int
>
(
...
...
@@ -75,7 +73,6 @@ PT_MAIN("Data Structures C++") {
PT_RUN
(
ObjectPoolTest
<
LockFreeTreeValuePool
<
bool
COMMA
false
>
>
);
PT_RUN
(
ObjectPoolTest
<
WaitFreeArrayValuePool
<
bool
COMMA
false
>
>
);
PT_RUN
(
LlxScxTest
);
//PT_RUN(MultisetTest);
PT_EXPECT
(
embb_get_bytes_allocated
()
==
0
);
PT_EXPECT
_EQ
(
embb_get_bytes_allocated
(),
static_cast
<
size_t
>
(
0
)
);
}
containers_cpp/test/multiset_test.h
View file @
56a22c45
...
...
@@ -28,7 +28,7 @@
#define CONTAINERS_CPP_TEST_MULTISET_TEST_H_
#include <partest/partest.h>
#include <embb/containers/
primitives
/llx_scx.h>
#include <embb/containers/
internal
/llx_scx.h>
namespace
embb
{
namespace
containers
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment