FairMQ/fairmq/shmem/Manager.cxx
Alexey Rybalchenko 58a312b730 FairMQ: Introduce callbacks for the FairMQUnmanagedRegion.
Callbacks are called when the data buffer of the message assiciated
with the corresponding region is no longer needed by the transport.
Example in examples/advanced/Region/
2017-11-29 09:06:17 +01:00

142 lines
3.5 KiB
C++

/********************************************************************************
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence version 3 (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "Manager.h"
#include "Common.h"
namespace fair
{
namespace mq
{
namespace shmem
{
using namespace std;
namespace bipc = boost::interprocess;
Manager::Manager(const string& name, size_t size)
: fName(name)
, fSegment(bipc::open_or_create, fName.c_str(), size)
, fManagementSegment(bipc::open_or_create, "fmq_shm_management", 65536)
, fRegions()
{}
bipc::managed_shared_memory& Manager::Segment()
{
return fSegment;
}
void Manager::Interrupt()
{
}
void Manager::Resume()
{
// close remote regions before processing new transfers
for (auto it = fRegions.begin(); it != fRegions.end(); /**/)
{
if (it->second.fRemote)
{
it = fRegions.erase(it);
}
else
{
++it;
}
}
}
bipc::mapped_region* Manager::CreateRegion(const size_t size, const uint64_t id, FairMQRegionCallback callback)
{
auto it = fRegions.find(id);
if (it != fRegions.end())
{
LOG(ERROR) << "shmem: Trying to create a region that already exists";
return nullptr;
}
else
{
auto r = fRegions.emplace(id, Region{*this, id, size, false, callback});
r.first->second.StartReceivingAcks();
return &(r.first->second.fRegion);
}
}
bipc::mapped_region* Manager::GetRemoteRegion(const uint64_t id)
{
// remote region could actually be a local one if a message originates from this device (has been sent out and returned)
auto it = fRegions.find(id);
if (it != fRegions.end())
{
return &(it->second.fRegion);
}
else
{
try
{
auto r = fRegions.emplace(id, Region{*this, id, 0, true, nullptr});
return &(r.first->second.fRegion);
}
catch (bipc::interprocess_exception& e)
{
// LOG(WARN) << "remote region (" << id << ") no longer exists";
return nullptr;
}
}
}
void Manager::RemoveRegion(const uint64_t id)
{
fRegions.erase(id);
}
bipc::message_queue* Manager::GetRegionQueue(const uint64_t id)
{
try
{
return fRegions.at(id).fQueue.get();
}
catch (out_of_range& oor)
{
return nullptr;
}
}
void Manager::RemoveSegment()
{
if (bipc::shared_memory_object::remove(fName.c_str()))
{
LOG(DEBUG) << "shmem: successfully removed " << fName << " segment after the device has stopped.";
}
else
{
LOG(DEBUG) << "shmem: did not remove " << fName << " segment after the device stopped. Already removed?";
}
if (bipc::shared_memory_object::remove("fmq_shm_management"))
{
LOG(DEBUG) << "shmem: successfully removed \"fmq_shm_management\" segment after the device has stopped.";
}
else
{
LOG(DEBUG) << "shmem: did not remove \"fmq_shm_management\" segment after the device stopped. Already removed?";
}
}
bipc::managed_shared_memory& Manager::ManagementSegment()
{
return fManagementSegment;
}
} // namespace shmem
} // namespace mq
} // namespace fair