diff --git a/containers_cpp/include/embb/containers/blocking_map.h b/containers_cpp/include/embb/containers/blocking_map.h new file mode 100755 index 0000000..3d857fa --- /dev/null +++ b/containers_cpp/include/embb/containers/blocking_map.h @@ -0,0 +1,65 @@ +/* +* 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 EMBB_CONTAINERS_BLOCKING_MAP_H_ +#define EMBB_CONTAINERS_BLOCKING_MAP_H_ + +#include +#include + +namespace embb { +namespace containers { + +template< typename Key, typename Value> +class BlockingMap { + typedef embb::base::Mutex Mutex; + typedef embb::base::LockGuard<> LockGuard; + + private: + std::map internalMap; + + Mutex mutex; + + public: + BlockingMap(); + + bool Insert(const Key& key, const Value& value); + + bool Erase(const Key& key); + + bool Contains(const Key& key); + + Value& operator[](const Key& key); + +}; + +} +} + +#include + +#endif EMBB_CONTAINERS_BLOCKING_MAP_H_ + diff --git a/containers_cpp/include/embb/containers/internal/blocking_map-inl.h b/containers_cpp/include/embb/containers/internal/blocking_map-inl.h new file mode 100755 index 0000000..84e2ebb --- /dev/null +++ b/containers_cpp/include/embb/containers/internal/blocking_map-inl.h @@ -0,0 +1,67 @@ +/* +* 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 EMBB_CONTAINERS_INTERNAL_BLOCKING_MAP_INL_H_ +#define EMBB_CONTAINERS_INTERNAL_BLOCKING_SET_INL_H_ + + +namespace embb { +namespace containers { + +template +BlockingMap::BlockingMap() : + internalMap() {} + + +template +bool BlockingMap::Insert(const K& key, const V& value) { + LockGuard lock(mutex); + return internalMap.insert(std::map::value_type(key, value)).second; +} + +template +bool BlockingMap::Erase(const K& key) { + LockGuard lock(mutex); + return internalMap.erase(key) > 0; +} + +template +bool BlockingMap::Contains(const K& key) { + LockGuard lock(mutex); + return internalMap.count(key) > 0; +} + +template +V& BlockingMap::operator[](const K& key) { + LockGuard lock(mutex); + return internalMap[key]; +} + + +} +} + +#endif // EMBB_CONTAINERS_INTERNAL_BLOCKING_MAP_INL_H_ \ No newline at end of file diff --git a/containers_cpp/test/blocking_map_test-inl.h b/containers_cpp/test/blocking_map_test-inl.h new file mode 100755 index 0000000..1dc8d94 --- /dev/null +++ b/containers_cpp/test/blocking_map_test-inl.h @@ -0,0 +1,126 @@ +/* +* 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_MAP_TEST_INL_H_ +#define CONTAINERS_CPP_TEST_MAP_TEST_INL_H_ + +namespace embb { + namespace containers { + namespace test { + +template +MapTest::MapTest() : + n_threads(static_cast + (partest::TestSuite::GetDefaultNumThreads())), + n_iterations(200), + n_operations_per_iteration(200), + n_map_elements_per_thread(100), + map(), + map_contain_vector(static_cast + (n_map_elements_per_thread*n_threads)) { + CreateUnit("MapTestThreadsInsertAndEraseToGlobalMap"). + Pre(&MapTest::MapTest1_Pre, this). + Add(&MapTest::MapTest1_ThreadMethod, this, + static_cast(n_threads), + static_cast(n_iterations)). + Post(&MapTest::MapTest1_Post, this); + +} + +template +void MapTest::MapTest1_Pre() { + embb_internal_thread_index_reset(); + thread_local_vectors_key = + new std::vector[static_cast(n_threads)]; + + thread_local_vectors_value = + new std::vector[static_cast(n_threads)]; + + for (int i = 0; i != n_threads; ++i) { + int offset = n_map_elements_per_thread; + + for (int i2 = 0; i2 != n_map_elements_per_thread; ++i2) { + int insert_element = i2 + (offset*i); + thread_local_vectors_key[i].push_back(insert_element); + thread_local_vectors_value[i].push_back(insert_element * 2); + map_contain_vector[static_cast(insert_element)] = false; + } + + } +} + +template +void MapTest::MapTest1_Post() { + unsigned int map_elements = map_contain_vector.size(); + for (unsigned int i = 0; i < map_elements; i++) { + PT_ASSERT(map_contain_vector[i] == map.Contains(static_cast(i))); + if (map_contain_vector[i]) + PT_ASSERT((map[i] == i * 2)); + } +} + +template +void MapTest::MapTest1_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_values = thread_local_vectors_value[thread_index]; + std::vector& my_keys = thread_local_vectors_key[thread_index]; + + + for (int i = 0; i < n_operations_per_iteration; i++) { + int random_number = rand() % 100; + int inserting = rand() % 2; + + int key = my_keys[static_cast(random_number)]; + int value = my_values[static_cast(random_number)]; + + if (inserting) { + PT_ASSERT(map.Insert(key, value) != map_contain_vector[static_cast(key)]); + map_contain_vector[static_cast(key)] = true; + + } + else { + PT_ASSERT(map.Erase(key) == map_contain_vector[static_cast(key)]); + map_contain_vector[static_cast(key)] = false; + } + } + +} + + + + +} // namespace test +} // namespace containers +} // namespace embb + + +#endif // CONTAINERS_CPP_TEST_MAP_TEST_INL_H_ \ No newline at end of file diff --git a/containers_cpp/test/blocking_map_test.h b/containers_cpp/test/blocking_map_test.h new file mode 100755 index 0000000..d43f3c2 --- /dev/null +++ b/containers_cpp/test/blocking_map_test.h @@ -0,0 +1,66 @@ +/* +* 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_MAP_TEST_H_ +#define CONTAINERS_CPP_TEST_MAP_TEST_H_ + +#include +#include +#include +#include + +namespace embb { +namespace containers { +namespace test { +template +class MapTest : public partest::TestCase { + private: + int n_threads; + int n_iterations; + int n_operations_per_iteration; + int n_map_elements_per_thread; + Map_t map; + std::vector* thread_local_vectors_key; + std::vector* thread_local_vectors_value; + std::vector map_contain_vector; + + public: + MapTest(); + + void MapTest1_Pre(); + + void MapTest1_Post(); + + void MapTest1_ThreadMethod(); + +}; +} // namespace test +} // namespace containers +} // namespace embb + +#include "./blocking_map_test-inl.h" + +#endif \ No newline at end of file diff --git a/containers_cpp/test/main.cc b/containers_cpp/test/main.cc index a6796e8..8f11809 100644 --- a/containers_cpp/test/main.cc +++ b/containers_cpp/test/main.cc @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,7 @@ #include "./hazard_pointer_test.h" #include "./object_pool_test.h" #include "./set_test.h" +#include "./blocking_map_test.h" #define COMMA , @@ -59,6 +61,7 @@ using embb::containers::BlockingStack; using embb::containers::LockFreeTreeValuePool; using embb::containers::WaitFreeArrayValuePool; using embb::containers::BlockingSet; +using embb::containers::BlockingMap; using embb::containers::test::PoolTest; using embb::containers::test::HazardPointerTest; using embb::containers::test::QueueTest; @@ -68,6 +71,7 @@ using embb::containers::test::BlockingStackTest; using embb::containers::test::SetTest; using embb::containers::test::ObjectPoolTest; using embb::containers::test::HazardPointerTest2; +using embb::containers::test::MapTest; PT_MAIN("Data Structures C++") { @@ -85,6 +89,7 @@ PT_MAIN("Data Structures C++") { PT_RUN(StackTest< LockFreeStack >); PT_RUN(BlockingStackTest< BlockingStack >); PT_RUN(SetTest< BlockingSet >); + PT_RUN(MapTest >); PT_RUN(ObjectPoolTest< LockFreeTreeValuePool >); PT_RUN(ObjectPoolTest< WaitFreeArrayValuePool >); PT_EXPECT(embb_get_bytes_allocated() == 0);