group_coordinator.h 3.1 KB

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