1 // 2 // Copyright 2019 gRPC authors. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #ifndef GRPC_SRC_CORE_UTIL_WORK_SERIALIZER_H 18 #define GRPC_SRC_CORE_UTIL_WORK_SERIALIZER_H 19 20 #include <grpc/event_engine/event_engine.h> 21 #include <grpc/support/port_platform.h> 22 23 #include <functional> 24 #include <memory> 25 26 #include "absl/base/thread_annotations.h" 27 #include "src/core/util/debug_location.h" 28 #include "src/core/util/orphanable.h" 29 30 namespace grpc_core { 31 32 // WorkSerializer is a mechanism to schedule callbacks in a synchronized manner. 33 // All callbacks scheduled on a WorkSerializer instance will be executed 34 // serially in a borrowed thread. The API provides a FIFO guarantee to the 35 // execution of callbacks scheduled on the thread. 36 // When a thread calls Run() with a callback, the thread is considered borrowed. 37 // The callback might run inline, or it might run asynchronously in a different 38 // thread that is already inside of Run(). If the callback runs directly inline, 39 // other callbacks from other threads might also be executed before Run() 40 // returns. Since an arbitrary set of callbacks might be executed when Run() is 41 // called, generally no locks should be held while calling Run(). 42 // If a thread wants to preclude the possibility of the callback being invoked 43 // inline in Run() (for example, if a mutex lock is held and executing callbacks 44 // inline would cause a deadlock), it should use Schedule() instead and then 45 // invoke DrainQueue() when it is safe to invoke the callback. 46 class ABSL_LOCKABLE WorkSerializer { 47 public: 48 explicit WorkSerializer( 49 std::shared_ptr<grpc_event_engine::experimental::EventEngine> 50 event_engine); 51 ~WorkSerializer(); 52 53 WorkSerializer(const WorkSerializer&) = delete; 54 WorkSerializer& operator=(const WorkSerializer&) = delete; 55 WorkSerializer(WorkSerializer&&) noexcept = default; 56 WorkSerializer& operator=(WorkSerializer&&) noexcept = default; 57 58 // Runs a given callback on the work serializer. 59 // 60 // If experiment `work_serializer_dispatch` is enabled: 61 // The callback will be executed as an EventEngine callback, that then 62 // arranges for the next callback in the queue to execute. 63 // 64 // If experiment `work_serializer_dispatch` is NOT enabled: 65 // If there is no other thread currently executing the WorkSerializer, the 66 // callback is run immediately. In this case, the current thread is also 67 // borrowed for draining the queue for any callbacks that get added in the 68 // meantime. 69 // This behavior is deprecated and will be removed soon. 70 // 71 // If you want to use clang thread annotation to make sure that callback is 72 // called by WorkSerializer only, you need to add the annotation to both the 73 // lambda function given to Run and the actual callback function like; 74 // 75 // void run_callback() { 76 // work_serializer.Run( 77 // []() ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer) { 78 // callback(); 79 // }, DEBUG_LOCATION); 80 // } 81 // void callback() ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer) { ... } 82 void Run(std::function<void()> callback, const DebugLocation& location); 83 84 // Schedule \a callback to be run later when the queue of callbacks is 85 // drained. 86 void Schedule(std::function<void()> callback, const DebugLocation& location); 87 // Drains the queue of callbacks. 88 void DrainQueue(); 89 90 #ifndef NDEBUG 91 // Returns true if the current thread is running in the WorkSerializer. 92 bool RunningInWorkSerializer() const; 93 #endif 94 95 private: 96 class WorkSerializerImpl; 97 class LegacyWorkSerializer; 98 class DispatchingWorkSerializer; 99 100 OrphanablePtr<WorkSerializerImpl> impl_; 101 }; 102 103 } // namespace grpc_core 104 105 #endif // GRPC_SRC_CORE_UTIL_WORK_SERIALIZER_H 106