1 // Copyright 2021 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef DAWNWIRE_CLIENT_REQUESTTRACKER_H_ 16 #define DAWNWIRE_CLIENT_REQUESTTRACKER_H_ 17 18 #include "common/Assert.h" 19 #include "common/NonCopyable.h" 20 21 #include <cstdint> 22 #include <map> 23 24 namespace dawn_wire { namespace client { 25 26 class Device; 27 class MemoryTransferService; 28 29 template <typename Request> 30 class RequestTracker : NonCopyable { 31 public: ~RequestTracker()32 ~RequestTracker() { 33 ASSERT(mRequests.empty()); 34 } 35 Add(Request && request)36 uint64_t Add(Request&& request) { 37 mSerial++; 38 mRequests.emplace(mSerial, request); 39 return mSerial; 40 } 41 Acquire(uint64_t serial,Request * request)42 bool Acquire(uint64_t serial, Request* request) { 43 auto it = mRequests.find(serial); 44 if (it == mRequests.end()) { 45 return false; 46 } 47 *request = std::move(it->second); 48 mRequests.erase(it); 49 return true; 50 } 51 52 template <typename CloseFunc> CloseAll(CloseFunc && closeFunc)53 void CloseAll(CloseFunc&& closeFunc) { 54 // Call closeFunc on all requests while handling reentrancy where the callback of some 55 // requests may add some additional requests. We guarantee all callbacks for requests 56 // are called exactly onces, so keep closing new requests if the first batch added more. 57 // It is fine to loop infinitely here if that's what the application makes use do. 58 while (!mRequests.empty()) { 59 // Move mRequests to a local variable so that further reentrant modifications of 60 // mRequests don't invalidate the iterators. 61 auto allRequests = std::move(mRequests); 62 for (auto& it : allRequests) { 63 closeFunc(&it.second); 64 } 65 } 66 } 67 68 template <typename F> ForAll(F && f)69 void ForAll(F&& f) { 70 for (auto& it : mRequests) { 71 f(&it.second); 72 } 73 } 74 75 private: 76 uint64_t mSerial; 77 std::map<uint64_t, Request> mRequests; 78 }; 79 80 }} // namespace dawn_wire::client 81 82 #endif // DAWNWIRE_CLIENT_REQUESTTRACKER_H_ 83