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
29e2079e
authored
Mar 26, 2015
by
Tobias Fuchs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
containers_cpp: implemented Multiset based on LLX/SCX
parent
95511ee9
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
427 additions
and
0 deletions
+427
-0
containers_cpp/include/embb/containers/internal/multiset-inl.h
+201
-0
containers_cpp/include/embb/containers/multiset.h
+109
-0
containers_cpp/test/multiset_test.cc
+62
-0
containers_cpp/test/multiset_test.h
+55
-0
No files found.
containers_cpp/include/embb/containers/internal/multiset-inl.h
0 → 100644
View file @
29e2079e
/*
* Copyright (c) 2014-2015, 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_MULTISET_INL_H_
#define EMBB_CONTAINERS_INTERNAL_MULTISET_INL_H_
#include <embb/containers/multiset.h>
#include <embb/base/atomic.h>
#include <embb/containers/primitives/llx_scx.h>
namespace
embb
{
namespace
containers
{
namespace
internal
{
template
<
typename
Type
>
MultisetNode
<
Type
>::
MultisetNode
(
const
Type
&
key
,
size_t
count
,
node_ptr_t
next
)
:
key_
(
key
),
count_
(
count
),
next_
(
next
)
{
}
template
<
typename
Type
>
inline
Type
&
MultisetNode
<
Type
>::
Key
()
const
{
return
key_
;
}
template
<
typename
Type
>
inline
embb
::
base
::
Atomic
<
size_t
>
&
MultisetNode
<
Type
>::
Count
()
{
return
count_
;
}
template
<
typename
Type
>
inline
embb
::
base
::
Atomic
<
node_ptr_t
>
&
MultisetNode
<
Type
>::
Next
()
{
return
next_
;
}
}
// namespace internal
template
<
typename
Type
,
Type
UndefinedKey
,
class
ValuePool
>
Multiset
<
Type
,
UndefinedKey
,
ValuePool
>::
Multiset
(
size_t
capacity
)
:
llx_scx_
(
NUM_LLX_SCX_LINKS
)
{
internal
::
MultisetNode
<
Type
>
sentinel_node
(
UndefinedKey
,
0
,
UNDEFINED_POINTER
);
head_
=
node_pool_
.
Allocate
(
sentinel_node
);
tail_
=
node_pool_
.
Allocate
(
sentinel_node
);
head_
->
Next
().
Store
(
tail_
);
tail_
->
Next
().
Store
(
UNDEFINED_POINTER
);
}
template
<
typename
Type
,
Type
UndefinedKey
,
class
ValuePool
>
bool
Multiset
<
Type
,
UndefinedKey
,
ValuePool
>::
Search
(
const
Type
key
,
node_ptr_t
&
node
,
node_ptr_t
&
next
)
{
node
=
head_
;
next
=
tail_
;
while
(
key
>
next
->
Key
()
&&
next
->
Key
()
!=
UndefinedKey
)
{
node
=
next
;
next
=
next
->
Next
();
}
return
(
next
->
Key
()
!=
UndefinedKey
);
}
template
<
typename
Type
,
Type
UndefinedKey
,
class
ValuePool
>
size_t
Multiset
<
Type
,
UndefinedKey
,
ValuePool
>::
Get
(
Type
key
)
{
node_ptr_t
node
,
next
;
if
(
Search
(
key
,
node
,
next
))
{
return
next
->
Count
().
Load
();
}
return
0
;
}
template
<
typename
Type
,
Type
UndefinedKey
,
class
ValuePool
>
void
Multiset
<
Type
,
UndefinedKey
,
ValuePool
>::
Insert
(
Type
key
,
size_t
count
)
{
if
(
count
==
0
)
{
return
;
}
while
(
true
)
{
node_ptr_t
node
,
next
,
local_next
;
Search
(
key
,
node
,
next
);
// Key value is stored in node->next as head node
// is sentinel.
if
(
key
==
next
->
Key
())
{
node_ptr_t
local_next
;
// Key already present in multiset, increment count of its node:
// LLX(r:next)
if
(
llx_scx_
.
TryLoadLinked
(
next
,
local_next
))
{
internal
::
FixedSizeList
<
node_ptr_t
>
linked_deps
(
1
);
linked_deps
.
PushBack
(
next
);
// SCX(fld:next->count, value:next->count + count, V:<next>);
if
(
llx_scx_
.
TryStoreConditional
(
next
->
Count
(),
local_next
->
Count
()
->
Load
()
+
count
,
linked_deps
))
{
return
;
}
}
}
else
{
// Key not present in multiset yet, add node:
node_ptr_t
local_node
;
if
(
llx_scx_
.
TryLoadLinked
(
node
,
local_node
)
&&
next
==
local_node
->
Next
())
{
internal
::
FixedSizeList
<
node_ptr_t
>
linked_deps
(
1
);
linked_deps
.
PushBack
(
node
);
node_t
new_node
(
internal
::
MultisetNode
<
Type
>
(
key
,
count
,
next
));
node_ptr_t
new_node_ptr
=
node_pool_
.
Allocate
(
new_node
);
if
(
llx_scx_
.
TryStoreConditional
(
node
->
Next
(),
new_node_ptr
,
linked_deps
))
{
return
;
}
else
{
// Insert failed, return new node object to pool:
node_pool_
.
Free
(
new_node_ptr
);
}
}
}
}
}
template
<
typename
Type
,
Type
UndefinedKey
,
class
ValuePool
>
bool
Multiset
<
Type
,
UndefinedKey
,
ValuePool
>::
TryDelete
(
Type
key
,
size_t
count
)
{
if
(
count
==
0
)
{
return
false
;
}
while
(
true
)
{
node_ptr_t
node
,
next
,
local_node
,
local_next
;
Search
(
key
,
node
,
next
);
if
(
llx_scx_
.
TryLoadLinked
(
node
,
local_node
)
&&
llx_scx_
.
TryLoadLinked
(
next
,
local_next
)
&&
next
==
local_node
->
Next
())
{
if
(
key
!=
next
->
Key
()
||
local_next
->
Count
()
<
count
)
{
// Key not present in multiset or existing count less
// than amount of elements requested for deletion:
return
false
;
}
else
if
(
local_next
->
Count
()
>
count
)
{
// Inserting a new node with decremented count instead
// of decrementing the exising node's count to reduce
// number of linked dependencies in SCX.
internal
::
MultisetNode
<
Type
>
new_node
(
key
,
count
,
next
);
node_ptr_t
new_node_ptr
=
node_pool_
.
Allocate
(
new_node
);
internal
::
FixedSizeList
<
node_ptr_t
>
linked_deps
(
1
);
linked_deps
.
PushBack
(
node
);
internal
::
FixedSizeList
<
node_ptr_t
>
finalize_deps
(
1
);
finalize_deps
.
PushBack
(
next
);
if
(
llx_scx_
.
TryStoreConditional
(
node
->
Next
(),
new_node_ptr
,
linked_deps
,
finalize_deps
))
{
return
true
;
}
}
else
{
assert
(
local_next
->
Count
()
==
count
);
node_ptr_t
local_next_next
;
if
(
llx_scx_
.
TryLoadLinked
(
next
->
Next
(),
local_next_next
))
{
node_ptr_t
new_next_next_ptr
=
node_pool_
.
Allocate
(
*
local_next_next
);
internal
::
FixedSizeList
<
node_ptr_t
>
linked_deps
(
3
);
linked_deps
.
PushBack
(
node
);
linked_deps
.
PushBack
(
next
);
linked_deps
.
PushBack
(
local_next_next
);
internal
::
FixedSizeList
<
node_ptr_t
>
finalize_deps
(
2
);
finalize_deps
.
PushBack
(
next
);
finalize_deps
.
PushBack
(
local_next_next
);
if
(
llx_scx_
.
TryStoreConditional
(
node
->
Next
(),
new_next_next_ptr
,
linked_deps
,
finalize_deps
)
{
return
true
;
}
else
{
// Delete failed, return new node object to pool and retry:
node_pool_
.
Free
(
new_next_next_ptr
);
}
}
}
}
}
}
}
// namespace containers
}
// namespace embb
#endif // EMBB_CONTAINERS_INTERNAL_MULTISET_INL_H_
\ No newline at end of file
containers_cpp/include/embb/containers/multiset.h
0 → 100644
View file @
29e2079e
/*
* Copyright (c) 2014-2015, 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_MULTISET_H_
#define EMBB_CONTAINERS_MULTISET_H_
#include <embb/base/atomic.h>
#include <embb/containers/wait_free_array_value_pool.h>
#include <embb/containers/lock_free_tree_value_pool.h>
#include <embb/containers/object_pool.h>
#include <embb/containers/primitives/llx_scx.h>
#include <embb/containers/internal/fixed_size_list.h>
namespace
embb
{
namespace
containers
{
namespace
internal
{
template
<
typename
Type
>
class
MultisetNode
{
private
:
typedef
primitives
::
LlxScxRecord
<
internal
::
MultisetNode
<
Type
>
>
*
node_ptr_t
;
public
:
MultisetNode
(
const
Type
&
key
,
size_t
count
,
node_ptr_t
next
);
inline
Type
&
Key
();
inline
embb
::
base
::
Atomic
<
size_t
>
*
Count
()
const
;
inline
embb
::
base
::
Atomic
<
node_ptr_t
>
*
Next
();
private
:
Type
key_
;
embb
::
base
::
Atomic
<
size_t
>
count_
;
embb
::
base
::
Atomic
<
node_ptr_t
>
next_
;
};
}
// namespace internal
template
<
typename
Type
,
Type
UndefinedKey
,
typename
ValuePool
=
embb
::
containers
::
LockFreeTreeValuePool
<
bool
,
false
>
>
class
Multiset
{
private
:
typedef
primitives
::
LlxScxRecord
<
internal
::
MultisetNode
<
Type
>
>
node_t
;
typedef
primitives
::
LlxScxRecord
<
internal
::
MultisetNode
<
Type
>
>
*
node_ptr_t
;
static
const
size_t
UNDEFINED_POINTER
=
static_cast
<
node_ptr_t
>
(
0
);
static
const
size_t
NUM_LLX_SCX_LINKS
=
3
;
public
:
Multiset
(
size_t
capacity
);
size_t
Get
(
Type
key
);
void
Insert
(
Type
key
,
size_t
count
);
bool
TryDelete
(
Type
key
,
size_t
count
);
private
:
void
Search
(
const
Type
key
,
///< [IN] The element key to search in the multiset
node_ptr_t
&
node
,
///< [OUT] The node in the multiset representing the given key
node_ptr_t
&
next
///< [OUT] The next pointer of the node in the multiset representing the given key
);
private
:
ObjectPool
<
node_t
,
ValuePool
>
node_pool_
;
node_ptr_t
head_
;
node_ptr_t
tail_
;
primitives
::
LlxScx
<
MultisetNode
<
Type
>
>
llx_scx_
;
};
}
// namespace containers
}
// namespace embb
// #include <embb/containers/internal/multiset-inl.h>
#endif // EMBB_CONTAINERS_MULTISET_H_
\ No newline at end of file
containers_cpp/test/multiset_test.cc
0 → 100644
View file @
29e2079e
/*
* Copyright (c) 2014-2015, 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.
*/
#if 0
#include <multiset_test.h>
#include <embb/containers/multiset.h>
namespace embb {
namespace containers {
namespace test {
MultisetTest::MultisetTest() :
num_threads_(static_cast<int>(
partest::TestSuite::GetDefaultNumThreads())) {
CreateUnit("SerialTest").Add(&MultisetTest::SerialTest, this);
}
void MultisetTest::SerialTest() {
Multiset<char, '-'> multiset(3);
multiset.Insert('a', 5);
multiset.Insert('b', 5);
multiset.Insert('c', 5);
PT_ASSERT(multiset.TryDelete('a', 4));
PT_ASSERT(multiset.TryDelete('b', 4));
PT_ASSERT(multiset.TryDelete('c', 4));
PT_ASSERT(multiset.Get('a') == 1);
PT_ASSERT(multiset.Get('b') == 1);
PT_ASSERT(multiset.Get('c') == 1);
PT_ASSERT(multiset.TryDelete('a', 1));
PT_ASSERT(multiset.TryDelete('b', 1));
PT_ASSERT(multiset.TryDelete('c', 1));
}
} // namespace test
} // namespace containers
} // namespace embb
#endif
containers_cpp/test/multiset_test.h
0 → 100644
View file @
29e2079e
/*
* Copyright (c) 2014-2015, 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 CONTAINERS_CPP_TEST_MULTISET_TEST_H_
#define CONTAINERS_CPP_TEST_MULTISET_TEST_H_
#include <partest/partest.h>
#include <embb/containers/primitives/llx_scx.h>
namespace
embb
{
namespace
containers
{
namespace
test
{
class
MultisetTest
:
public
partest
::
TestCase
{
public
:
/**
* Adds test methods.
*/
MultisetTest
();
private
:
void
SerialTest
();
int
num_threads_
;
};
}
// namespace test
}
// namespace containers
}
// namespace embb
#endif // CONTAINERS_CPP_TEST_MULTISET_TEST_H_
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