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(); |
73 |
|
} |
74 |
|
|
75 |
|
for (int i = 0; i < nblocks; ++i) { |
76 |
< |
blocks_.push_back(SnapshotBlock(i, (i+1)*nSnapshotPerBlock_)); |
76 |
> |
blocks_.push_back(SnapshotBlock(i*nSnapshotPerBlock_, (i+1)*nSnapshotPerBlock_)); |
77 |
|
} |
78 |
|
//the last block may not have nSnapshotPerBlock frames, we need to consider this special situation |
79 |
|
blocks_.back().second = nframes_; |
80 |
|
|
81 |
< |
snapshots_.insert(snapshots_.begin(), nframes_, NULL); |
81 |
> |
snapshots_.insert(snapshots_.begin(), nframes_, static_cast<Snapshot*>(NULL)); |
82 |
|
|
83 |
|
} |
84 |
|
|
98 |
|
} |
99 |
|
|
100 |
|
int BlockSnapshotManager::getNActiveBlocks() { |
101 |
+ |
#ifdef __RWSTD |
102 |
+ |
int count = 0; |
103 |
+ |
std::count_if(activeBlocks_.begin(), activeBlocks_.end(), std::bind2nd(std::not_equal_to<int>(), -1), count); |
104 |
+ |
return count; |
105 |
+ |
#else |
106 |
|
return std::count_if(activeBlocks_.begin(), activeBlocks_.end(), std::bind2nd(std::not_equal_to<int>(), -1)); |
107 |
+ |
#endif |
108 |
|
} |
109 |
|
|
103 |
– |
bool BlockSnapshotManager::isBlockActive(int block) { |
104 |
– |
return std::find(activeBlocks_.begin(), activeBlocks_.end(), block) != activeBlocks_.end() ? true : false; |
105 |
– |
} |
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) { |
114 |
< |
snapshots_[i] = loadFrame(i); |
115 |
< |
} |
116 |
< |
|
117 |
< |
std::vector<int>::iterator j; |
118 |
< |
j = std::find(activeBlocks_.begin(), activeBlocks_.end(), -1); |
119 |
< |
assert(j != activeBlocks_.end()); |
120 |
< |
*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; |
139 |
< |
j = std::find(activeBlocks_.begin(), activeBlocks_.end(), block); |
140 |
< |
assert(j != activeBlocks_.end()); |
141 |
< |
*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); |
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), |