1 // Copyright 2018 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef SERVICES_AUDIO_GROUP_COORDINATOR_H_ 6 #define SERVICES_AUDIO_GROUP_COORDINATOR_H_ 7 8 #include <algorithm> 9 #include <utility> 10 #include <vector> 11 12 #include "base/callback.h" 13 #include "base/logging.h" 14 #include "base/macros.h" 15 #include "base/sequence_checker.h" 16 #include "base/stl_util.h" 17 #include "base/unguessable_token.h" 18 19 namespace audio { 20 21 // Manages a registry of group members and notifies observers as membership in 22 // the group changes. 23 template <typename Member> 24 class GroupCoordinator { 25 public: 26 // Interface for entities that wish to montior and take action as members 27 // join/leave a particular group. 28 class Observer { 29 public: 30 virtual void OnMemberJoinedGroup(Member* member) = 0; 31 virtual void OnMemberLeftGroup(Member* member) = 0; 32 33 protected: 34 virtual ~Observer(); 35 }; 36 37 GroupCoordinator(); 38 ~GroupCoordinator(); 39 40 // Registers/Unregisters a group |member|. The member must remain valid until 41 // after UnregisterMember() is called. 42 void RegisterMember(const base::UnguessableToken& group_id, Member* member); 43 void UnregisterMember(const base::UnguessableToken& group_id, Member* member); 44 45 void AddObserver(const base::UnguessableToken& group_id, Observer* observer); 46 void RemoveObserver(const base::UnguessableToken& group_id, 47 Observer* observer); 48 49 // Runs a |callback| for each member associated with the given |group_id|. 50 void ForEachMemberInGroup( 51 const base::UnguessableToken& group_id, 52 base::RepeatingCallback<void(Member*)> callback) const; 53 54 protected: 55 // Returns the current members in the group having the given |group_id|. Note 56 // that the validity of the returned reference is uncertain once any of the 57 // other non-const methods are called. 58 const std::vector<Member*>& GetCurrentMembersUnsafe( 59 const base::UnguessableToken& group_id) const; 60 61 private: 62 struct Group { 63 std::vector<Member*> members; 64 std::vector<Observer*> observers; 65 66 Group(); 67 ~Group(); 68 Group(Group&& other); 69 Group& operator=(Group&& other); 70 71 private: 72 DISALLOW_COPY_AND_ASSIGN(Group); 73 }; 74 75 using GroupMap = std::vector<std::pair<base::UnguessableToken, Group>>; 76 77 // Returns an iterator to the entry associated with the given |group_id|, 78 // creating a new one if necessary. 79 typename GroupMap::iterator FindGroup(const base::UnguessableToken& group_id); 80 81 // Deletes the entry in |groups_| if it has no members or observers remaining. 82 void MaybePruneGroupMapEntry(typename GroupMap::iterator it); 83 84 GroupMap groups_; 85 86 #if DCHECK_IS_ON() 87 // Incremented with each mutation, and used to sanity-check that there aren't 88 // any possible re-entrancy bugs. It's okay if this rolls over, since the 89 // implementation is only doing DCHECK_EQ's. 90 size_t mutation_count_ = 0; 91 #endif 92 93 SEQUENCE_CHECKER(sequence_checker_); 94 95 DISALLOW_COPY_AND_ASSIGN(GroupCoordinator); 96 }; 97 98 } // namespace audio 99 100 #endif // SERVICES_AUDIO_GROUP_COORDINATOR_H_ 101