tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

simple_thread.h (9492B)


      1 // Copyright 2011 The Chromium Authors
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // WARNING: You should probably be using Thread (thread.h) instead.  Thread is
      6 //          Chrome's message-loop based Thread abstraction, and if you are a
      7 //          thread running in the browser, there will likely be assumptions
      8 //          that your thread will have an associated message loop.
      9 //
     10 // This is a simple thread interface that backs to a native operating system
     11 // thread.  You should use this only when you want a thread that does not have
     12 // an associated MessageLoop.  Unittesting is the best example of this.
     13 //
     14 // The simplest interface to use is DelegateSimpleThread, which will create
     15 // a new thread, and execute the Delegate's virtual Run() in this new thread
     16 // until it has completed, exiting the thread.
     17 //
     18 // NOTE: You *MUST* call Join on the thread to clean up the underlying thread
     19 // resources.  You are also responsible for destructing the SimpleThread object.
     20 // It is invalid to destroy a SimpleThread while it is running, or without
     21 // Start() having been called (and a thread never created).  The Delegate
     22 // object should live as long as a DelegateSimpleThread.
     23 //
     24 // Thread Safety: A SimpleThread is not completely thread safe.  It is safe to
     25 // access it from the creating thread or from the newly created thread.  This
     26 // implies that the creator thread should be the thread that calls Join.
     27 //
     28 // Example:
     29 //   class MyThreadRunner : public DelegateSimpleThread::Delegate { ... };
     30 //   MyThreadRunner runner;
     31 //   DelegateSimpleThread thread(&runner, "good_name_here");
     32 //   thread.Start();
     33 //   // Start will return after the Thread has been successfully started and
     34 //   // initialized.  The newly created thread will invoke runner->Run(), and
     35 //   // run until it returns.
     36 //   thread.Join();  // Wait until the thread has exited.  You *MUST* Join!
     37 //   // The SimpleThread object is still valid, however you may not call Join
     38 //   // or Start again.
     39 
     40 #ifndef BASE_THREADING_SIMPLE_THREAD_H_
     41 #define BASE_THREADING_SIMPLE_THREAD_H_
     42 
     43 #include <stddef.h>
     44 
     45 #include <memory>
     46 #include <string>
     47 #include <vector>
     48 
     49 #include "base/base_export.h"
     50 #include "base/compiler_specific.h"
     51 #include "base/containers/queue.h"
     52 #include "base/memory/raw_ptr.h"
     53 #include "base/synchronization/lock.h"
     54 #include "base/synchronization/waitable_event.h"
     55 #include "base/threading/platform_thread.h"
     56 
     57 namespace base {
     58 
     59 // This is the base SimpleThread.  You can derive from it and implement the
     60 // virtual Run method, or you can use the DelegateSimpleThread interface.
     61 // SimpleThread should not be used to run a MessagePump, `base::Thread` must be
     62 // used for that.
     63 class BASE_EXPORT SimpleThread : public PlatformThread::Delegate {
     64 public:
     65  struct BASE_EXPORT Options {
     66   public:
     67    Options() = default;
     68    explicit Options(ThreadType thread_type) : thread_type(thread_type) {}
     69    ~Options() = default;
     70 
     71    // Allow copies.
     72    Options(const Options& other) = default;
     73    Options& operator=(const Options& other) = default;
     74 
     75    // A custom stack size, or 0 for the system default.
     76    size_t stack_size = 0;
     77 
     78    ThreadType thread_type = ThreadType::kDefault;
     79 
     80    // If false, the underlying thread's PlatformThreadHandle will not be kept
     81    // around and as such the SimpleThread instance will not be Join()able and
     82    // must not be deleted before Run() is invoked. After that, it's up to
     83    // the subclass to determine when it is safe to delete itself.
     84    bool joinable = true;
     85  };
     86 
     87  // Creates a SimpleThread. |options| should be used to manage any specific
     88  // configuration involving the thread creation and management.
     89  // Every thread has a name, which is a display string to identify the thread.
     90  // The thread will not be created until Start() is called.
     91  explicit SimpleThread(const std::string& name);
     92  SimpleThread(const std::string& name, const Options& options);
     93 
     94  SimpleThread(const SimpleThread&) = delete;
     95  SimpleThread& operator=(const SimpleThread&) = delete;
     96 
     97  ~SimpleThread() override;
     98 
     99  // Starts the thread and returns only after the thread has started and
    100  // initialized (i.e. ThreadMain() has been called).
    101  void Start();
    102 
    103  // Joins the thread. If StartAsync() was used to start the thread, then this
    104  // first waits for the thread to start cleanly, then it joins.
    105  void Join();
    106 
    107  // Starts the thread, but returns immediately, without waiting for the thread
    108  // to have initialized first (i.e. this does not wait for ThreadMain() to have
    109  // been run first).
    110  void StartAsync();
    111 
    112  // Subclasses should override the Run method.
    113  virtual void Run() = 0;
    114 
    115  // Returns the thread id, only valid after the thread has started. If the
    116  // thread was started using Start(), then this will be valid after the call to
    117  // Start(). If StartAsync() was used to start the thread, then this must not
    118  // be called before HasBeenStarted() returns True.
    119  PlatformThreadId tid();
    120 
    121  // Returns True if the thread has been started and initialized (i.e. if
    122  // ThreadMain() has run). If the thread was started with StartAsync(), but it
    123  // hasn't been initialized yet (i.e. ThreadMain() has not run), then this will
    124  // return False.
    125  bool HasBeenStarted();
    126 
    127  // Returns True if Join() has ever been called.
    128  bool HasBeenJoined() const { return joined_; }
    129 
    130  // Returns true if Start() or StartAsync() has been called.
    131  bool HasStartBeenAttempted() { return start_called_; }
    132 
    133  // Overridden from PlatformThread::Delegate:
    134  void ThreadMain() override;
    135 
    136 private:
    137  // This is called just before the thread is started. This is called regardless
    138  // of whether Start() or StartAsync() is used to start the thread.
    139  virtual void BeforeStart() {}
    140 
    141  // This is called just after the thread has been initialized and just before
    142  // Run() is called. This is called on the newly started thread.
    143  virtual void BeforeRun() {}
    144 
    145  // This is called just before the thread is joined. The thread is started and
    146  // has been initialized before this is called.
    147  virtual void BeforeJoin() {}
    148 
    149  const std::string name_;
    150  const Options options_;
    151  PlatformThreadHandle thread_;  // PlatformThread handle, reset after Join.
    152  WaitableEvent event_;          // Signaled if Start() was ever called.
    153  PlatformThreadId tid_ = kInvalidThreadId;  // The backing thread's id.
    154  bool joined_ = false;                      // True if Join has been called.
    155  // Set to true when the platform-thread creation has started.
    156  bool start_called_ = false;
    157 };
    158 
    159 // A SimpleThread which delegates Run() to its Delegate. Non-joinable
    160 // DelegateSimpleThread are safe to delete after Run() was invoked, their
    161 // Delegates are also safe to delete after that point from this class' point of
    162 // view (although implementations must of course make sure that Run() will not
    163 // use their Delegate's member state after its deletion).
    164 class BASE_EXPORT DelegateSimpleThread : public SimpleThread {
    165 public:
    166  class BASE_EXPORT Delegate {
    167   public:
    168    virtual ~Delegate() = default;
    169    virtual void Run() = 0;
    170  };
    171 
    172  DelegateSimpleThread(Delegate* delegate,
    173                       const std::string& name_prefix);
    174  DelegateSimpleThread(Delegate* delegate,
    175                       const std::string& name_prefix,
    176                       const Options& options);
    177 
    178  DelegateSimpleThread(const DelegateSimpleThread&) = delete;
    179  DelegateSimpleThread& operator=(const DelegateSimpleThread&) = delete;
    180 
    181  ~DelegateSimpleThread() override;
    182  void Run() override;
    183 
    184 private:
    185  raw_ptr<Delegate> delegate_;
    186 };
    187 
    188 // DelegateSimpleThreadPool allows you to start up a fixed number of threads,
    189 // and then add jobs which will be dispatched to the threads.  This is
    190 // convenient when you have a lot of small work that you want done
    191 // multi-threaded, but don't want to spawn a thread for each small bit of work.
    192 //
    193 // You just call AddWork() to add a delegate to the list of work to be done.
    194 // JoinAll() will make sure that all outstanding work is processed, and wait
    195 // for everything to finish.  You can reuse a pool, so you can call Start()
    196 // again after you've called JoinAll().
    197 class BASE_EXPORT DelegateSimpleThreadPool
    198    : public DelegateSimpleThread::Delegate {
    199 public:
    200  typedef DelegateSimpleThread::Delegate Delegate;
    201 
    202  DelegateSimpleThreadPool(const std::string& name_prefix, size_t num_threads);
    203 
    204  DelegateSimpleThreadPool(const DelegateSimpleThreadPool&) = delete;
    205  DelegateSimpleThreadPool& operator=(const DelegateSimpleThreadPool&) = delete;
    206 
    207  ~DelegateSimpleThreadPool() override;
    208 
    209  // Start up all of the underlying threads, and start processing work if we
    210  // have any.
    211  void Start();
    212 
    213  // Make sure all outstanding work is finished, and wait for and destroy all
    214  // of the underlying threads in the pool.
    215  void JoinAll();
    216 
    217  // It is safe to AddWork() any time, before or after Start().
    218  // Delegate* should always be a valid pointer, NULL is reserved internally.
    219  void AddWork(Delegate* work, size_t repeat_count = 1);
    220 
    221  // We implement the Delegate interface, for running our internal threads.
    222  void Run() override;
    223 
    224 private:
    225  const std::string name_prefix_;
    226  size_t num_threads_;
    227  std::vector<std::unique_ptr<DelegateSimpleThread>> threads_;
    228  base::queue<Delegate*> delegates_;
    229  base::Lock lock_;            // Locks delegates_
    230  WaitableEvent dry_;    // Not signaled when there is no work to do.
    231 };
    232 
    233 }  // namespace base
    234 
    235 #endif  // BASE_THREADING_SIMPLE_THREAD_H_