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
00086
00088 ShTransfer::ShTransfer(
const std::string& from,
const std::string& to)
00089 {
00090 ShStorage::addTransfer(from, to,
this);
00091 }
00092
00093
00095
00097 ShStorage::ShStorage()
00098 : m_timestamp(-1)
00099 {
00100 }
00101
00102 ShStorage::~ShStorage()
00103 {
00104
if (m_memory) {
00105 m_memory->removeStorage(
this);
00106 }
00107 }
00108
00109 int ShStorage::timestamp()
const
00110
{
00111
return m_timestamp;
00112 }
00113
00114 void ShStorage::setTimestamp(
int timestamp)
00115 {
00116 SH_DEBUG_ASSERT(timestamp >= m_timestamp);
00117
00118 m_timestamp = timestamp;
00119 }
00120
00121 const ShMemory* ShStorage::memory()
const
00122
{
00123
return m_memory;
00124 }
00125
00126 ShMemory* ShStorage::memory()
00127 {
00128
return m_memory;
00129 }
00130
00131 void ShStorage::orphan()
00132 {
00133 m_memory = 0;
00134 }
00135
00136 void ShStorage::sync()
00137 {
00138 SH_DEBUG_ASSERT(m_memory);
00139
00140
if (m_memory->
timestamp() ==
timestamp())
return;
00141
00142
00143
00144
ShStorage* source = 0;
00145
int transfer_cost = -1;
00146 ShMemory::StorageList::const_iterator I;
00147
for (I = m_memory->
m_storages.begin(); I != m_memory->
m_storages.end(); ++I) {
00148
ShStorage* other = I->object();
00149
if (other ==
this)
continue;
00150
if (other->
timestamp() < m_memory->
timestamp())
continue;
00151
int local_cost =
cost(other,
this);
00152
if (local_cost < 0)
continue;
00153
if (!source || local_cost < transfer_cost) {
00154 source = other;
00155 transfer_cost = local_cost;
00156 }
00157 }
00158
00159
00160 SH_DEBUG_ASSERT(source);
00161
00162
00163
00164
00165
if (!
transfer(source,
this)) {
00166 SH_DEBUG_WARN(
"Transfer from " << source <<
" to " <<
this <<
" failed!");
00167 }
00168 }
00169
00170 void ShStorage::dirty()
00171 {
00172
00173
sync();
00174
00175
00176
00177
00178 m_timestamp++;
00179 m_memory->
updateTimestamp(m_timestamp);
00180 }
00181
00182 int ShStorage::cost(
ShStorage* from,
ShStorage* to)
00183 {
00184
if (!from)
return -1;
00185
if (!to)
return -1;
00186
if (!m_transfers)
return false;
00187
00188 TransferMap::const_iterator I = m_transfers->find(std::make_pair(from->
id(), to->
id()));
00189
if (I == m_transfers->end())
return -1;
00190
00191
return I->second->cost();
00192 }
00193
00194 bool ShStorage::transfer(
ShStorage* from,
ShStorage* to)
00195 {
00196
if (!from)
return false;
00197
if (!to)
return false;
00198
if (!m_transfers)
return false;
00199
00200 TransferMap::const_iterator I = m_transfers->find(std::make_pair(from->
id(), to->
id()));
00201
if (I == m_transfers->end())
return false;
00202
00203
00204
00205
00206
if (I->second->transfer(from, to)) {
00207 to->
setTimestamp(from->
timestamp());
00208
return true;
00209 }
else {
00210
return false;
00211 }
00212 }
00213
00214 void ShStorage::addTransfer(
const std::string& from,
00215
const std::string& to,
00216
ShTransfer* transfer)
00217 {
00218
if (!m_transfers) m_transfers =
new TransferMap();
00219 (*m_transfers)[std::make_pair(from, to)] = transfer;
00220 }
00221
00222 ShStorage::ShStorage(
ShMemory* memory)
00223 : m_memory(memory), m_timestamp(-1)
00224 {
00225 m_memory->
addStorage(
this);
00226 }
00227
00228 ShStorage::TransferMap* ShStorage::m_transfers = 0;
00229
00231
00233
00234 ShHostStorage::ShHostStorage(
ShMemory* memory,
int length)
00235 :
ShStorage(memory),
00236 m_length(
length),
00237 m_data(new char[
length]),
00238 m_managed(true)
00239 {
00240 }
00241
00242 ShHostStorage::ShHostStorage(
ShMemory* memory,
int length,
void* data)
00243 :
ShStorage(memory),
00244 m_length(
length),
00245 m_data(data),
00246 m_managed(false)
00247 {
00248 }
00249
00250 ShHostStorage::~ShHostStorage()
00251 {
00252
if (m_managed) {
00253
delete [] reinterpret_cast<char*>(m_data);
00254 }
00255 }
00256
00257 std::string ShHostStorage::id()
const
00258
{
00259
return "host";
00260 }
00261
00262
00263 int ShHostStorage::length()
const
00264
{
00265
return m_length;
00266 }
00267
00268 const void* ShHostStorage::data()
const
00269
{
00270
return m_data;
00271 }
00272
00273 void* ShHostStorage::data()
00274 {
00275
return m_data;
00276 }
00277
00279
00281
00282 ShHostMemory::ShHostMemory(
int length)
00283 : m_hostStorage(new
ShHostStorage(this,
length))
00284 {
00285 m_hostStorage->setTimestamp(0);
00286 }
00287
00288 ShHostMemory::ShHostMemory(
int length,
void* data)
00289 : m_hostStorage(new ShHostStorage(this, length, data))
00290 {
00291 m_hostStorage->setTimestamp(0);
00292 }
00293
00294 ShHostMemory::~ShHostMemory()
00295 {
00296 }
00297
00298 ShHostStoragePtr ShHostMemory::hostStorage()
00299 {
00300
return m_hostStorage;
00301 }
00302
00303 ShPointer<const ShHostStorage> ShHostMemory::hostStorage()
const
00304
{
00305
return m_hostStorage;
00306 }
00307
00308
class ShHostHostTransfer :
public ShTransfer {
00309
public:
00310
bool transfer(
const ShStorage* from, ShStorage* to)
00311 {
00312
const ShHostStorage* host_from = dynamic_cast<const ShHostStorage*>(from);
00313 ShHostStorage* host_to = dynamic_cast<ShHostStorage*>(to);
00314
00315
00316
if (!host_from)
return false;
00317
if (!host_to)
return false;
00318
00319
00320
if (host_from->length() != host_to->length())
return false;
00321
00322 std::memcpy(host_to->data(), host_from->data(), host_to->length());
00323
00324
return true;
00325 }
00326
00327
int cost()
00328 {
00329
return 10;
00330 }
00331
00332
private:
00333 ShHostHostTransfer()
00334 : ShTransfer("host", "host")
00335 {
00336 }
00337
00338
static ShHostHostTransfer* instance;
00339 };
00340
00341 ShHostHostTransfer* ShHostHostTransfer::instance =
new ShHostHostTransfer();
00342
00343 }