diff --git a/containers_cpp/include/embb/containers/blocking_set.h b/containers_cpp/include/embb/containers/blocking_set.h new file mode 100755 index 0000000..495c650 --- /dev/null +++ b/containers_cpp/include/embb/containers/blocking_set.h @@ -0,0 +1,68 @@ +/* +* 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_BLOCKING_SET_H_ +#define EMBB_CONTAINERS_BLOCKING_SET_H_ + + +#include +#include + + +namespace embb { +namespace containers { + +/* +* Wrapper for the standard library set. +* +* \tparam T Element type. +*/ +template < typename Type > +class BlockingSet { + typedef embb::base::Mutex Mutex; + typedef embb::base::LockGuard LockGuard; + private: + std::set internalSet; + + Mutex mutex; + + public: + BlockingSet(); + + bool Insert(const Type& element); + + bool Erase(const Type& element); + + bool Contains(const Type& element); + +}; + +} +} + +#include + +#endif // EMBB_CONTAINERS_BLOCKING_CONTAINER_ \ No newline at end of file diff --git a/containers_cpp/include/embb/containers/internal/blocking_set-inl.h b/containers_cpp/include/embb/containers/internal/blocking_set-inl.h new file mode 100755 index 0000000..271211f --- /dev/null +++ b/containers_cpp/include/embb/containers/internal/blocking_set-inl.h @@ -0,0 +1,60 @@ +#include "..\blocking_set.h" +/* +* 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_BLOCKING_SET_INL_H_ +#define EMBB_CONTAINERS_BLOCKING_SET_INL_H_ + + +namespace embb { +namespace containers { + + template + BlockingSet::BlockingSet() : + internalSet() {} + + template + bool BlockingSet::Insert(const T& element){ + LockGuard lock(mutex); + return internalSet.insert(element).second; + } + + template + bool BlockingSet::Erase(const T& element){ + LockGuard lock(mutex); + return internalSet.erase(element) > 0; + } + + template + bool BlockingSet::Contains(const T& element){ + LockGuard lock(mutex); + return internalSet.find(element) != internalSet.end(); + } + +} +} + +#endif // EMBB_CONTAINERS_BLOCKING_SET_INL_H_ \ No newline at end of file diff --git a/containers_cpp/test/main.cc b/containers_cpp/test/main.cc index 85c8561..a6796e8 100644 --- a/containers_cpp/test/main.cc +++ b/containers_cpp/test/main.cc @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,7 @@ #include "./blocking_stack_test.h" #include "./hazard_pointer_test.h" #include "./object_pool_test.h" +#include "./set_test.h" #define COMMA , @@ -56,20 +58,22 @@ using embb::containers::LockFreeStack; using embb::containers::BlockingStack; using embb::containers::LockFreeTreeValuePool; using embb::containers::WaitFreeArrayValuePool; +using embb::containers::BlockingSet; using embb::containers::test::PoolTest; using embb::containers::test::HazardPointerTest; using embb::containers::test::QueueTest; using embb::containers::test::BlockingQueueTest; using embb::containers::test::StackTest; using embb::containers::test::BlockingStackTest; +using embb::containers::test::SetTest; using embb::containers::test::ObjectPoolTest; using embb::containers::test::HazardPointerTest2; PT_MAIN("Data Structures C++") { + unsigned int max_threads = static_cast( 2 * partest::TestSuite::GetDefaultNumThreads()); embb_thread_set_max_count(max_threads); - PT_RUN(PoolTest< WaitFreeArrayValuePool >); PT_RUN(PoolTest< LockFreeTreeValuePool >); PT_RUN(HazardPointerTest); @@ -80,8 +84,9 @@ PT_MAIN("Data Structures C++") { PT_RUN(BlockingQueueTest< BlockingQueue >); PT_RUN(StackTest< LockFreeStack >); PT_RUN(BlockingStackTest< BlockingStack >); + PT_RUN(SetTest< BlockingSet >); PT_RUN(ObjectPoolTest< LockFreeTreeValuePool >); PT_RUN(ObjectPoolTest< WaitFreeArrayValuePool >); - PT_EXPECT(embb_get_bytes_allocated() == 0); + } diff --git a/containers_cpp/test/set_test-inl.h b/containers_cpp/test/set_test-inl.h new file mode 100755 index 0000000..129b059 --- /dev/null +++ b/containers_cpp/test/set_test-inl.h @@ -0,0 +1,117 @@ +#pragma once +/* +* Copyright (c) 2014-2016, 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_SET_TEST_INL_H_ +#define CONTAINERS_CPP_TEST_SET_TEST_INL_H_ + +#include +#include +#include + +namespace embb { +namespace containers { +namespace test { + +template +SetTest::SetTest() : + n_threads(static_cast + (partest::TestSuite::GetDefaultNumThreads())), + n_iterations(200), + n_operations_per_iteration(200), + n_set_elements_per_thread(100), + set(), + set_contain_vector(static_cast + (n_set_elements_per_thread*n_threads)) { + CreateUnit("SetTestThreadsInsertAndEraseToGlobalSet"). + Pre(&SetTest::SetTest1_Pre, this). + Add(&SetTest::SetTest1_ThreadMethod, this, + static_cast(n_threads), + static_cast(n_iterations)). + Post(&SetTest::SetTest1_Post, this); +} + +template +void SetTest::SetTest1_Pre(){ + embb_internal_thread_index_reset(); + thread_local_vectors = + new std::vector[static_cast(n_threads)]; + + for (int i = 0; i != n_threads; ++i) { + int offset = n_set_elements_per_thread; + + for (int i2 = 0; i2 != n_set_elements_per_thread; ++i2) { + int insert_element = i2 + (offset*i); + thread_local_vectors[i].push_back(insert_element); + set_contain_vector[static_cast(insert_element)] = false; + } + } +} + +template +void SetTest::SetTest1_Post(){ + unsigned int set_elements = set_contain_vector.size(); + for (unsigned int i = 0; i < set_elements; i++) { + PT_ASSERT(set_contain_vector[i] == set.Contains(static_cast(i))); + } + + delete[] thread_local_vectors; +} + +template +void SetTest::SetTest1_ThreadMethod() { + unsigned int thread_index; + int return_val = embb_internal_thread_index(&thread_index); + + PT_ASSERT(EMBB_SUCCESS == return_val); + + srand(time(NULL)); + + std::vector& my_elements = thread_local_vectors[thread_index]; + + for (int i = 0; i < n_operations_per_iteration; i++) { + int random_number = rand() % 100; + int inserting = rand() % 2; + + int element = my_elements[static_cast(random_number)]; + + if (inserting) { + PT_ASSERT(set.Insert(element) != set_contain_vector[static_cast(element)]); + set_contain_vector[static_cast(element)] = true; + } + else { + PT_ASSERT(set.Erase(element) == set_contain_vector[static_cast(element)]); + set_contain_vector[static_cast(element)] = false; + } + } +} + + +} // namespace test +} // namespace containers +} // namespace embb + +#endif // CONTAINERS_CPP_TEST_SET_TEST_INL_H_ \ No newline at end of file diff --git a/containers_cpp/test/set_test.h b/containers_cpp/test/set_test.h new file mode 100755 index 0000000..3cc3a5f --- /dev/null +++ b/containers_cpp/test/set_test.h @@ -0,0 +1,62 @@ +/* +* Copyright (c) 2014-2016, 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_SET_TEST_H_ +#define CONTAINERS_CPP_TEST_SET_TEST_H_ + +#include +#include +#include + +namespace embb { +namespace containers { +namespace test { +template +class SetTest : public partest::TestCase { +private: + int n_threads; + int n_iterations; + int n_operations_per_iteration; + int n_set_elements_per_thread; + Set_t set; + std::vector* thread_local_vectors; + std::vector set_contain_vector; + +public: + SetTest(); + + void SetTest1_Pre(); + + void SetTest1_Post(); + + void SetTest1_ThreadMethod(); +}; +} // namespace test +} // namespace containers +} // namespace embb + +#include "./set_test-inl.h" + +#endif // CONTAINERS_CPP_TEST_SET_TEST_H_ \ No newline at end of file diff --git a/containers_cpp/test/stack_test-inl.h b/containers_cpp/test/stack_test-inl.h index 18ef724..63d77cc 100644 --- a/containers_cpp/test/stack_test-inl.h +++ b/containers_cpp/test/stack_test-inl.h @@ -35,19 +35,19 @@ namespace containers { namespace test { template StackTest::StackTest() : -n_threads(static_cast - (partest::TestSuite::GetDefaultNumThreads())), + n_threads(static_cast + (partest::TestSuite::GetDefaultNumThreads())), n_iterations(200), n_stack_elements_per_thread(100), n_stack_elements(n_stack_elements_per_thread*n_threads), stack(static_cast(n_stack_elements)), stackSize(0) { CreateUnit("StackTestThreadsPushAndPopToGlobalStack"). - Pre(&StackTest::StackTest1_Pre, this). - Add(&StackTest::StackTest1_ThreadMethod, this, - static_cast(n_threads), - static_cast(n_iterations)). - Post(&StackTest::StackTest1_Post, this); + Pre(&StackTest::StackTest1_Pre, this). + Add(&StackTest::StackTest1_ThreadMethod, this, + static_cast(n_threads), + static_cast(n_iterations)). + Post(&StackTest::StackTest1_Post, this); } template