LCOV - code coverage report
Current view: top level - source/common/thread_local - thread_local_impl.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 1 3 33.3 %
Date: 2024-01-05 06:35:25 Functions: 1 3 33.3 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <atomic>
       4             : #include <cstdint>
       5             : #include <list>
       6             : #include <memory>
       7             : #include <vector>
       8             : 
       9             : #include "envoy/thread_local/thread_local.h"
      10             : 
      11             : #include "source/common/common/logger.h"
      12             : #include "source/common/common/non_copyable.h"
      13             : 
      14             : namespace Envoy {
      15             : namespace ThreadLocal {
      16             : 
      17             : /**
      18             :  * Implementation of ThreadLocal that relies on static thread_local objects.
      19             :  */
      20             : class InstanceImpl : Logger::Loggable<Logger::Id::main>, public NonCopyable, public Instance {
      21             : public:
      22             :   ~InstanceImpl() override;
      23             : 
      24             :   // ThreadLocal::Instance
      25             :   SlotPtr allocateSlot() override;
      26             :   void registerThread(Event::Dispatcher& dispatcher, bool main_thread) override;
      27             :   void shutdownGlobalThreading() override;
      28             :   void shutdownThread() override;
      29             :   Event::Dispatcher& dispatcher() override;
      30           0 :   bool isShutdown() const override { return shutdown_; }
      31             : 
      32             : private:
      33             :   // On destruction returns the slot index to the deferred delete queue (detaches it). This allows
      34             :   // a slot to be destructed on the main thread while controlling the lifetime of the underlying
      35             :   // slot as callbacks drain from workers.
      36             :   struct SlotImpl : public Slot {
      37             :     SlotImpl(InstanceImpl& parent, uint32_t index);
      38        1281 :     ~SlotImpl() override { parent_.removeSlot(index_); }
      39             :     std::function<void()> wrapCallback(const std::function<void()>& cb);
      40             :     std::function<void()> dataCallback(const UpdateCb& cb);
      41             :     static bool currentThreadRegisteredWorker(uint32_t index);
      42             :     static ThreadLocalObjectSharedPtr getWorker(uint32_t index);
      43             : 
      44             :     // ThreadLocal::Slot
      45             :     ThreadLocalObjectSharedPtr get() override;
      46             :     void runOnAllThreads(const UpdateCb& cb) override;
      47             :     void runOnAllThreads(const UpdateCb& cb, const std::function<void()>& complete_cb) override;
      48             :     bool currentThreadRegistered() override;
      49             :     void set(InitializeCb cb) override;
      50           0 :     bool isShutdown() const override { return parent_.shutdown_; }
      51             : 
      52             :     InstanceImpl& parent_;
      53             :     const uint32_t index_;
      54             :     // The following is used to safely verify via weak_ptr that this slot is still alive. This
      55             :     // does not prevent all races if a callback does not capture appropriately, but it does fix
      56             :     // the common case of a slot destroyed immediately before anything is posted to a worker.
      57             :     // NOTE: The general safety model of a slot is that it is destroyed immediately on the main
      58             :     //       thread. This means that *all* captures must not reference the slot object directly.
      59             :     //       this is why index_ is captured manually in callbacks that require it.
      60             :     // NOTE: When the slot is destroyed, the index is immediately recycled. This is safe because
      61             :     //       any new posts for a recycled index must come after any previous callbacks for the
      62             :     //       previous owner of the index.
      63             :     // TODO(mattklein123): Add clang-tidy analysis rule to check that "this" is not captured by
      64             :     // a TLS function call. This check will not prevent all bad captures, but it will at least
      65             :     // make the programmer more aware of potential issues.
      66             :     std::shared_ptr<bool> still_alive_guard_;
      67             :   };
      68             : 
      69             :   struct ThreadLocalData {
      70             :     Event::Dispatcher* dispatcher_{};
      71             :     std::vector<ThreadLocalObjectSharedPtr> data_;
      72             :   };
      73             : 
      74             :   void removeSlot(uint32_t slot);
      75             :   void runOnAllThreads(std::function<void()> cb);
      76             :   void runOnAllThreads(std::function<void()> cb, std::function<void()> main_callback);
      77             :   static void setThreadLocal(uint32_t index, ThreadLocalObjectSharedPtr object);
      78             : 
      79             :   static thread_local ThreadLocalData thread_local_data_;
      80             : 
      81             :   Thread::MainThread main_thread_;
      82             :   std::vector<Slot*> slots_;
      83             :   // A list of index of freed slots.
      84             :   std::list<uint32_t> free_slot_indexes_;
      85             :   std::list<std::reference_wrapper<Event::Dispatcher>> registered_threads_;
      86             :   Event::Dispatcher* main_thread_dispatcher_{};
      87             :   std::atomic<bool> shutdown_{};
      88             : 
      89             :   // Test only.
      90             :   friend class ThreadLocalInstanceImplTest;
      91             : };
      92             : 
      93             : using InstanceImplPtr = std::unique_ptr<InstanceImpl>;
      94             : 
      95             : } // namespace ThreadLocal
      96             : } // namespace Envoy

Generated by: LCOV version 1.15