Home | History | Annotate | Download | only in system
      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