diff --git a/src/lib/typed-counter.hpp b/src/lib/typed-counter.hpp index 88e14fc07..fdd9100a7 100644 --- a/src/lib/typed-counter.hpp +++ b/src/lib/typed-counter.hpp @@ -126,7 +126,7 @@ namespace lib { /** - * Helper providing a set of counters, each tied to a specific type. + * Utility providing a set of counters, each tied to a specific type. */ class TypedCounter : public Sync<> @@ -186,5 +186,43 @@ namespace lib { + /** + * Utility to produce member IDs + * for objects belonging to a "Family", + * as defined by a distinguishing type. + */ + template + class FamilyMember + { + const size_t id_; + + /** member counter shared per template instance */ + static size_t memberCounter; + + /** threadsafe allocation of member ID */ + static size_t + allocateNextMember() + { + ClassLock synchronised; + return memberCounter++; + } + + public: + FamilyMember() + : id_{allocateNextMember()} + { } + + operator size_t() const + { + return id_; + } + }; + + /** allocate storage for the counter per type family */ + template + size_t FamilyMember::memberCounter{0}; + + + } // namespace lib #endif diff --git a/tests/12metaprogramming.tests b/tests/12metaprogramming.tests index e7d6f59f7..3ec9cfd3c 100644 --- a/tests/12metaprogramming.tests +++ b/tests/12metaprogramming.tests @@ -602,6 +602,11 @@ return: 0 END +TEST "Type-based family member IDs" TypedFamilyMemberID_test < + ** ** This test builds several "families", each sharing a TypedCounter. Each of these ** families runs a set of member threads, which concurrently access the TypedCounter of ** this family. After waiting for all threads to finish, we compare the checksum built @@ -85,7 +85,7 @@ namespace test{ */ - /** + /** * Interface to a family of dummy types */ class DummyType @@ -180,7 +180,7 @@ namespace test{ - /** + /** * Collection of target functions, * to be invoked during the test run */ @@ -224,14 +224,14 @@ namespace test{ iterator end() { return targets_.end(); } }; - DummyTarget targetCollection; + DummyTarget targetCollection; /** * Each single check runs in a separate thread * and performs a random sequence of increments - * and decrements on random targets. + * and decrements on random targets. */ class SingleCheck : ThreadJoinable @@ -259,7 +259,7 @@ namespace test{ }; - /** + /** * Family of individual checks, sharing * a common TypedCounter instance. */ @@ -311,7 +311,7 @@ namespace test{ { void - run (Arg) + run (Arg) { simpleUsageTest(); tortureTest(); @@ -366,7 +366,7 @@ namespace test{ void - tortureTest () + tortureTest () { std::srand (::time (NULL)); sum_TypedCounter_ = 0; diff --git a/tests/basics/typed-family-member-id-test.cpp b/tests/basics/typed-family-member-id-test.cpp new file mode 100644 index 000000000..39210e3d5 --- /dev/null +++ b/tests/basics/typed-family-member-id-test.cpp @@ -0,0 +1,90 @@ +/* + TypedFamilyMemberID(Test) - verify type based member ID + + Copyright (C) Lumiera.org + 2017, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +/** @file typed-family-member-id-test.cpp + ** Unit test to verify generation of a Member ID within a type based family of objects. + */ + + + +#include "lib/test/run.hpp" +#include "lib/typed-counter.hpp" + + +namespace lib { +namespace test{ + + + + + /*******************************************************************//** + * @test simplistic unit test to demonstrate generating _member IDs + * within a family of objects delineated by type. + * @warning this test does not cover the thread safety, + * because FamilyMember relies on lib::ClassLock, + * which is assumed to be covered separately + * + * @see SessionCommandFunction_test::perform_massivelyParallel + * @see typed-counter.hpp + */ + class TypedFamilyMemberID_test : public Test + { + + void + run (Arg) + { + struct X { }; + struct Y { }; + struct Z { }; + + CHECK (0 == FamilyMember{}); + CHECK (1 == FamilyMember{}); + CHECK (2 == FamilyMember{}); + + CHECK (0 == FamilyMember{}); + CHECK (1 == FamilyMember{}); + + CHECK (0 == FamilyMember{}); + + CHECK (2 == FamilyMember{}); + CHECK (3 == FamilyMember{}); + + CHECK (1 == FamilyMember{}); + CHECK (2 == FamilyMember{}); + CHECK (3 == FamilyMember{}); + CHECK (4 == FamilyMember{}); + + CHECK (4 == FamilyMember{}); + CHECK (5 == FamilyMember{}); + CHECK (3 == FamilyMember{}); + CHECK (5 == FamilyMember{}); + CHECK (4 == FamilyMember{}); + } + }; + + + /** Register this test class... */ + LAUNCHER (TypedFamilyMemberID_test, "unit common"); + + +}} // namespace lib::test