| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 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 MOJO_SERVICES_MEDIA_FRAMEWORK_UTIL_INCIDENT_H_ | |
| 6 #define MOJO_SERVICES_MEDIA_FRAMEWORK_UTIL_INCIDENT_H_ | |
| 7 | |
| 8 #include <functional> | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "base/synchronization/lock.h" | |
| 12 | |
| 13 namespace mojo { | |
| 14 namespace media { | |
| 15 | |
| 16 // The Incident class provides a facility for executing code as the consequence | |
| 17 // of some occurrence. This can be useful for building state machines and | |
| 18 // otherwise dealing with asynchronous operations. | |
| 19 // | |
| 20 // Incident is not a thread-safe class and has no ability to make a thread wait | |
| 21 // or to execute code on a particular thread. | |
| 22 // | |
| 23 // Incidents rely heavily on std::function, so they shouldn't be used in | |
| 24 // enormous numbers. | |
| 25 // | |
| 26 // An Incident can be in one of two states: initial state or occurred state. | |
| 27 // | |
| 28 // Code can be executed when an incident occurs: | |
| 29 // | |
| 30 // incident.When([]() { | |
| 31 // // Do something... | |
| 32 // }); | |
| 33 // | |
| 34 // The behavior of the When method depends on the incident's state. In initial | |
| 35 // state, the consequence is added to a list to be executed when the incident | |
| 36 // occurs. In occurred state, When executes the consequence immediately (before | |
| 37 // When returns). | |
| 38 // | |
| 39 // An Incident occurs when its Occur (or Run) method is invoked and the Incident | |
| 40 // is in the initial state. All registered consequences of the Incident are | |
| 41 // executed during the call to Occur in the order they were added. Subsequent | |
| 42 // calls to Occur are ignored until the Incident is reset. | |
| 43 // | |
| 44 // The Reset method ensures that the Incident is in its initial state and that | |
| 45 // the list of consequences is cleared (without running the consequences). | |
| 46 class Incident { | |
| 47 public: | |
| 48 Incident(); | |
| 49 | |
| 50 ~Incident(); | |
| 51 | |
| 52 // Determines if this Incident has occurred due to a past call to Occur. | |
| 53 bool occurred() { return occurred_; } | |
| 54 | |
| 55 // Executes the consequence when this Incident occurs. If this Incident hasn't | |
| 56 // occurred when this method is called, a copy of the consequence is held | |
| 57 // until this Incident occurs or is reset. If this Incident has occurred when | |
| 58 // this method is called, the consequence is executed immediately and no copy | |
| 59 // of the consequence is held. | |
| 60 void When(const std::function<void()>& consequence) { | |
| 61 if (occurred_) { | |
| 62 consequence(); | |
| 63 } else { | |
| 64 consequences_.push_back(consequence); | |
| 65 } | |
| 66 } | |
| 67 | |
| 68 // If this Incident is in inital state (!occurred()), this method makes this | |
| 69 // Incident occur, executing and deleting all its consequences. Otherwise, | |
| 70 // does nothing. | |
| 71 void Occur(); | |
| 72 | |
| 73 // Resets this Incident to initial state and clears the list of consequences. | |
| 74 void Reset() { | |
| 75 occurred_ = false; | |
| 76 consequences_.clear(); | |
| 77 } | |
| 78 | |
| 79 // Calls Occur. This method makes an Incident convertible to | |
| 80 // mojo::Callback<void()>. | |
| 81 void Run() { Occur(); } | |
| 82 | |
| 83 private: | |
| 84 bool occurred_ = false; | |
| 85 std::vector<std::function<void()>> consequences_; | |
| 86 }; | |
| 87 | |
| 88 // Like Incident, but threadsafe. | |
| 89 class ThreadsafeIncident { | |
| 90 public: | |
| 91 ThreadsafeIncident(); | |
| 92 | |
| 93 ~ThreadsafeIncident(); | |
| 94 | |
| 95 // Determines if this ThreadsafeIncident has occurred due to a past call to | |
| 96 // Occur. Note that the state of the this ThreadsafeIncident may change | |
| 97 // immediately after this method returns, so there's no guarantee that the | |
| 98 // result is still valid. | |
| 99 bool occurred() { | |
| 100 base::AutoLock lock(consequences_lock_); | |
| 101 return occurred_; | |
| 102 } | |
| 103 | |
| 104 // Executes the consequence when this ThreadsafeIncident occurs. If this | |
| 105 // ThreadsafeIncident hasn't occurred when this method is called, a copy of | |
| 106 // the consequence is held until this ThreadsafeIncident occurs or is reset. | |
| 107 // If this ThreadsafeIncident has occurred when this method is called, the | |
| 108 // consequence is executed immediately and no copy of the consequence is held. | |
| 109 // Note that this ThreadsafeIncident's internal lock is not held when the | |
| 110 // consequence is called. It's therefore possible for this ThreadsafeIncident | |
| 111 // to be reset between the time the decision is made to run the consequence | |
| 112 // and when the consequence is actually run. | |
| 113 void When(const std::function<void()>& consequence) { | |
| 114 { | |
| 115 base::AutoLock lock(consequences_lock_); | |
| 116 if (!occurred_) { | |
| 117 consequences_.push_back(consequence); | |
| 118 return; | |
| 119 } | |
| 120 } | |
| 121 | |
| 122 consequence(); | |
| 123 } | |
| 124 | |
| 125 // If this ThreadsafeIncident is in inital state (!occurred()), this method | |
| 126 // makes this ThreadsafeIncident occur, executing and deleting all its | |
| 127 // consequences. Otherwise, does nothing. | |
| 128 void Occur(); | |
| 129 | |
| 130 // Resets this ThreadsafeIncident to initial state and clears the list of | |
| 131 // consequences. | |
| 132 void Reset() { | |
| 133 base::AutoLock lock(consequences_lock_); | |
| 134 occurred_ = false; | |
| 135 consequences_.clear(); | |
| 136 } | |
| 137 | |
| 138 // Calls Occur. This method makes an ThreadsafeIncident convertible to | |
| 139 // mojo::Callback<void()>. | |
| 140 void Run() { Occur(); } | |
| 141 | |
| 142 private: | |
| 143 mutable base::Lock consequences_lock_; | |
| 144 bool occurred_ = false; | |
| 145 std::vector<std::function<void()>> consequences_; | |
| 146 }; | |
| 147 | |
| 148 } // namespace media | |
| 149 } // namespace mojo | |
| 150 | |
| 151 #endif // MOJO_SERVICES_MEDIA_FRAMEWORK_UTIL_INCIDENT_H_ | |
| OLD | NEW |