# HG changeset patch # User David Demelier # Date 1504344282 -7200 # Node ID 385ba70b93e3964eeef4bcf920dafb3e9c3c0220 # Parent 41e5722da2aef4d1ee6094b91e8864e73f811af3 Common: add weak_array class diff -r 41e5722da2ae -r 385ba70b93e3 libcommon/CMakeLists.txt --- a/libcommon/CMakeLists.txt Mon Aug 21 20:59:18 2017 +0200 +++ b/libcommon/CMakeLists.txt Sat Sep 02 11:24:42 2017 +0200 @@ -27,6 +27,7 @@ ${libmlk-common_SOURCE_DIR}/malikania/size.hpp ${libmlk-common_SOURCE_DIR}/malikania/tileset.hpp ${libmlk-common_SOURCE_DIR}/malikania/util.hpp + ${libmlk-common_SOURCE_DIR}/malikania/weak_array.hpp ) set( diff -r 41e5722da2ae -r 385ba70b93e3 libcommon/malikania/weak_array.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libcommon/malikania/weak_array.hpp Sat Sep 02 11:24:42 2017 +0200 @@ -0,0 +1,79 @@ +/* + * weak_array.hpp -- implement a cache array of weak values + * + * Copyright (c) 2013-2017 David Demelier + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef MALIKANIA_WEAK_ARRAY_HPP +#define MALIKANIA_WEAK_ARRAY_HPP + +/** + * \file weak_array.hpp + * \brief Implement a cache array of weak values. + */ + +#include +#include + +namespace mlk { + +/** + * \brief Implement a cache array of weak values. + */ +template +class weak_array : public std::vector> { +public: + /** + * Find a value by a predicate. + * + * The predicate must have the following signature: + * + * ````cpp + * bool f(const std::shared_ptr& value) const noexcept + * ```` + * + * \param pred the predicate + * \return nullptr if not found + */ + template + std::shared_ptr find_if(Predicate&& pred) const noexcept + { + for (const auto& value : *this) { + auto sp = value.lock(); + + if (sp && pred(sp)) + return sp; + } + + return nullptr; + } + + /** + * Remove values that have no more referenced. + */ + void purge() + { + for (auto it = this->begin(); it != this->end(); ) { + if (!it->lock()) + it = this->erase(it); + else + it++; + } + } +}; + +} // !mlk + +#endif // !MALIKANIA_WEAK_ARRAY_HPP diff -r 41e5722da2ae -r 385ba70b93e3 tests/libcommon/weak_array/CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/libcommon/weak_array/CMakeLists.txt Sat Sep 02 11:24:42 2017 +0200 @@ -0,0 +1,23 @@ +# +# CMakeLists.txt -- CMake build system for malikania +# +# Copyright (c) 2013-2017 Malikania Authors +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +malikania_create_test( + NAME weak_array + LIBRARIES libmlk-common + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp +) diff -r 41e5722da2ae -r 385ba70b93e3 tests/libcommon/weak_array/main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/libcommon/weak_array/main.cpp Sat Sep 02 11:24:42 2017 +0200 @@ -0,0 +1,67 @@ +/* + * main.cpp -- test weak_array + * + * Copyright (c) 2013-2017 Malikania Authors + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define BOOST_TEST_MODULE "weak_array" +#include + +#include + +namespace mlk { + +class weak_array_fixture { +protected: + weak_array array_; +}; + +BOOST_FIXTURE_TEST_SUITE(weak_array_suite, weak_array_fixture) + +BOOST_AUTO_TEST_CASE(reuse) +{ + auto value = std::make_shared(123); + + array_.push_back(value); + array_.push_back(std::make_shared(256)); + + auto it1 = array_.find_if([] (auto ptr) { + return *ptr = 123; + }); + auto it2 = array_.find_if([] (auto ptr) { + return *ptr = 123; + }); + + BOOST_TEST(it1 == value); + BOOST_TEST(it2 == value); + BOOST_TEST(it1 == it2); + BOOST_TEST(*it1 == 123); + BOOST_TEST(*it2 == 123); +} + +BOOST_AUTO_TEST_CASE(not_found) +{ + array_.push_back(std::make_shared(123)); + + auto v = array_.find_if([] (auto ptr) { + return *ptr = 123; + }); + + BOOST_TEST(!v); +} + +BOOST_AUTO_TEST_SUITE_END() + +} // !mlk