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
fb4b4604
authored
Mar 27, 2015
by
Tobias Fuchs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
containers_cpp: added specialization of LLX/SCX for pointer types, added another simple unit test
parent
763326c7
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
339 additions
and
65 deletions
+339
-65
containers_cpp/include/embb/containers/internal/llx_scx-inl.h
+59
-30
containers_cpp/include/embb/containers/internal/llx_scx.h
+231
-20
containers_cpp/test/llx_scx_test.cc
+43
-10
containers_cpp/test/llx_scx_test.h
+6
-5
No files found.
containers_cpp/include/embb/containers/internal/
primitives/
llx_scx-inl.h
→
containers_cpp/include/embb/containers/internal/llx_scx-inl.h
View file @
fb4b4604
...
...
@@ -24,25 +24,19 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef EMBB_CONTAINERS_
PRIMITIVES
_LLX_SCX_INL_H_
#define EMBB_CONTAINERS_
PRIMITIVES
_LLX_SCX_INL_H_
#ifndef EMBB_CONTAINERS_
INTERNAL
_LLX_SCX_INL_H_
#define EMBB_CONTAINERS_
INTERNAL
_LLX_SCX_INL_H_
#include <embb/containers/
primitives
/llx_scx.h>
#include <embb/containers/
internal
/llx_scx.h>
#include <embb/base/thread.h>
#include <embb/base/atomic.h>
#include <embb/base/memory_allocation.h>
#include <vector>
#include <stdarg.h>
/**
* Implementation of the LX/STX primitive as presented in
* "Pragmatic Primitives for Non-blocking Data Structures"
* (Brown et al., 2013).
*/
namespace
embb
{
namespace
containers
{
namespace
primitives
{
namespace
internal
{
template
<
typename
UserData
,
typename
ValuePool
>
unsigned
int
LlxScx
<
UserData
,
ValuePool
>::
ThreadId
()
{
...
...
@@ -89,7 +83,7 @@ LlxScx<UserData, ValuePool>::~LlxScx() {
template
<
typename
UserData
,
typename
ValuePool
>
bool
LlxScx
<
UserData
,
ValuePool
>::
TryLoadLinked
(
DataRecord_t
*
const
data_record
,
DataRecord_t
&
user_data
,
UserData
&
user_data
,
bool
&
finalized
)
{
finalized
=
false
;
unsigned
int
thread_id
=
ThreadId
();
...
...
@@ -132,7 +126,7 @@ bool LlxScx<UserData, ValuePool>::TryLoadLinked(
template
<
typename
UserData
,
typename
ValuePool
>
bool
LlxScx
<
UserData
,
ValuePool
>::
TryLoadLinked
(
DataRecord_t
*
const
data_record
,
DataRecord_t
&
user_data
)
{
UserData
&
user_data
)
{
bool
finalized
;
return
TryLoadLinked
(
data_record
,
user_data
,
finalized
);
}
...
...
@@ -144,6 +138,51 @@ bool LlxScx<UserData, ValuePool>::TryStoreConditional(
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
,
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
finalize_deps
)
{
typedef
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
dr_list_t
;
typedef
embb
::
containers
::
internal
::
FixedSizeList
<
ScxRecord_t
*>
scx_op_list_t
;
// Preconditions:
...
...
@@ -184,11 +223,11 @@ bool LlxScx<UserData, ValuePool>::TryStoreConditional(
linked_deps
,
finalize_deps
,
// target field:
reinterpret_cast
<
embb
::
base
::
Atomic
<
cas_t
>
*>
(
field
)
,
cas_field
,
// new value:
reinterpret_cast
<
cas_t
>
(
value
)
,
cas_value
,
// old value:
reinterpret_cast
<
cas_t
>
(
field
->
Load
()
),
cas_field
->
Load
(
),
// linked SCX operations:
info_fields
,
// initial operation state:
...
...
@@ -199,16 +238,6 @@ bool LlxScx<UserData, ValuePool>::TryStoreConditional(
}
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
>::
TryValidateLink
(
const
DataRecord_t
&
field
)
{
return
true
;
// @TODO
...
...
@@ -233,7 +262,7 @@ LlxScxRecord<UserData>::LlxScxRecord(
// internal::ScxRecord
template
<
typename
DataRecord
>
bool
internal
::
ScxRecord
<
DataRecord
>::
Help
()
{
bool
ScxRecord
<
DataRecord
>::
Help
()
{
// We ensure that an SCX S does not change a data record
// while it is frozen for another SCX S'. Instead, S uses
// the information in the SCX record of S' to help S'
...
...
@@ -291,12 +320,12 @@ bool internal::ScxRecord<DataRecord>::Help() {
}
template
<
typename
UserData
>
internal
::
ScxRecord
<
LlxScxRecord
<
UserData
>
>
ScxRecord
<
LlxScxRecord
<
UserData
>
>
LlxScxRecord
<
UserData
>::
dummy_scx
=
internal
::
ScxRecord
<
LlxScxRecord
<
UserData
>
>
();
ScxRecord
<
LlxScxRecord
<
UserData
>
>
();
}
// namespace
primitives
}
// namespace
internal
}
// namespace containers
}
// namespace embb
#endif // EMBB_CONTAINERS_
PRIMITIVES
_LLX_SCX_INL_H_
#endif // EMBB_CONTAINERS_
INTERNAL
_LLX_SCX_INL_H_
containers_cpp/include/embb/containers/
primitives
/llx_scx.h
→
containers_cpp/include/embb/containers/
internal
/llx_scx.h
View file @
fb4b4604
...
...
@@ -24,8 +24,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef EMBB_CONTAINERS_
PRIMITIVES
_LLX_SCX_H_
#define EMBB_CONTAINERS_
PRIMITIVES
_LLX_SCX_H_
#ifndef EMBB_CONTAINERS_
INTERNAL
_LLX_SCX_H_
#define EMBB_CONTAINERS_
INTERNAL
_LLX_SCX_H_
#include <embb/base/thread.h>
#include <embb/base/atomic.h>
...
...
@@ -36,13 +36,177 @@
namespace
embb
{
namespace
containers
{
namespace
primitives
{
namespace
internal
{
#ifdef DOXYGEN
/**
* Wraps user-defined data with fields required for LLX/SCX algorithm.
* Mutable fields must each be contained in a single word.
*/
template
<
typename
UserData
>
class
LlxScxRecord
{
public
:
/**
* Default constructor.
*/
LlxScxRecord
();
/**
* Constructor. Creates an instance of \c DataRecord_t wrapping a user
* data object.
*/
LlxScxRecord
(
const
UserData
&
user_data
);
/**
* Copy constructor
*/
LlxScxRecord
(
const
LlxScxRecord
&
other
);
/**
* Assignment operator.
*/
LlxScxRecord
&
operator
=
(
const
LlxScxRecord
&
rhs
);
/**
* Destructor.
*/
~
LlxScxRecord
();
/**
* Returns user data payload of this LLX/SCX record
*/
UserData
&
Data
();
/**
* Allows pointer semantics, returns user data payload of this
* LLX/SCX record
*/
UserData
*
operator
*
();
/**
* Allows pointer semantics, returns user data payload of this
* LLX/SCX record
*/
UserData
*
operator
->
();
/**
* Whether this data record is marked for finalizing.
*/
bool
IsMarkedForFinalize
()
const
;
};
/**
* Multiword LL/SC
*
* Implementation of the LLX/STX primitive as presented in
* "Pragmatic Primitives for Non-blocking Data Structures"
* (Brown et al., 2013).
*
* \tparam UserData Type containing mutable fields
* \tparam ValuePool Type containing mutable fields
*/
template
<
typename
UserData
,
typename
ValuePool
=
embb
::
containers
::
LockFreeTreeValuePool
<
bool
,
false
>
>
class
LlxScx
{
public
:
/**
* Constructs a new instance of LlxScx.
*/
LlxScx
(
size_t
max_links
/**< [IN] Maximum number of links depending on a single SCX operation */
);
/**
* Destructor, frees memory.
*/
~
LlxScx
();
/**
* Tentatively performs an LLX (extended load-linked) operation on given
* LLX/SCX data record.
* Returns true and stores result in given reference variable on success,
* otherwise returns false.
*/
bool
TryLoadLinked
(
DataRecord_t
*
const
data_record
,
/**< [IN] Pointer to data record to load */
UserData
&
data
,
/**< [OUT] Atomic snapshot of data record */
bool
&
finalized
/**< [OUT] Indicating whether requested fields have been finalized */
);
/**
* Tentatively performs an LLX (extended load-linked) operation on given
* LLX/SCX data record.
* Returns true and stores result in given reference variable on success,
* otherwise returns false.
*/
bool
TryLoadLinked
(
DataRecord_t
*
const
data_record
,
/**< [IN] Pointer to data record to load */
UserData
&
data
/**< [OUT] Atomic snapshot of data record */
);
/**
* Tentatively performs a single-record Store-Conditional operation on
* given LLX/SCX data record.
* Returns true if the given value has been stored successfully, otherwise
* false.
*/
template
<
typename
FieldType
>
bool
TryStoreConditional
(
embb
::
base
::
Atomic
<
FieldType
>
*
field
,
/**< [IN] Pointer to the field the value will be stored into */
FieldType
value
,
/**< [IN] Value to store */
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
linked_deps
,
/**< [IN] Data records linked to this store operation */
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
finalize_deps
/**< [IN] Data records to be finalized in this store operation */
);
/**
* Tentatively performs a single-record Store-Conditional operation on
* given LLX/SCX data record.
* Returns true if the given value has been stored successfully, otherwise
* false.
*/
template
<
typename
FieldType
>
bool
TryStoreConditional
(
embb
::
base
::
Atomic
<
FieldType
>
*
field
,
/**< [IN] Pointer to the field the value will be stored into */
FieldType
value
,
/**< [IN] Value to store */
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
linked_deps
/**< [IN] Data records linked to this store operation */
);
/**
* Performs a VLX (extended validate link) operation on given LLX data
* record.
* Before calling this method, the given LLX/SCX record must have been
* linked via \c TryLoadLinked.
*
* \returns True if the calling thread's link obtained by its most recent
* invocation of SCX is still valid.
*/
bool
TryValidateLink
(
const
DataRecord_t
&
data_record
/**< [IN] Linked data record to validate */
);
};
#else
/**
* SCX operation description. An SCX record contains all information
* required to allow any process to complete a pending SCX operation.
* This class is non-public.
*/
template
<
typename
DataRecord
>
class
ScxRecord
{
...
...
@@ -163,8 +327,6 @@ class ScxRecord {
};
/* class ScxRecord */
}
// namespace internal
/**
* Wraps user-defined data with fields required for LLX/SCX algorithm.
* Mutable fields must each be contained in a single word.
...
...
@@ -341,7 +503,7 @@ class LlxScx {
bool
TryLoadLinked
(
DataRecord_t
*
const
data_record
,
/**< [IN] Pointer to data record to load */
DataRecord_t
&
data
,
UserData
&
data
,
/**< [OUT] Atomic snapshot of data record */
bool
&
finalized
/**< [OUT] Indicating whether requested fields have been finalized */
...
...
@@ -356,7 +518,7 @@ class LlxScx {
bool
TryLoadLinked
(
DataRecord_t
*
const
data_record
,
/**< [IN] Pointer to data record to load */
DataRecord_t
&
data
UserData
&
data
/**< [OUT] Atomic snapshot of data record */
);
...
...
@@ -378,6 +540,18 @@ class LlxScx {
/**< [IN] Data records to be finalized in this store operation */
);
template
<
typename
FieldType
>
bool
TryStoreConditional
(
embb
::
base
::
Atomic
<
FieldType
*>
*
field
,
/**< [IN] Pointer to the field the value will be stored into */
FieldType
*
value
,
/**< [IN] Value to store */
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
linked_deps
,
/**< [IN] Data records linked to this store operation */
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
finalize_deps
/**< [IN] Data records to be finalized in this store operation */
);
/**
* Tentatively performs a single-record Store-Conditional operation on
* given LLX/SCX data record.
...
...
@@ -393,22 +567,31 @@ class LlxScx {
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
linked_deps
/**< [IN] Data records linked to this store operation */
);
template
<
typename
FieldType
>
bool
TryStoreConditional
(
embb
::
base
::
Atomic
<
FieldType
*>
*
field
,
/**< [IN] Pointer to the field the value will be stored into */
FieldType
*
value
,
/**< [IN] Value to store */
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
linked_deps
/**< [IN] Data records linked to this store operation */
);
/**
* Performs a VLX (extended validate link) operation on given LLX data
* record.
*
Returns true if the calling thread's link obtained by its most recent
*
invocation of SCX is still vali
d.
*
Before calling this method, the given LLX/SCX record must have been
*
linked via \c TryLoadLinke
d.
*
* Precondition:
* - for each data record r in data_records, the active thread
* has performed and r.LLX linked to this VLX.
* \returns True if the calling thread's link obtained by its most recent
* invocation of SCX is still valid.
*/
bool
TryValidateLink
(
const
DataRecord_t
&
data_record
/**< [IN] Linked data record to validate */
);
private
:
typedef
struct
{
...
...
@@ -433,13 +616,16 @@ class LlxScx {
unsigned
int
max_threads_
;
/**
* Shared table containing for each r in V, a copy of r's info
*
value in this
thread's local table of LLX results.
* Shared table containing for each r in V, a copy of r's info
value in this
* thread's local table of LLX results.
*/
embb
::
containers
::
ObjectPool
<
embb
::
containers
::
internal
::
FixedSizeList
<
ScxRecord_t
*>
,
ValuePool
>
scx_record_list_pool_
;
/**
* Pool for SCX records allocated in TryStoreConditional
*/
embb
::
containers
::
ObjectPool
<
ScxRecord_t
,
ValuePool
>
scx_record_pool_
;
/**
...
...
@@ -463,12 +649,37 @@ class LlxScx {
*/
LlxScx
&
operator
=
(
const
LlxScx
&
);
/**
* Actual implementation of StoreConditional operating on unified fields/values
* of type cas_t.
*/
bool
TryStoreConditionalCAS
(
embb
::
base
::
Atomic
<
cas_t
>
*
cas_field
,
/**< [IN] Pointer to the field the value will be stored into */
cas_t
cas_value
,
/**< [IN] Value to store */
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
linked_deps
,
/**< [IN] Data records linked to this store operation */
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
finalize_deps
/**< [IN] Data records to be finalized in this store operation */
);
template
<
typename
FieldType
>
cas_t
ToCASValue
(
FieldType
value
)
{
return
static_cast
<
cas_t
>
(
value
);
}
template
<
typename
FieldType
>
cas_t
ToCASValue
(
FieldType
*
value
)
{
return
reinterpret_cast
<
cas_t
>
(
value
);
}
};
#endif // DOXYGEN
}
// namespace primitives
}
// namespace containers
}
// namespace embb
#include <embb/containers/internal/
primitives/
llx_scx-inl.h>
#include <embb/containers/internal/llx_scx-inl.h>
#endif // EMBB_CONTAINERS_PRIMITIVES_LLX_SCX_H_
\ No newline at end of file
#endif // EMBB_CONTAINERS_INTERNAL_LLX_SCX_H_
\ No newline at end of file
containers_cpp/test/llx_scx_test.cc
View file @
fb4b4604
...
...
@@ -26,15 +26,15 @@
#include <llx_scx_test.h>
#include <embb/containers/internal/fixed_size_list.h>
#include <embb/containers/
primitives
/llx_scx.h>
#include <embb/containers/
internal
/llx_scx.h>
namespace
embb
{
namespace
containers
{
namespace
test
{
using
embb
::
containers
::
internal
::
FixedSizeList
;
using
embb
::
containers
::
primitives
::
LlxScxRecord
;
using
embb
::
containers
::
primitives
::
LlxScx
;
using
embb
::
containers
::
internal
::
LlxScxRecord
;
using
embb
::
containers
::
internal
::
LlxScx
;
LlxScxTest
::
LlxScxTest
()
:
num_threads_
(
...
...
@@ -42,7 +42,8 @@ LlxScxTest::LlxScxTest() :
llxscx_
(
3
),
tail
(
0
,
'-'
),
head
(
0
,
'-'
,
Node
::
node_ptr_t
(
&
tail
))
{
CreateUnit
(
"SerialTest"
).
Add
(
&
LlxScxTest
::
SerialTest
,
this
);
CreateUnit
(
"SerialArrayTest"
).
Add
(
&
LlxScxTest
::
SerialArrayTest
,
this
);
CreateUnit
(
"SerialListTest"
).
Add
(
&
LlxScxTest
::
SerialListTest
,
this
);
CreateUnit
(
"ParallelTest"
).
Add
(
&
LlxScxTest
::
ParallelTest
,
this
);
}
...
...
@@ -57,7 +58,39 @@ void LlxScxTest::ParallelTest() {
// Threads try to append n nodes to a linked list in parallel
}
void
LlxScxTest
::
SerialTest
()
{
void
LlxScxTest
::
SerialArrayTest
()
{
typedef
int
Payload
;
typedef
embb
::
base
::
Atomic
<
size_t
>
AtomicField
;
// LLX/SCX with maximum of 3 active load-links in every thread:
LlxScx
<
Payload
>
llxscx
(
3
);
// Atomic<size_t> not assignable, TryStoreConditional requires
// a specialization for atomics that uses a.Store(b.Load()).
AtomicField
field
(
23
);
// Initialize
LlxScxRecord
<
Payload
>
*
my_list
=
new
LlxScxRecord
<
Payload
>
[
10
];
for
(
int
i
=
0
;
i
!=
10
;
++
i
)
{
my_list
[
i
]
=
i
;
}
Payload
l1
,
l2
;
PT_ASSERT
(
llxscx
.
TryLoadLinked
(
&
my_list
[
0
],
l1
));
PT_ASSERT
(
llxscx
.
TryLoadLinked
(
&
my_list
[
5
],
l2
));
FixedSizeList
<
LlxScxRecord
<
Payload
>
*
>
links
(
2
);
links
.
PushBack
(
&
my_list
[
0
]);
links
.
PushBack
(
&
my_list
[
5
]);
// Try to store new value depending on links:
size_t
a
=
42
;
PT_ASSERT
(
llxscx
.
TryStoreConditional
(
&
field
,
a
,
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
);
...
...
@@ -77,17 +110,17 @@ void LlxScxTest::SerialTest() {
dr2
->
next_
.
Store
(
&
dr3
);
// Thread-local:
LlxScxRecord
<
Node
>
l1
,
l2
,
l3
;
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_EQ
(
l1
.
value_
,
dr1
->
value_
);
PT_ASSERT
(
llxscx
.
TryLoadLinked
(
&
dr2
,
l2
,
finalized
));
PT_ASSERT
(
!
finalized
);
PT_ASSERT_EQ
(
l2
->
value_
,
dr2
->
value_
);
PT_ASSERT_EQ
(
l2
.
value_
,
dr2
->
value_
);
PT_ASSERT
(
llxscx
.
TryLoadLinked
(
&
dr3
,
l3
,
finalized
));
PT_ASSERT
(
!
finalized
);
PT_ASSERT_EQ
(
l3
->
value_
,
dr3
->
value_
);
PT_ASSERT_EQ
(
l3
.
value_
,
dr3
->
value_
);
FixedSizeList
<
LlxScxRecord
<
Node
>
*
>
linked_deps
(
3
);
...
...
@@ -103,7 +136,7 @@ void LlxScxTest::SerialTest() {
LlxScxRecord
<
Node
>
new_node
(
n3
);
PT_ASSERT
(
llxscx
.
TryStoreConditional
<
LlxScxRecord
<
Node
>
*>
(
llxscx
.
TryStoreConditional
(
&
n2
.
next_
,
// fld: field to update
&
new_node
,
// new value
linked_deps
,
// V: dependencies, must be LL'd before
...
...
containers_cpp/test/llx_scx_test.h
View file @
fb4b4604
...
...
@@ -28,7 +28,7 @@
#define CONTAINERS_CPP_TEST_LLX_SCX_TEST_H_
#include <partest/partest.h>
#include <embb/containers/
primitives
/llx_scx.h>
#include <embb/containers/
internal
/llx_scx.h>
namespace
embb
{
namespace
containers
{
...
...
@@ -39,10 +39,10 @@ class LlxScxTest : public partest::TestCase {
private
:
class
Node
{
public
:
typedef
primitives
::
LlxScxRecord
<
Node
>
*
node_ptr_t
;
typedef
internal
::
LlxScxRecord
<
Node
>
*
node_ptr_t
;
public
:
embb
::
base
::
Atomic
<
primitives
::
LlxScxRecord
<
Node
>
*>
next_
;
embb
::
base
::
Atomic
<
internal
::
LlxScxRecord
<
Node
>
*>
next_
;
embb
::
base
::
Atomic
<
int
>
count_
;
char
value_
;
...
...
@@ -88,11 +88,12 @@ class LlxScxTest : public partest::TestCase {
LlxScxTest
();
private
:
void
SerialTest
();
void
SerialArrayTest
();
void
SerialListTest
();
void
ParallelTest
();
int
num_threads_
;
primitives
::
LlxScx
<
Node
>
llxscx_
;
internal
::
LlxScx
<
Node
>
llxscx_
;
Node
tail
;
Node
head
;
};
...
...
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