• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
source()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