| 48 | 
  | 
namespace oopse { | 
| 49 | 
  | 
BlockSnapshotManager::BlockSnapshotManager(SimInfo* info, const std::string& filename,  | 
| 50 | 
  | 
    int storageLayout, int blockCapacity)  | 
| 51 | 
< | 
    : SnapshotManager(storageLayout), info_(info), blockCapacity_(blockCapacity), activeBlocks_(blockCapacity_, -1) { | 
| 51 | 
> | 
    : SnapshotManager(storageLayout), info_(info), blockCapacity_(blockCapacity),  | 
| 52 | 
> | 
      activeBlocks_(blockCapacity_, -1), activeRefCount_(blockCapacity_, 0) { | 
| 53 | 
  | 
 | 
| 54 | 
  | 
    nAtoms_ = info->getNGlobalAtoms(); | 
| 55 | 
  | 
    nRigidBodies_ = info->getNGlobalRigidBodies(); | 
| 107 | 
  | 
#endif | 
| 108 | 
  | 
} | 
| 109 | 
  | 
 | 
| 109 | 
– | 
bool BlockSnapshotManager::isBlockActive(int block) { | 
| 110 | 
– | 
    return std::find(activeBlocks_.begin(), activeBlocks_.end(), block) != activeBlocks_.end() ? true : false; | 
| 111 | 
– | 
} | 
| 110 | 
  | 
 | 
| 111 | 
+ | 
 | 
| 112 | 
  | 
bool BlockSnapshotManager::loadBlock(int block) { | 
| 113 | 
+ | 
    std::vector<int>::iterator i = findActiveBlock(block); | 
| 114 | 
  | 
    bool loadSuccess; | 
| 115 | 
< | 
    if (isBlockActive(block)) { | 
| 115 | 
> | 
    if (i != activeBlocks_.end()) { | 
| 116 | 
> | 
        //if block is already in memory, just increast the reference count | 
| 117 | 
> | 
        ++activeRefCount_[i - activeBlocks_.begin()]; | 
| 118 | 
  | 
        loadSuccess = true; | 
| 119 | 
  | 
    } else if (getNActiveBlocks() < blockCapacity_){ | 
| 120 | 
< | 
 | 
| 121 | 
< | 
        for (int i = blocks_[block].first; i < blocks_[block].second; ++i) { | 
| 120 | 
< | 
            snapshots_[i] = loadFrame(i); | 
| 121 | 
< | 
        } | 
| 122 | 
< | 
         | 
| 123 | 
< | 
        std::vector<int>::iterator j; | 
| 124 | 
< | 
        j = std::find(activeBlocks_.begin(), activeBlocks_.end(), -1); | 
| 125 | 
< | 
        assert(j != activeBlocks_.end()); | 
| 126 | 
< | 
        *j = block;     | 
| 120 | 
> | 
        //if number of active blocks is less than the block capacity, just load it | 
| 121 | 
> | 
        internalLoad(block); | 
| 122 | 
  | 
        loadSuccess = true; | 
| 123 | 
< | 
    }else { | 
| 123 | 
> | 
    } else if (hasZeroRefBlock() > 0) { | 
| 124 | 
> | 
        //if already reach the block capacity, need to unload a block with 0 reference | 
| 125 | 
> | 
        int zeroRefBlock = getFirstZeroRefBlock(); | 
| 126 | 
> | 
        assert(zeroRefBlock != -1); | 
| 127 | 
> | 
        internalUnload(zeroRefBlock); | 
| 128 | 
> | 
        internalLoad(block); | 
| 129 | 
> | 
    } else { | 
| 130 | 
> | 
        //reach the capacity and all blocks in memory are not zero reference | 
| 131 | 
  | 
        loadSuccess = false; | 
| 132 | 
  | 
    } | 
| 133 | 
< | 
 | 
| 133 | 
> | 
     | 
| 134 | 
  | 
    return loadSuccess; | 
| 135 | 
  | 
} | 
| 136 | 
  | 
 | 
| 137 | 
  | 
bool BlockSnapshotManager::unloadBlock(int block) { | 
| 138 | 
  | 
    bool unloadSuccess; | 
| 139 | 
< | 
    if (!isBlockActive(block)){ | 
| 140 | 
< | 
        unloadSuccess = false; | 
| 141 | 
< | 
    } else { | 
| 142 | 
< | 
        for (int i = blocks_[block].first; i < blocks_[block].second; ++i) { | 
| 143 | 
< | 
            delete snapshots_[i]; | 
| 144 | 
< | 
            snapshots_[i] = NULL; | 
| 139 | 
> | 
    std::vector<int>::iterator i = findActiveBlock(block); | 
| 140 | 
> | 
     | 
| 141 | 
> | 
    if (i != activeBlocks_.end()){ | 
| 142 | 
> | 
        --activeRefCount_[i - activeBlocks_.begin()]; | 
| 143 | 
> | 
        if (activeRefCount_[i - activeBlocks_.begin()] < 0) { | 
| 144 | 
> | 
            //in case, unloadBlock called multiple times | 
| 145 | 
> | 
            activeRefCount_[i - activeBlocks_.begin()]  = 0; | 
| 146 | 
  | 
        } | 
| 147 | 
< | 
        std::vector<int>::iterator j; | 
| 145 | 
< | 
        j = std::find(activeBlocks_.begin(), activeBlocks_.end(), block); | 
| 146 | 
< | 
        assert(j != activeBlocks_.end()); | 
| 147 | 
< | 
        *j = -1; | 
| 147 | 
> | 
         | 
| 148 | 
  | 
        unloadSuccess = true; | 
| 149 | 
+ | 
    } else { | 
| 150 | 
+ | 
        unloadSuccess = false; | 
| 151 | 
  | 
    } | 
| 152 | 
  | 
 | 
| 153 | 
  | 
    return unloadSuccess; | 
| 154 | 
  | 
} | 
| 155 | 
  | 
 | 
| 156 | 
+ | 
void BlockSnapshotManager::internalLoad(int block) { | 
| 157 | 
+ | 
         | 
| 158 | 
+ | 
    for (int i = blocks_[block].first; i < blocks_[block].second; ++i) { | 
| 159 | 
+ | 
        snapshots_[i] = loadFrame(i); | 
| 160 | 
+ | 
    } | 
| 161 | 
+ | 
     | 
| 162 | 
+ | 
    std::vector<int>::iterator j; | 
| 163 | 
+ | 
    j = std::find(activeBlocks_.begin(), activeBlocks_.end(), -1); | 
| 164 | 
+ | 
    assert(j != activeBlocks_.end()); | 
| 165 | 
+ | 
    *j = block;     | 
| 166 | 
+ | 
    ++activeRefCount_[j - activeBlocks_.begin()]; | 
| 167 | 
+ | 
} | 
| 168 | 
+ | 
 | 
| 169 | 
+ | 
void BlockSnapshotManager::internalUnload(int block) { | 
| 170 | 
+ | 
    for (int i = blocks_[block].first; i < blocks_[block].second; ++i) { | 
| 171 | 
+ | 
        delete snapshots_[i]; | 
| 172 | 
+ | 
        snapshots_[i] = NULL; | 
| 173 | 
+ | 
    } | 
| 174 | 
+ | 
    std::vector<int>::iterator j; | 
| 175 | 
+ | 
    j = std::find(activeBlocks_.begin(), activeBlocks_.end(), block); | 
| 176 | 
+ | 
    assert(j != activeBlocks_.end()); | 
| 177 | 
+ | 
    *j = -1; | 
| 178 | 
+ | 
} | 
| 179 | 
+ | 
 | 
| 180 | 
+ | 
bool BlockSnapshotManager::hasZeroRefBlock(){ | 
| 181 | 
+ | 
    return std::find(activeRefCount_.begin(), activeRefCount_.end(), 0) != activeRefCount_.end() ?  true : false; | 
| 182 | 
+ | 
} | 
| 183 | 
+ | 
 | 
| 184 | 
+ | 
int BlockSnapshotManager::getFirstZeroRefBlock(){ | 
| 185 | 
+ | 
     std::vector<int>::iterator i = std::find(activeRefCount_.begin(), activeRefCount_.end(), 0); | 
| 186 | 
+ | 
     return i != activeRefCount_.end() ? activeBlocks_[i - activeRefCount_.begin()] : -1; | 
| 187 | 
+ | 
} | 
| 188 | 
+ | 
 | 
| 189 | 
  | 
std::vector<int> BlockSnapshotManager::getActiveBlocks() { | 
| 190 | 
  | 
    std::vector<int> result; | 
| 191 | 
  | 
    oopse::copy_if(activeBlocks_.begin(), activeBlocks_.end(), std::back_inserter(result),  |