LCOV - code coverage report
Current view: top level - root/contrail/src/contrail-common/base - label_block.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 22 22 100.0 %
Date: 2026-08-03 02:19:58 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #ifndef ctrlplane_label_block_h
       6             : #define ctrlplane_label_block_h
       7             : 
       8             : #include <atomic>
       9             : #include <vector>
      10             : #include <mutex>
      11             : #include <boost/intrusive_ptr.hpp>
      12             : 
      13             : #include "base/bitset.h"
      14             : 
      15             : class LabelBlock;
      16             : class LabelBlockManager;
      17             : 
      18             : typedef boost::intrusive_ptr<LabelBlockManager> LabelBlockManagerPtr;
      19             : typedef boost::intrusive_ptr<LabelBlock> LabelBlockPtr;
      20             : 
      21             : //
      22             : // This class represents the manager for a label space. The label space could
      23             : // be for the local node or for a remote node.  The manager maintains a list
      24             : // of LabelBlocks from which labels can be allocated.
      25             : //
      26             : // Clients locate LabelBLocks by specifying the first and last label values for
      27             : // a block. A new LabelBlock is created or the refcount for an existing one is
      28             : // updated as appropriate.  Note that we always return an intrusive pointer to
      29             : // LabelBlock, so that the removal of the LabelBlock happens automatically.
      30             : //
      31             : class LabelBlockManager {
      32             : public:
      33             :     LabelBlockManager();
      34             :     ~LabelBlockManager();
      35             :     LabelBlockPtr LocateBlock(uint32_t first, uint32_t last);
      36             :     void RemoveBlock(LabelBlock *block);
      37       11988 :     std::mutex &mutex() { return mutex_; }
      38             : 
      39             : private:
      40             :     friend class LabelBlockTest;
      41             :     friend void intrusive_ptr_add_ref(LabelBlockManager *block_manager);
      42             :     friend void intrusive_ptr_release(LabelBlockManager *block_manager);
      43             : 
      44             :     typedef std::vector<LabelBlock *> LabelBlockList;
      45             : 
      46             :     size_t size();
      47             : 
      48             :     std::atomic<int> refcount_;
      49             : 
      50             :     // The vector of LabelBlocks is protected via the mutex_. This is needed
      51             :     // because we need to handle concurrent calls to LocateBlock/RemoveBLock.
      52             :     std::mutex mutex_;
      53             :     LabelBlockList blocks_;
      54             : };
      55             : 
      56       35555 : inline void intrusive_ptr_add_ref(LabelBlockManager *block_manager) {
      57       35555 :     block_manager->refcount_++;
      58       35557 : }
      59             : 
      60       35557 : inline void intrusive_ptr_release(LabelBlockManager *block_manager) {
      61       35557 :     int prev = block_manager->refcount_.fetch_sub(1);
      62       35557 :     if (prev == 1) {
      63       10058 :         delete block_manager;
      64             :     }
      65       35557 : }
      66             : 
      67             : //
      68             : // This class represents a block of labels within a label space. Clients can
      69             : // make requests to allocate/release a single label from within this block.
      70             : // As mentioned above, clients always maintain an intrusive pointer to these
      71             : // objects.
      72             : //
      73             : // A BitSet is used to keep track of used/allocated values. A position in the
      74             : // BitSet represents an offset from the first value e.g. label value of first
      75             : // corresponds to bit position 0.
      76             : //
      77             : // TBD: A BitSet is not time efficient when managing a large label space so
      78             : // we should revisit the implementation of this class. Perhaps we could use
      79             : // an itable or a hierarchy of BitSets.
      80             : //
      81             : class LabelBlock {
      82             : public:
      83             :     LabelBlock(uint32_t first, uint32_t last);
      84             :     LabelBlock(LabelBlockManager *block_manager, uint32_t first, uint32_t last);
      85             :     ~LabelBlock();
      86             : 
      87             :     uint32_t AllocateLabel();
      88             :     void ReleaseLabel(uint32_t value);
      89             :     std::string ToString() const;
      90      177690 :     uint32_t first() { return first_; }
      91      163410 :     uint32_t last() { return last_; }
      92       41706 :     LabelBlockManagerPtr block_manager() { return block_manager_; }
      93             : 
      94             : private:
      95             :     friend class LabelBlockManager;
      96             :     friend class LabelBlockTest;
      97             :     friend void intrusive_ptr_add_ref(LabelBlock *block);
      98             :     friend void intrusive_ptr_release(LabelBlock *block);
      99             : 
     100             :     LabelBlockManagerPtr block_manager_;
     101             :     uint32_t first_, last_;
     102             :     size_t prev_pos_;
     103             :     std::atomic<int> refcount_;
     104             : 
     105             :     // The BitSet of used labels is protected via the mutex_. This is needed
     106             :     // since we need to handle concurrent calls to AllocateLabel/ReleaseLabel.
     107             :     std::mutex mutex_;
     108             :     BitSet used_bitset_;
     109             : };
     110             : 
     111       29719 : inline void intrusive_ptr_add_ref(LabelBlock *block) {
     112       29719 :     block->refcount_++;
     113       29720 : }
     114             : 
     115       29719 : inline void intrusive_ptr_release(LabelBlock *block) {
     116       29719 :     std::mutex mutex;
     117             : 
     118       41707 :     std::scoped_lock lock(block->block_manager() ? block->block_manager()->mutex() : mutex);
     119             : 
     120       29720 :     int prev = block->refcount_.fetch_sub(1);
     121       29720 :     if (prev == 1) {
     122        7974 :         delete block;
     123             :     }
     124       29720 : }
     125             : 
     126             : #endif

Generated by: LCOV version 1.14