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 @@
...
@@ -24,25 +24,19 @@
* POSSIBILITY OF SUCH DAMAGE.
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
#ifndef EMBB_CONTAINERS_
PRIMITIVES
_LLX_SCX_INL_H_
#ifndef EMBB_CONTAINERS_
INTERNAL
_LLX_SCX_INL_H_
#define EMBB_CONTAINERS_
PRIMITIVES
_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/thread.h>
#include <embb/base/atomic.h>
#include <embb/base/atomic.h>
#include <embb/base/memory_allocation.h>
#include <embb/base/memory_allocation.h>
#include <vector>
#include <vector>
#include <stdarg.h>
#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
embb
{
namespace
containers
{
namespace
containers
{
namespace
primitives
{
namespace
internal
{
template
<
typename
UserData
,
typename
ValuePool
>
template
<
typename
UserData
,
typename
ValuePool
>
unsigned
int
LlxScx
<
UserData
,
ValuePool
>::
ThreadId
()
{
unsigned
int
LlxScx
<
UserData
,
ValuePool
>::
ThreadId
()
{
...
@@ -89,7 +83,7 @@ LlxScx<UserData, ValuePool>::~LlxScx() {
...
@@ -89,7 +83,7 @@ LlxScx<UserData, ValuePool>::~LlxScx() {
template
<
typename
UserData
,
typename
ValuePool
>
template
<
typename
UserData
,
typename
ValuePool
>
bool
LlxScx
<
UserData
,
ValuePool
>::
TryLoadLinked
(
bool
LlxScx
<
UserData
,
ValuePool
>::
TryLoadLinked
(
DataRecord_t
*
const
data_record
,
DataRecord_t
*
const
data_record
,
DataRecord_t
&
user_data
,
UserData
&
user_data
,
bool
&
finalized
)
{
bool
&
finalized
)
{
finalized
=
false
;
finalized
=
false
;
unsigned
int
thread_id
=
ThreadId
();
unsigned
int
thread_id
=
ThreadId
();
...
@@ -132,7 +126,7 @@ bool LlxScx<UserData, ValuePool>::TryLoadLinked(
...
@@ -132,7 +126,7 @@ bool LlxScx<UserData, ValuePool>::TryLoadLinked(
template
<
typename
UserData
,
typename
ValuePool
>
template
<
typename
UserData
,
typename
ValuePool
>
bool
LlxScx
<
UserData
,
ValuePool
>::
TryLoadLinked
(
bool
LlxScx
<
UserData
,
ValuePool
>::
TryLoadLinked
(
DataRecord_t
*
const
data_record
,
DataRecord_t
*
const
data_record
,
DataRecord_t
&
user_data
)
{
UserData
&
user_data
)
{
bool
finalized
;
bool
finalized
;
return
TryLoadLinked
(
data_record
,
user_data
,
finalized
);
return
TryLoadLinked
(
data_record
,
user_data
,
finalized
);
}
}
...
@@ -144,6 +138,51 @@ bool LlxScx<UserData, ValuePool>::TryStoreConditional(
...
@@ -144,6 +138,51 @@ bool LlxScx<UserData, ValuePool>::TryStoreConditional(
FieldType
value
,
FieldType
value
,
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
linked_deps
,
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
linked_deps
,
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
finalize_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
<
DataRecord_t
*>
dr_list_t
;
typedef
embb
::
containers
::
internal
::
FixedSizeList
<
ScxRecord_t
*>
scx_op_list_t
;
typedef
embb
::
containers
::
internal
::
FixedSizeList
<
ScxRecord_t
*>
scx_op_list_t
;
// Preconditions:
// Preconditions:
...
@@ -184,11 +223,11 @@ bool LlxScx<UserData, ValuePool>::TryStoreConditional(
...
@@ -184,11 +223,11 @@ bool LlxScx<UserData, ValuePool>::TryStoreConditional(
linked_deps
,
linked_deps
,
finalize_deps
,
finalize_deps
,
// target field:
// target field:
reinterpret_cast
<
embb
::
base
::
Atomic
<
cas_t
>
*>
(
field
)
,
cas_field
,
// new value:
// new value:
reinterpret_cast
<
cas_t
>
(
value
)
,
cas_value
,
// old value:
// old value:
reinterpret_cast
<
cas_t
>
(
field
->
Load
()
),
cas_field
->
Load
(
),
// linked SCX operations:
// linked SCX operations:
info_fields
,
info_fields
,
// initial operation state:
// initial operation state:
...
@@ -199,16 +238,6 @@ bool LlxScx<UserData, ValuePool>::TryStoreConditional(
...
@@ -199,16 +238,6 @@ bool LlxScx<UserData, ValuePool>::TryStoreConditional(
}
}
template
<
typename
UserData
,
typename
ValuePool
>
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
(
bool
LlxScx
<
UserData
,
ValuePool
>::
TryValidateLink
(
const
DataRecord_t
&
field
)
{
const
DataRecord_t
&
field
)
{
return
true
;
// @TODO
return
true
;
// @TODO
...
@@ -233,7 +262,7 @@ LlxScxRecord<UserData>::LlxScxRecord(
...
@@ -233,7 +262,7 @@ LlxScxRecord<UserData>::LlxScxRecord(
// internal::ScxRecord
// internal::ScxRecord
template
<
typename
DataRecord
>
template
<
typename
DataRecord
>
bool
internal
::
ScxRecord
<
DataRecord
>::
Help
()
{
bool
ScxRecord
<
DataRecord
>::
Help
()
{
// We ensure that an SCX S does not change a data record
// We ensure that an SCX S does not change a data record
// while it is frozen for another SCX S'. Instead, S uses
// while it is frozen for another SCX S'. Instead, S uses
// the information in the SCX record of S' to help S'
// the information in the SCX record of S' to help S'
...
@@ -291,12 +320,12 @@ bool internal::ScxRecord<DataRecord>::Help() {
...
@@ -291,12 +320,12 @@ bool internal::ScxRecord<DataRecord>::Help() {
}
}
template
<
typename
UserData
>
template
<
typename
UserData
>
internal
::
ScxRecord
<
LlxScxRecord
<
UserData
>
>
ScxRecord
<
LlxScxRecord
<
UserData
>
>
LlxScxRecord
<
UserData
>::
dummy_scx
=
LlxScxRecord
<
UserData
>::
dummy_scx
=
internal
::
ScxRecord
<
LlxScxRecord
<
UserData
>
>
();
ScxRecord
<
LlxScxRecord
<
UserData
>
>
();
}
// namespace
primitives
}
// namespace
internal
}
// namespace containers
}
// namespace containers
}
// namespace embb
}
// 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 @@
...
@@ -24,8 +24,8 @@
* POSSIBILITY OF SUCH DAMAGE.
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
#ifndef EMBB_CONTAINERS_
PRIMITIVES
_LLX_SCX_H_
#ifndef EMBB_CONTAINERS_
INTERNAL
_LLX_SCX_H_
#define EMBB_CONTAINERS_
PRIMITIVES
_LLX_SCX_H_
#define EMBB_CONTAINERS_
INTERNAL
_LLX_SCX_H_
#include <embb/base/thread.h>
#include <embb/base/thread.h>
#include <embb/base/atomic.h>
#include <embb/base/atomic.h>
...
@@ -36,13 +36,177 @@
...
@@ -36,13 +36,177 @@
namespace
embb
{
namespace
embb
{
namespace
containers
{
namespace
containers
{
namespace
primitives
{
namespace
internal
{
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
* SCX operation description. An SCX record contains all information
* required to allow any process to complete a pending SCX operation.
* required to allow any process to complete a pending SCX operation.
* This class is non-public.
*/
*/
template
<
typename
DataRecord
>
template
<
typename
DataRecord
>
class
ScxRecord
{
class
ScxRecord
{
...
@@ -163,8 +327,6 @@ class ScxRecord {
...
@@ -163,8 +327,6 @@ class ScxRecord {
};
/* class ScxRecord */
};
/* class ScxRecord */
}
// namespace internal
/**
/**
* Wraps user-defined data with fields required for LLX/SCX algorithm.
* Wraps user-defined data with fields required for LLX/SCX algorithm.
* Mutable fields must each be contained in a single word.
* Mutable fields must each be contained in a single word.
...
@@ -341,7 +503,7 @@ class LlxScx {
...
@@ -341,7 +503,7 @@ class LlxScx {
bool
TryLoadLinked
(
bool
TryLoadLinked
(
DataRecord_t
*
const
data_record
,
DataRecord_t
*
const
data_record
,
/**< [IN] Pointer to data record to load */
/**< [IN] Pointer to data record to load */
DataRecord_t
&
data
,
UserData
&
data
,
/**< [OUT] Atomic snapshot of data record */
/**< [OUT] Atomic snapshot of data record */
bool
&
finalized
bool
&
finalized
/**< [OUT] Indicating whether requested fields have been finalized */
/**< [OUT] Indicating whether requested fields have been finalized */
...
@@ -356,7 +518,7 @@ class LlxScx {
...
@@ -356,7 +518,7 @@ class LlxScx {
bool
TryLoadLinked
(
bool
TryLoadLinked
(
DataRecord_t
*
const
data_record
,
DataRecord_t
*
const
data_record
,
/**< [IN] Pointer to data record to load */
/**< [IN] Pointer to data record to load */
DataRecord_t
&
data
UserData
&
data
/**< [OUT] Atomic snapshot of data record */
/**< [OUT] Atomic snapshot of data record */
);
);
...
@@ -378,6 +540,18 @@ class LlxScx {
...
@@ -378,6 +540,18 @@ class LlxScx {
/**< [IN] Data records to be finalized in this store operation */
/**< [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
* Tentatively performs a single-record Store-Conditional operation on
* given LLX/SCX data record.
* given LLX/SCX data record.
...
@@ -393,22 +567,31 @@ class LlxScx {
...
@@ -393,22 +567,31 @@ class LlxScx {
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
linked_deps
embb
::
containers
::
internal
::
FixedSizeList
<
DataRecord_t
*>
&
linked_deps
/**< [IN] Data records linked to this store operation */
/**< [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
* Performs a VLX (extended validate link) operation on given LLX data
* record.
* record.
*
Returns true if the calling thread's link obtained by its most recent
*
Before calling this method, the given LLX/SCX record must have been
*
invocation of SCX is still vali
d.
*
linked via \c TryLoadLinke
d.
*
*
* Precondition:
* \returns True if the calling thread's link obtained by its most recent
* - for each data record r in data_records, the active thread
* invocation of SCX is still valid.
* has performed and r.LLX linked to this VLX.
*/
*/
bool
TryValidateLink
(
bool
TryValidateLink
(
const
DataRecord_t
&
data_record
const
DataRecord_t
&
data_record
/**< [IN] Linked data record to validate */
/**< [IN] Linked data record to validate */
);
);
private
:
private
:
typedef
struct
{
typedef
struct
{
...
@@ -433,13 +616,16 @@ class LlxScx {
...
@@ -433,13 +616,16 @@ class LlxScx {
unsigned
int
max_threads_
;
unsigned
int
max_threads_
;
/**
/**
* Shared table containing for each r in V, a copy of r's info
* Shared table containing for each r in V, a copy of r's info
value in this
*
value in this
thread's local table of LLX results.
* thread's local table of LLX results.
*/
*/
embb
::
containers
::
ObjectPool
<
embb
::
containers
::
ObjectPool
<
embb
::
containers
::
internal
::
FixedSizeList
<
ScxRecord_t
*>
,
ValuePool
>
embb
::
containers
::
internal
::
FixedSizeList
<
ScxRecord_t
*>
,
ValuePool
>
scx_record_list_pool_
;
scx_record_list_pool_
;
/**
* Pool for SCX records allocated in TryStoreConditional
*/
embb
::
containers
::
ObjectPool
<
ScxRecord_t
,
ValuePool
>
scx_record_pool_
;
embb
::
containers
::
ObjectPool
<
ScxRecord_t
,
ValuePool
>
scx_record_pool_
;
/**
/**
...
@@ -463,12 +649,37 @@ class LlxScx {
...
@@ -463,12 +649,37 @@ class LlxScx {
*/
*/
LlxScx
&
operator
=
(
const
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 primitives
}
// namespace containers
}
// namespace containers
}
// namespace embb
}
// 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_
#endif // EMBB_CONTAINERS_INTERNAL_LLX_SCX_H_
\ No newline at end of file
\ No newline at end of file
containers_cpp/test/llx_scx_test.cc
View file @
fb4b4604
...
@@ -26,15 +26,15 @@
...
@@ -26,15 +26,15 @@
#include <llx_scx_test.h>
#include <llx_scx_test.h>
#include <embb/containers/internal/fixed_size_list.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
embb
{
namespace
containers
{
namespace
containers
{
namespace
test
{
namespace
test
{
using
embb
::
containers
::
internal
::
FixedSizeList
;
using
embb
::
containers
::
internal
::
FixedSizeList
;
using
embb
::
containers
::
primitives
::
LlxScxRecord
;
using
embb
::
containers
::
internal
::
LlxScxRecord
;
using
embb
::
containers
::
primitives
::
LlxScx
;
using
embb
::
containers
::
internal
::
LlxScx
;
LlxScxTest
::
LlxScxTest
()
:
LlxScxTest
::
LlxScxTest
()
:
num_threads_
(
num_threads_
(
...
@@ -42,7 +42,8 @@ LlxScxTest::LlxScxTest() :
...
@@ -42,7 +42,8 @@ LlxScxTest::LlxScxTest() :
llxscx_
(
3
),
llxscx_
(
3
),
tail
(
0
,
'-'
),
tail
(
0
,
'-'
),
head
(
0
,
'-'
,
Node
::
node_ptr_t
(
&
tail
))
{
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
);
CreateUnit
(
"ParallelTest"
).
Add
(
&
LlxScxTest
::
ParallelTest
,
this
);
}
}
...
@@ -57,7 +58,39 @@ void LlxScxTest::ParallelTest() {
...
@@ -57,7 +58,39 @@ void LlxScxTest::ParallelTest() {
// Threads try to append n nodes to a linked list in parallel
// 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
;
typedef
LlxScxTest
::
Node
Node
;
// Global:
// Global:
LlxScx
<
Node
>
llxscx
(
3
);
LlxScx
<
Node
>
llxscx
(
3
);
...
@@ -77,17 +110,17 @@ void LlxScxTest::SerialTest() {
...
@@ -77,17 +110,17 @@ void LlxScxTest::SerialTest() {
dr2
->
next_
.
Store
(
&
dr3
);
dr2
->
next_
.
Store
(
&
dr3
);
// Thread-local:
// Thread-local:
LlxScxRecord
<
Node
>
l1
,
l2
,
l3
;
Node
l1
,
l2
,
l3
;
bool
finalized
;
bool
finalized
;
PT_ASSERT
(
llxscx
.
TryLoadLinked
(
&
dr1
,
l1
,
finalized
));
PT_ASSERT
(
llxscx
.
TryLoadLinked
(
&
dr1
,
l1
,
finalized
));
PT_ASSERT
(
!
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
(
llxscx
.
TryLoadLinked
(
&
dr2
,
l2
,
finalized
));
PT_ASSERT
(
!
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
(
llxscx
.
TryLoadLinked
(
&
dr3
,
l3
,
finalized
));
PT_ASSERT
(
!
finalized
);
PT_ASSERT
(
!
finalized
);
PT_ASSERT_EQ
(
l3
->
value_
,
dr3
->
value_
);
PT_ASSERT_EQ
(
l3
.
value_
,
dr3
->
value_
);
FixedSizeList
<
LlxScxRecord
<
Node
>
*
>
FixedSizeList
<
LlxScxRecord
<
Node
>
*
>
linked_deps
(
3
);
linked_deps
(
3
);
...
@@ -103,7 +136,7 @@ void LlxScxTest::SerialTest() {
...
@@ -103,7 +136,7 @@ void LlxScxTest::SerialTest() {
LlxScxRecord
<
Node
>
new_node
(
n3
);
LlxScxRecord
<
Node
>
new_node
(
n3
);
PT_ASSERT
(
PT_ASSERT
(
llxscx
.
TryStoreConditional
<
LlxScxRecord
<
Node
>
*>
(
llxscx
.
TryStoreConditional
(
&
n2
.
next_
,
// fld: field to update
&
n2
.
next_
,
// fld: field to update
&
new_node
,
// new value
&
new_node
,
// new value
linked_deps
,
// V: dependencies, must be LL'd before
linked_deps
,
// V: dependencies, must be LL'd before
...
...
containers_cpp/test/llx_scx_test.h
View file @
fb4b4604
...
@@ -28,7 +28,7 @@
...
@@ -28,7 +28,7 @@
#define CONTAINERS_CPP_TEST_LLX_SCX_TEST_H_
#define CONTAINERS_CPP_TEST_LLX_SCX_TEST_H_
#include <partest/partest.h>
#include <partest/partest.h>
#include <embb/containers/
primitives
/llx_scx.h>
#include <embb/containers/
internal
/llx_scx.h>
namespace
embb
{
namespace
embb
{
namespace
containers
{
namespace
containers
{
...
@@ -39,10 +39,10 @@ class LlxScxTest : public partest::TestCase {
...
@@ -39,10 +39,10 @@ class LlxScxTest : public partest::TestCase {
private
:
private
:
class
Node
{
class
Node
{
public
:
public
:
typedef
primitives
::
LlxScxRecord
<
Node
>
*
node_ptr_t
;
typedef
internal
::
LlxScxRecord
<
Node
>
*
node_ptr_t
;
public
:
public
:
embb
::
base
::
Atomic
<
primitives
::
LlxScxRecord
<
Node
>
*>
next_
;
embb
::
base
::
Atomic
<
internal
::
LlxScxRecord
<
Node
>
*>
next_
;
embb
::
base
::
Atomic
<
int
>
count_
;
embb
::
base
::
Atomic
<
int
>
count_
;
char
value_
;
char
value_
;
...
@@ -88,11 +88,12 @@ class LlxScxTest : public partest::TestCase {
...
@@ -88,11 +88,12 @@ class LlxScxTest : public partest::TestCase {
LlxScxTest
();
LlxScxTest
();
private
:
private
:
void
SerialTest
();
void
SerialArrayTest
();
void
SerialListTest
();
void
ParallelTest
();
void
ParallelTest
();
int
num_threads_
;
int
num_threads_
;
primitives
::
LlxScx
<
Node
>
llxscx_
;
internal
::
LlxScx
<
Node
>
llxscx_
;
Node
tail
;
Node
tail
;
Node
head
;
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