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

Generated by: LCOV version 1.14