00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00027 #include "ShMemory.hpp"
00028 #include "ShDebug.hpp"
00029 #include <cstring>
00030 #include <algorithm>
00031
00032 namespace SH {
00033
00035
00037
00038 ShMemory::~ShMemory()
00039 {
00040 for (StorageList::iterator I = m_storages.begin(); I != m_storages.end(); ++I) {
00041 (*I)->orphan();
00042
00043 }
00044 }
00045
00046 int ShMemory::timestamp() const
00047 {
00048 return m_timestamp;
00049 }
00050
00051 ShPointer<ShStorage> ShMemory::findStorage(const std::string& id)
00052 {
00053 for (StorageList::iterator I = m_storages.begin(); I != m_storages.end(); ++I) {
00054 if ((*I)->id() == id) return *I;
00055 }
00056 return 0;
00057 }
00058
00059 ShMemory::ShMemory()
00060 : m_timestamp(0)
00061 {
00062 }
00063
00064 void ShMemory::updateTimestamp(int timestamp)
00065 {
00066 SH_DEBUG_ASSERT(timestamp >= m_timestamp);
00067 m_timestamp = timestamp;
00068 }
00069
00070 void ShMemory::addStorage(const ShPointer<ShStorage>& storage)
00071 {
00072 m_storages.push_back(storage);
00073 }
00074
00075 void ShMemory::removeStorage(const ShPointer<ShStorage>& storage)
00076 {
00077 StorageList::iterator I = std::find(m_storages.begin(), m_storages.end(), storage);
00078 if (I == m_storages.end()) return;
00079 (*I)->orphan();
00080 m_storages.erase(I);
00081
00082
00083 }
00084
00085 void ShMemory::add_dep(ShMemoryDep* dep)
00086 {
00087 dependencies.push_back(dep);
00088 }
00089
00090 void ShMemory::flush()
00091 {
00092 ShHostStoragePtr storage = shref_dynamic_cast<ShHostStorage>(findStorage("host"));
00093 storage->dirtyall();
00094 for(std::list<ShMemoryDep*>::iterator i = dependencies.begin() ; i != dependencies.end() ; i++)
00095 (*i)->memory_update();
00096 }
00097
00099
00101 ShTransfer::ShTransfer(const std::string& from, const std::string& to)
00102 {
00103 ShStorage::addTransfer(from, to, this);
00104 }
00105
00106
00108
00110 ShStorage::ShStorage()
00111 : m_timestamp(-1)
00112 {
00113 }
00114
00115 ShStorage::~ShStorage()
00116 {
00117 if (m_memory) {
00118 m_memory->removeStorage(this);
00119 }
00120 }
00121
00122 int ShStorage::timestamp() const
00123 {
00124 return m_timestamp;
00125 }
00126
00127 void ShStorage::setTimestamp(int timestamp)
00128 {
00129 SH_DEBUG_ASSERT(timestamp >= m_timestamp);
00130
00131 m_timestamp = timestamp;
00132 }
00133
00134 const ShMemory* ShStorage::memory() const
00135 {
00136 return m_memory;
00137 }
00138
00139 ShMemory* ShStorage::memory()
00140 {
00141 return m_memory;
00142 }
00143
00144 void ShStorage::orphan()
00145 {
00146 m_memory = 0;
00147 }
00148
00149 void ShStorage::sync()
00150 {
00151 SH_DEBUG_ASSERT(m_memory);
00152
00153 if (m_memory->timestamp() == timestamp()) return;
00154
00155
00156
00157 ShStorage* source = 0;
00158 int transfer_cost = -1;
00159 ShMemory::StorageList::const_iterator I;
00160 for (I = m_memory->m_storages.begin(); I != m_memory->m_storages.end(); ++I) {
00161 ShStorage* other = I->object();
00162 if (other == this) continue;
00163 if (other->timestamp() < m_memory->timestamp()) continue;
00164 int local_cost = cost(other, this);
00165 if (local_cost < 0) continue;
00166 if (!source || local_cost < transfer_cost) {
00167 source = other;
00168 transfer_cost = local_cost;
00169 }
00170 }
00171
00172
00173 SH_DEBUG_ASSERT(source);
00174
00175
00176
00177
00178 if (!transfer(source, this)) {
00179 SH_DEBUG_WARN("Transfer from " << source << " to " << this << " failed!");
00180 }
00181 }
00182
00183 void ShStorage::dirty()
00184 {
00185
00186 sync();
00187
00188 dirtyall();
00189 }
00190
00191 void ShStorage::dirtyall()
00192 {
00193 m_timestamp++;
00194 m_memory->updateTimestamp(m_timestamp);
00195 }
00196
00197 int ShStorage::cost(ShStorage* from, ShStorage* to)
00198 {
00199 if (!from) return -1;
00200 if (!to) return -1;
00201 if (!m_transfers) return false;
00202
00203 TransferMap::const_iterator I = m_transfers->find(std::make_pair(from->id(), to->id()));
00204 if (I == m_transfers->end()) return -1;
00205
00206 return I->second->cost();
00207 }
00208
00209 bool ShStorage::transfer(ShStorage* from, ShStorage* to)
00210 {
00211 if (!from) return false;
00212 if (!to) return false;
00213 if (!m_transfers) return false;
00214
00215 TransferMap::const_iterator I = m_transfers->find(std::make_pair(from->id(), to->id()));
00216 if (I == m_transfers->end()) return false;
00217
00218
00219
00220
00221 if (I->second->transfer(from, to)) {
00222 to->setTimestamp(from->timestamp());
00223 return true;
00224 } else {
00225 return false;
00226 }
00227 }
00228
00229 void ShStorage::addTransfer(const std::string& from,
00230 const std::string& to,
00231 ShTransfer* transfer)
00232 {
00233 if (!m_transfers) m_transfers = new TransferMap();
00234 (*m_transfers)[std::make_pair(from, to)] = transfer;
00235 }
00236
00237 ShStorage::ShStorage(ShMemory* memory)
00238 : m_memory(memory), m_timestamp(-1)
00239 {
00240 m_memory->addStorage(this);
00241 }
00242
00243 ShStorage::TransferMap* ShStorage::m_transfers = 0;
00244
00246
00248
00249 ShHostStorage::ShHostStorage(ShMemory* memory, int length)
00250 : ShStorage(memory),
00251 m_length(length),
00252 m_data(new char[length]),
00253 m_managed(true)
00254 {
00255 }
00256
00257 ShHostStorage::ShHostStorage(ShMemory* memory, int length, void* data)
00258 : ShStorage(memory),
00259 m_length(length),
00260 m_data(data),
00261 m_managed(false)
00262 {
00263 }
00264
00265 ShHostStorage::~ShHostStorage()
00266 {
00267 if (m_managed) {
00268 delete [] reinterpret_cast<char*>(m_data);
00269 }
00270 }
00271
00272 std::string ShHostStorage::id() const
00273 {
00274 return "host";
00275 }
00276
00277
00278 int ShHostStorage::length() const
00279 {
00280 return m_length;
00281 }
00282
00283 const void* ShHostStorage::data() const
00284 {
00285 return m_data;
00286 }
00287
00288 void* ShHostStorage::data()
00289 {
00290 return m_data;
00291 }
00292
00294
00296
00297 ShHostMemory::ShHostMemory(int length)
00298 : m_hostStorage(new ShHostStorage(this, length))
00299 {
00300 m_hostStorage->setTimestamp(0);
00301 }
00302
00303 ShHostMemory::ShHostMemory(int length, void* data)
00304 : m_hostStorage(new ShHostStorage(this, length, data))
00305 {
00306 m_hostStorage->setTimestamp(0);
00307 }
00308
00309 ShHostMemory::~ShHostMemory()
00310 {
00311 }
00312
00313 ShHostStoragePtr ShHostMemory::hostStorage()
00314 {
00315 return m_hostStorage;
00316 }
00317
00318 ShPointer<const ShHostStorage> ShHostMemory::hostStorage() const
00319 {
00320 return m_hostStorage;
00321 }
00322
00323 class ShHostHostTransfer : public ShTransfer {
00324 public:
00325 bool transfer(const ShStorage* from, ShStorage* to)
00326 {
00327 const ShHostStorage* host_from = dynamic_cast<const ShHostStorage*>(from);
00328 ShHostStorage* host_to = dynamic_cast<ShHostStorage*>(to);
00329
00330
00331 if (!host_from) return false;
00332 if (!host_to) return false;
00333
00334
00335 if (host_from->length() != host_to->length()) return false;
00336
00337 std::memcpy(host_to->data(), host_from->data(), host_to->length());
00338
00339 return true;
00340 }
00341
00342 int cost()
00343 {
00344 return 10;
00345 }
00346
00347 private:
00348 ShHostHostTransfer()
00349 : ShTransfer("host", "host")
00350 {
00351 }
00352
00353 static ShHostHostTransfer* instance;
00354 };
00355
00356 ShHostHostTransfer* ShHostHostTransfer::instance = new ShHostHostTransfer();
00357
00358 }