Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #include "base/label_block.h" 6 : 7 : #include <stdio.h> 8 : 9 : #include <cassert> 10 : #include <string> 11 : 12 : using std::string; 13 : 14 10061 : LabelBlockManager::LabelBlockManager() { 15 10061 : refcount_ = 0; 16 10061 : } 17 : 18 10061 : LabelBlockManager::~LabelBlockManager() { 19 10061 : assert(blocks_.size() == 0); 20 10061 : } 21 : 22 1790 : LabelBlockPtr LabelBlockManager::LocateBlock(uint32_t first, uint32_t last) { 23 1790 : std::scoped_lock lock(mutex_); 24 : 25 1792 : for (LabelBlockList::iterator it = blocks_.begin(); 26 1975 : it != blocks_.end(); ++it) { 27 1137 : LabelBlock *block = *it; 28 1137 : if (block->first_ == first && block->last_ == last) { 29 954 : return LabelBlockPtr(block); 30 : } 31 : } 32 : 33 838 : LabelBlock *block = new LabelBlock(this, first, last); 34 838 : blocks_.push_back(block); 35 836 : return LabelBlockPtr(block); 36 1792 : } 37 : 38 838 : void LabelBlockManager::RemoveBlock(LabelBlock *block) { 39 838 : for (LabelBlockList::iterator it = blocks_.begin(); 40 928 : it != blocks_.end(); ++it) { 41 928 : if (*it == block) { 42 838 : blocks_.erase(it); 43 838 : return; 44 : } 45 : } 46 0 : assert(false); 47 : } 48 : 49 1066 : size_t LabelBlockManager::size() { 50 1066 : std::scoped_lock lock(mutex_); 51 2134 : return blocks_.size(); 52 1067 : } 53 : 54 6480 : LabelBlock::LabelBlock(uint32_t first, uint32_t last) 55 6480 : : block_manager_(NULL), 56 6480 : first_(first), 57 6480 : last_(last), 58 6480 : prev_pos_(BitSet::npos) { 59 6480 : refcount_ = 0; 60 6481 : } 61 : 62 838 : LabelBlock::LabelBlock( 63 838 : LabelBlockManager *block_manager, uint32_t first, uint32_t last) 64 838 : : block_manager_(block_manager), 65 838 : first_(first), 66 838 : last_(last), 67 838 : prev_pos_(BitSet::npos) { 68 838 : refcount_ = 0; 69 838 : } 70 : 71 7319 : LabelBlock::~LabelBlock() { 72 7319 : assert(used_bitset_.empty()); 73 7319 : if (block_manager_) 74 838 : block_manager_->RemoveBlock(this); 75 7319 : } 76 : 77 5841 : uint32_t LabelBlock::AllocateLabel() { 78 5841 : std::scoped_lock lock(mutex_); 79 : 80 : size_t pos; 81 6390 : for (int idx = 0; idx < 2; prev_pos_ = BitSet::npos, idx++) { 82 6377 : if (prev_pos_ == BitSet::npos) { 83 2200 : pos = used_bitset_.find_first_clear(); 84 : } else { 85 4177 : pos = used_bitset_.find_next_clear(prev_pos_); 86 : } 87 : 88 6377 : if (first_ + pos <= last_) { 89 5828 : used_bitset_.set(pos); 90 5828 : prev_pos_ = pos; 91 5828 : return static_cast<uint32_t>(first_ + pos); 92 : } 93 : } 94 : 95 13 : return 0; 96 5841 : } 97 : 98 5828 : void LabelBlock::ReleaseLabel(uint32_t value) { 99 5828 : std::scoped_lock lock(mutex_); 100 : 101 5828 : assert(value >= first_ && value <= last_); 102 5828 : size_t pos = value - first_; 103 5828 : used_bitset_.reset(pos); 104 5828 : } 105 : 106 8 : string LabelBlock::ToString() const { 107 : char repr[32]; 108 8 : snprintf(repr, sizeof(repr), "%u-%u", first_, last_); 109 8 : return repr; 110 : }