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_EDK_SYSTEM_REQUEST_CONTEXT_H_ 6 #define MOJO_EDK_SYSTEM_REQUEST_CONTEXT_H_ 7 8 #include "base/containers/stack_container.h" 9 #include "base/macros.h" 10 #include "mojo/edk/system/handle_signals_state.h" 11 #include "mojo/edk/system/system_impl_export.h" 12 #include "mojo/edk/system/watcher.h" 13 14 namespace base { 15 template<typename T> class ThreadLocalPointer; 16 } 17 18 namespace mojo { 19 namespace edk { 20 21 // A RequestContext is a thread-local object which exists for the duration of 22 // a single system API call. It is constructed immediately upon EDK entry and 23 // destructed immediately before returning to the caller, after any internal 24 // locks have been released. 25 // 26 // NOTE: It is legal to construct a RequestContext while another one already 27 // exists on the current thread, but it is not safe to use the nested context 28 // for any reason. Therefore it is important to always use 29 // |RequestContext::current()| rather than referring to any local instance 30 // directly. 31 class MOJO_SYSTEM_IMPL_EXPORT RequestContext { 32 public: 33 // Identifies the source of the current stack frame's RequestContext. 34 enum class Source { 35 LOCAL_API_CALL, 36 SYSTEM, 37 }; 38 39 // Constructs a RequestContext with a LOCAL_API_CALL Source. 40 RequestContext(); 41 42 explicit RequestContext(Source source); 43 ~RequestContext(); 44 45 // Returns the current thread-local RequestContext. 46 static RequestContext* current(); 47 48 Source source() const { return source_; } 49 50 // Adds a finalizer to this RequestContext corresponding to a watch callback 51 // which should be triggered in response to some handle state change. If 52 // the Watcher hasn't been cancelled by the time this RequestContext is 53 // destroyed, its WatchCallback will be invoked with |result| and |state| 54 // arguments. 55 void AddWatchNotifyFinalizer(scoped_refptr<Watcher> watcher, 56 MojoResult result, 57 const HandleSignalsState& state); 58 59 // Adds a finalizer to this RequestContext which cancels a watch. 60 void AddWatchCancelFinalizer(scoped_refptr<Watcher> watcher); 61 62 private: 63 // Is this request context the current one? 64 bool IsCurrent() const; 65 66 struct WatchNotifyFinalizer { 67 WatchNotifyFinalizer(scoped_refptr<Watcher> watcher, 68 MojoResult result, 69 const HandleSignalsState& state); 70 WatchNotifyFinalizer(const WatchNotifyFinalizer& other); 71 ~WatchNotifyFinalizer(); 72 73 scoped_refptr<Watcher> watcher; 74 MojoResult result; 75 HandleSignalsState state; 76 }; 77 78 // Chosen by fair dice roll. 79 // 80 // TODO: We should measure the distribution of # of finalizers typical to 81 // any RequestContext and adjust this number accordingly. It's probably 82 // almost always 1, but 4 seems like a harmless upper bound for now. 83 static const size_t kStaticWatchFinalizersCapacity = 4; 84 85 using WatchNotifyFinalizerList = 86 base::StackVector<WatchNotifyFinalizer, kStaticWatchFinalizersCapacity>; 87 using WatchCancelFinalizerList = 88 base::StackVector<scoped_refptr<Watcher>, kStaticWatchFinalizersCapacity>; 89 90 const Source source_; 91 92 WatchNotifyFinalizerList watch_notify_finalizers_; 93 WatchCancelFinalizerList watch_cancel_finalizers_; 94 95 // Pointer to the TLS context. Although this can easily be accessed via the 96 // global LazyInstance, accessing a LazyInstance has a large cost relative to 97 // the rest of this class and its usages. 98 base::ThreadLocalPointer<RequestContext>* tls_context_; 99 100 DISALLOW_COPY_AND_ASSIGN(RequestContext); 101 }; 102 103 } // namespace edk 104 } // namespace mojo 105 106 #endif // MOJO_EDK_SYSTEM_REQUEST_CONTEXT_H_ 107