OpenSDN source code
label_block.h
Go to the documentation of this file.
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 //
32 public:
35  LabelBlockPtr LocateBlock(uint32_t first, uint32_t last);
36  void RemoveBlock(LabelBlock *block);
37  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_;
54 };
55 
56 inline void intrusive_ptr_add_ref(LabelBlockManager *block_manager) {
57  block_manager->refcount_++;
58 }
59 
60 inline void intrusive_ptr_release(LabelBlockManager *block_manager) {
61  int prev = block_manager->refcount_.fetch_sub(1);
62  if (prev == 1) {
63  delete block_manager;
64  }
65 }
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  uint32_t first() { return first_; }
91  uint32_t last() { return last_; }
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 
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_;
109 };
110 
111 inline void intrusive_ptr_add_ref(LabelBlock *block) {
112  block->refcount_++;
113 }
114 
115 inline void intrusive_ptr_release(LabelBlock *block) {
116  std::mutex mutex;
117 
118  std::scoped_lock lock(block->block_manager() ? block->block_manager()->mutex() : mutex);
119 
120  int prev = block->refcount_.fetch_sub(1);
121  if (prev == 1) {
122  delete block;
123  }
124 }
125 
126 #endif
Definition: bitset.h:17
std::mutex & mutex()
Definition: label_block.h:37
std::vector< LabelBlock * > LabelBlockList
Definition: label_block.h:44
std::mutex mutex_
Definition: label_block.h:52
friend void intrusive_ptr_release(LabelBlockManager *block_manager)
Definition: label_block.h:60
LabelBlockPtr LocateBlock(uint32_t first, uint32_t last)
Definition: label_block.cc:22
std::atomic< int > refcount_
Definition: label_block.h:48
void RemoveBlock(LabelBlock *block)
Definition: label_block.cc:38
LabelBlockList blocks_
Definition: label_block.h:53
friend void intrusive_ptr_add_ref(LabelBlockManager *block_manager)
Definition: label_block.h:56
friend class LabelBlockTest
Definition: label_block.h:40
friend void intrusive_ptr_add_ref(LabelBlock *block)
Definition: label_block.h:111
std::atomic< int > refcount_
Definition: label_block.h:103
LabelBlockManagerPtr block_manager_
Definition: label_block.h:100
uint32_t first()
Definition: label_block.h:90
uint32_t first_
Definition: label_block.h:101
uint32_t last_
Definition: label_block.h:101
LabelBlock(uint32_t first, uint32_t last)
Definition: label_block.cc:54
LabelBlockManagerPtr block_manager()
Definition: label_block.h:92
BitSet used_bitset_
Definition: label_block.h:108
std::string ToString() const
Definition: label_block.cc:106
void ReleaseLabel(uint32_t value)
Definition: label_block.cc:98
friend void intrusive_ptr_release(LabelBlock *block)
Definition: label_block.h:115
std::mutex mutex_
Definition: label_block.h:107
uint32_t AllocateLabel()
Definition: label_block.cc:77
size_t prev_pos_
Definition: label_block.h:102
uint32_t last()
Definition: label_block.h:91
friend class LabelBlockTest
Definition: label_block.h:96
void intrusive_ptr_release(LabelBlockManager *block_manager)
Definition: label_block.h:60
boost::intrusive_ptr< LabelBlock > LabelBlockPtr
Definition: label_block.h:19
void intrusive_ptr_add_ref(LabelBlockManager *block_manager)
Definition: label_block.h:56
boost::intrusive_ptr< LabelBlockManager > LabelBlockManagerPtr
Definition: label_block.h:16