2016-01-07 13:19:55 -05:00
|
|
|
#ifndef SHARED_MEMORY_HPP
|
|
|
|
#define SHARED_MEMORY_HPP
|
2013-09-17 08:23:06 -04:00
|
|
|
|
2016-01-28 08:27:05 -05:00
|
|
|
#include "util/exception.hpp"
|
2016-01-02 11:13:44 -05:00
|
|
|
#include "util/simple_logger.hpp"
|
2013-09-17 08:23:06 -04:00
|
|
|
|
|
|
|
#include <boost/filesystem.hpp>
|
2013-09-26 05:28:51 -04:00
|
|
|
#include <boost/filesystem/fstream.hpp>
|
2013-09-17 08:23:06 -04:00
|
|
|
#include <boost/interprocess/mapped_region.hpp>
|
2014-04-07 07:07:27 -04:00
|
|
|
#ifndef WIN32
|
2013-09-17 08:23:06 -04:00
|
|
|
#include <boost/interprocess/xsi_shared_memory.hpp>
|
2014-04-07 07:07:27 -04:00
|
|
|
#else
|
|
|
|
#include <boost/interprocess/shared_memory_object.hpp>
|
|
|
|
#endif
|
2013-09-17 08:23:06 -04:00
|
|
|
|
2013-11-14 12:33:09 -05:00
|
|
|
#ifdef __linux__
|
|
|
|
#include <sys/ipc.h>
|
|
|
|
#include <sys/shm.h>
|
|
|
|
#endif
|
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
// #include <cstring>
|
2014-05-07 08:46:46 -04:00
|
|
|
#include <cstdint>
|
2013-11-19 04:38:59 -05:00
|
|
|
|
2013-09-17 08:23:06 -04:00
|
|
|
#include <algorithm>
|
|
|
|
#include <exception>
|
|
|
|
|
2016-01-05 10:51:13 -05:00
|
|
|
namespace osrm
|
|
|
|
{
|
2016-01-07 13:19:55 -05:00
|
|
|
namespace storage
|
2016-01-05 10:51:13 -05:00
|
|
|
{
|
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
struct OSRMLockFile
|
|
|
|
{
|
|
|
|
boost::filesystem::path operator()()
|
|
|
|
{
|
|
|
|
boost::filesystem::path temp_dir = boost::filesystem::temp_directory_path();
|
|
|
|
boost::filesystem::path lock_file = temp_dir / "osrm.lock";
|
|
|
|
return lock_file;
|
|
|
|
}
|
2013-09-17 08:23:06 -04:00
|
|
|
};
|
|
|
|
|
2014-04-07 07:07:27 -04:00
|
|
|
#ifndef WIN32
|
2014-05-07 12:39:16 -04:00
|
|
|
class SharedMemory
|
|
|
|
{
|
|
|
|
|
|
|
|
// Remove shared memory on destruction
|
|
|
|
class shm_remove
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
int m_shmid;
|
|
|
|
bool m_initialized;
|
|
|
|
|
|
|
|
public:
|
|
|
|
void SetID(int shmid)
|
|
|
|
{
|
|
|
|
m_shmid = shmid;
|
|
|
|
m_initialized = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
shm_remove() : m_shmid(INT_MIN), m_initialized(false) {}
|
Takes care of proper special member generation globally, fixes #1689
Phew, a lot of classes were affected by this. The rationale for the
changes are as follows:
- When a type X declares any constructor, the default constructor is
not declared, so there is no need for X() = delete there. In fact,
there is brutal difference between those two: deleted members
participate in overload resolution, but not-declared members do not!
- When a type X wants to be non-copyable (e.g. to be only movable, like
threads, unique_ptrs, and so on), you can either do it by inheriting
from boost::noncopyable (the old way), or better declare both (!) the
copy constructor _and_ the copy assignment operator as deleted:
X(X const&) = delete;
X& operator=(X const&) = delete;
We had tons of types with deleted copy constructors that were lacking
a corresponding deleted copy assignment operator, making them still
copyable and you wouldn't even notice (read: scary)!
References:
- http://accu.org/content/conf2014/Howard_Hinnant_Accu_2014.pdf
- http://www.boost.org/doc/libs/master/libs/core/doc/html/core/noncopyable.html
Note: I know, I'm quoting Hinnant's extraordinary slides a lot, but
getting the sematic right here is so incredibly important.
2016-01-27 05:20:55 -05:00
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
shm_remove(const shm_remove &) = delete;
|
Takes care of proper special member generation globally, fixes #1689
Phew, a lot of classes were affected by this. The rationale for the
changes are as follows:
- When a type X declares any constructor, the default constructor is
not declared, so there is no need for X() = delete there. In fact,
there is brutal difference between those two: deleted members
participate in overload resolution, but not-declared members do not!
- When a type X wants to be non-copyable (e.g. to be only movable, like
threads, unique_ptrs, and so on), you can either do it by inheriting
from boost::noncopyable (the old way), or better declare both (!) the
copy constructor _and_ the copy assignment operator as deleted:
X(X const&) = delete;
X& operator=(X const&) = delete;
We had tons of types with deleted copy constructors that were lacking
a corresponding deleted copy assignment operator, making them still
copyable and you wouldn't even notice (read: scary)!
References:
- http://accu.org/content/conf2014/Howard_Hinnant_Accu_2014.pdf
- http://www.boost.org/doc/libs/master/libs/core/doc/html/core/noncopyable.html
Note: I know, I'm quoting Hinnant's extraordinary slides a lot, but
getting the sematic right here is so incredibly important.
2016-01-27 05:20:55 -05:00
|
|
|
shm_remove &operator=(const shm_remove &) = delete;
|
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
~shm_remove()
|
|
|
|
{
|
|
|
|
if (m_initialized)
|
|
|
|
{
|
2016-01-05 10:51:13 -05:00
|
|
|
util::SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
|
2014-05-07 12:39:16 -04:00
|
|
|
if (!boost::interprocess::xsi_shared_memory::remove(m_shmid))
|
|
|
|
{
|
2016-01-05 10:51:13 -05:00
|
|
|
util::SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
|
2014-05-07 12:39:16 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
|
|
|
void *Ptr() const { return region.get_address(); }
|
|
|
|
|
|
|
|
SharedMemory(const SharedMemory &) = delete;
|
2016-01-13 04:57:05 -05:00
|
|
|
SharedMemory &operator=(const SharedMemory &) = delete;
|
2014-05-07 12:39:16 -04:00
|
|
|
|
|
|
|
template <typename IdentifierT>
|
|
|
|
SharedMemory(const boost::filesystem::path &lock_file,
|
|
|
|
const IdentifierT id,
|
|
|
|
const uint64_t size = 0,
|
|
|
|
bool read_write = false,
|
|
|
|
bool remove_prev = true)
|
|
|
|
: key(lock_file.string().c_str(), id)
|
|
|
|
{
|
|
|
|
if (0 == size)
|
|
|
|
{ // read_only
|
|
|
|
shm = boost::interprocess::xsi_shared_memory(boost::interprocess::open_only, key);
|
|
|
|
|
|
|
|
region = boost::interprocess::mapped_region(
|
|
|
|
shm,
|
|
|
|
(read_write ? boost::interprocess::read_write : boost::interprocess::read_only));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // writeable pointer
|
|
|
|
// remove previously allocated mem
|
|
|
|
if (remove_prev)
|
|
|
|
{
|
|
|
|
Remove(key);
|
|
|
|
}
|
2015-01-27 11:44:46 -05:00
|
|
|
shm = boost::interprocess::xsi_shared_memory(boost::interprocess::open_or_create, key,
|
|
|
|
size);
|
2013-11-14 12:33:09 -05:00
|
|
|
#ifdef __linux__
|
2015-08-18 06:56:34 -04:00
|
|
|
if (-1 == shmctl(shm.get_shmid(), SHM_LOCK, nullptr))
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
|
|
|
if (ENOMEM == errno)
|
|
|
|
{
|
2016-01-05 10:51:13 -05:00
|
|
|
util::SimpleLogger().Write(logWARNING) << "could not lock shared memory to RAM";
|
2014-05-07 12:39:16 -04:00
|
|
|
}
|
|
|
|
}
|
2013-11-14 12:33:09 -05:00
|
|
|
#endif
|
2014-05-07 12:39:16 -04:00
|
|
|
region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
|
|
|
|
|
|
|
|
remover.SetID(shm.get_shmid());
|
2016-01-07 19:31:57 -05:00
|
|
|
util::SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size
|
|
|
|
<< " bytes";
|
2014-05-07 12:39:16 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename IdentifierT> static bool RegionExists(const IdentifierT id)
|
|
|
|
{
|
|
|
|
bool result = true;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
OSRMLockFile lock_file;
|
|
|
|
boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
|
|
|
|
result = RegionExists(key);
|
|
|
|
}
|
2015-01-27 11:44:46 -05:00
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
result = false;
|
|
|
|
}
|
2014-05-07 12:39:16 -04:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename IdentifierT> static bool Remove(const IdentifierT id)
|
|
|
|
{
|
|
|
|
OSRMLockFile lock_file;
|
|
|
|
boost::interprocess::xsi_key key(lock_file().string().c_str(), id);
|
|
|
|
return Remove(key);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
static bool RegionExists(const boost::interprocess::xsi_key &key)
|
|
|
|
{
|
|
|
|
bool result = true;
|
2015-01-27 11:44:46 -05:00
|
|
|
try
|
|
|
|
{
|
|
|
|
boost::interprocess::xsi_shared_memory shm(boost::interprocess::open_only, key);
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
result = false;
|
|
|
|
}
|
2014-05-07 12:39:16 -04:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool Remove(const boost::interprocess::xsi_key &key)
|
|
|
|
{
|
|
|
|
bool ret = false;
|
|
|
|
try
|
|
|
|
{
|
2016-01-05 10:51:13 -05:00
|
|
|
util::SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
|
2014-05-07 12:39:16 -04:00
|
|
|
boost::interprocess::xsi_shared_memory xsi(boost::interprocess::open_only, key);
|
|
|
|
ret = boost::interprocess::xsi_shared_memory::remove(xsi.get_shmid());
|
|
|
|
}
|
|
|
|
catch (const boost::interprocess::interprocess_exception &e)
|
|
|
|
{
|
|
|
|
if (e.get_error_code() != boost::interprocess::not_found_error)
|
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
boost::interprocess::xsi_key key;
|
|
|
|
boost::interprocess::xsi_shared_memory shm;
|
|
|
|
boost::interprocess::mapped_region region;
|
|
|
|
shm_remove remover;
|
2013-09-17 08:23:06 -04:00
|
|
|
};
|
2014-04-07 07:07:27 -04:00
|
|
|
#else
|
|
|
|
// Windows - specific code
|
2014-10-20 04:20:58 -04:00
|
|
|
class SharedMemory
|
2014-04-07 07:07:27 -04:00
|
|
|
{
|
2015-01-27 11:44:46 -05:00
|
|
|
SharedMemory(const SharedMemory &) = delete;
|
2016-01-13 04:57:05 -05:00
|
|
|
SharedMemory &operator=(const SharedMemory &) = delete;
|
2014-06-11 09:22:51 -04:00
|
|
|
// Remove shared memory on destruction
|
2014-10-20 04:20:58 -04:00
|
|
|
class shm_remove
|
2014-04-07 07:07:27 -04:00
|
|
|
{
|
|
|
|
private:
|
2014-06-11 09:22:51 -04:00
|
|
|
char *m_shmid;
|
2014-04-07 07:07:27 -04:00
|
|
|
bool m_initialized;
|
2014-06-11 09:22:51 -04:00
|
|
|
|
2014-04-07 07:07:27 -04:00
|
|
|
public:
|
2014-06-11 09:22:51 -04:00
|
|
|
void SetID(char *shmid)
|
2014-04-07 07:07:27 -04:00
|
|
|
{
|
2014-06-11 09:22:51 -04:00
|
|
|
m_shmid = shmid;
|
2014-04-07 07:07:27 -04:00
|
|
|
m_initialized = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
shm_remove() : m_shmid("undefined"), m_initialized(false) {}
|
|
|
|
|
Takes care of proper special member generation globally, fixes #1689
Phew, a lot of classes were affected by this. The rationale for the
changes are as follows:
- When a type X declares any constructor, the default constructor is
not declared, so there is no need for X() = delete there. In fact,
there is brutal difference between those two: deleted members
participate in overload resolution, but not-declared members do not!
- When a type X wants to be non-copyable (e.g. to be only movable, like
threads, unique_ptrs, and so on), you can either do it by inheriting
from boost::noncopyable (the old way), or better declare both (!) the
copy constructor _and_ the copy assignment operator as deleted:
X(X const&) = delete;
X& operator=(X const&) = delete;
We had tons of types with deleted copy constructors that were lacking
a corresponding deleted copy assignment operator, making them still
copyable and you wouldn't even notice (read: scary)!
References:
- http://accu.org/content/conf2014/Howard_Hinnant_Accu_2014.pdf
- http://www.boost.org/doc/libs/master/libs/core/doc/html/core/noncopyable.html
Note: I know, I'm quoting Hinnant's extraordinary slides a lot, but
getting the sematic right here is so incredibly important.
2016-01-27 05:20:55 -05:00
|
|
|
shm_remove(const shm_remove &) = delete;
|
|
|
|
shm_remove &operator=(const shm_remove &) = delete;
|
|
|
|
|
2014-04-07 07:07:27 -04:00
|
|
|
~shm_remove()
|
|
|
|
{
|
2014-06-11 09:22:51 -04:00
|
|
|
if (m_initialized)
|
2014-04-07 07:07:27 -04:00
|
|
|
{
|
2016-01-05 10:51:13 -05:00
|
|
|
util::SimpleLogger().Write(logDEBUG) << "automatic memory deallocation";
|
2014-06-11 09:22:51 -04:00
|
|
|
if (!boost::interprocess::shared_memory_object::remove(m_shmid))
|
2014-04-07 07:07:27 -04:00
|
|
|
{
|
2016-01-05 10:51:13 -05:00
|
|
|
util::SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
|
2014-04-07 07:07:27 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
2014-06-11 09:22:51 -04:00
|
|
|
void *Ptr() const { return region.get_address(); }
|
2014-04-07 07:07:27 -04:00
|
|
|
|
2014-06-11 09:22:51 -04:00
|
|
|
SharedMemory(const boost::filesystem::path &lock_file,
|
|
|
|
const int id,
|
|
|
|
const uint64_t size = 0,
|
|
|
|
bool read_write = false,
|
|
|
|
bool remove_prev = true)
|
2014-04-07 07:07:27 -04:00
|
|
|
{
|
2014-06-11 09:22:51 -04:00
|
|
|
sprintf(key, "%s.%d", "osrm.lock", id);
|
|
|
|
if (0 == size)
|
|
|
|
{ // read_only
|
2014-04-07 07:07:27 -04:00
|
|
|
shm = boost::interprocess::shared_memory_object(
|
2015-01-27 11:44:46 -05:00
|
|
|
boost::interprocess::open_only, key,
|
2014-04-07 07:07:27 -04:00
|
|
|
read_write ? boost::interprocess::read_write : boost::interprocess::read_only);
|
2014-06-11 09:22:51 -04:00
|
|
|
region = boost::interprocess::mapped_region(
|
2014-04-07 07:07:27 -04:00
|
|
|
shm, read_write ? boost::interprocess::read_write : boost::interprocess::read_only);
|
2014-06-11 09:22:51 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // writeable pointer
|
|
|
|
// remove previously allocated mem
|
|
|
|
if (remove_prev)
|
2014-04-07 07:07:27 -04:00
|
|
|
{
|
|
|
|
Remove(key);
|
|
|
|
}
|
2015-01-27 11:44:46 -05:00
|
|
|
shm = boost::interprocess::shared_memory_object(boost::interprocess::open_or_create,
|
|
|
|
key, boost::interprocess::read_write);
|
2014-04-07 07:07:27 -04:00
|
|
|
shm.truncate(size);
|
2014-06-11 09:22:51 -04:00
|
|
|
region = boost::interprocess::mapped_region(shm, boost::interprocess::read_write);
|
2014-04-07 07:07:27 -04:00
|
|
|
|
2014-06-11 09:22:51 -04:00
|
|
|
remover.SetID(key);
|
2016-01-07 19:31:57 -05:00
|
|
|
util::SimpleLogger().Write(logDEBUG) << "writeable memory allocated " << size
|
|
|
|
<< " bytes";
|
2014-04-07 07:07:27 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool RegionExists(const int id)
|
|
|
|
{
|
|
|
|
bool result = true;
|
2014-06-11 09:22:51 -04:00
|
|
|
try
|
2014-04-07 07:07:27 -04:00
|
|
|
{
|
|
|
|
char k[500];
|
|
|
|
build_key(id, k);
|
|
|
|
result = RegionExists(k);
|
|
|
|
}
|
2015-01-27 11:44:46 -05:00
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
result = false;
|
|
|
|
}
|
2014-04-07 07:07:27 -04:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool Remove(const int id)
|
|
|
|
{
|
|
|
|
char k[500];
|
|
|
|
build_key(id, k);
|
|
|
|
return Remove(k);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2015-01-27 11:44:46 -05:00
|
|
|
static void build_key(int id, char *key) { sprintf(key, "%s.%d", "osrm.lock", id); }
|
2014-06-17 09:48:47 -04:00
|
|
|
|
2014-06-11 09:22:51 -04:00
|
|
|
static bool RegionExists(const char *key)
|
2014-04-07 07:07:27 -04:00
|
|
|
{
|
|
|
|
bool result = true;
|
2014-06-11 09:22:51 -04:00
|
|
|
try
|
2014-04-07 07:07:27 -04:00
|
|
|
{
|
2015-01-27 11:44:46 -05:00
|
|
|
boost::interprocess::shared_memory_object shm(boost::interprocess::open_only, key,
|
|
|
|
boost::interprocess::read_write);
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
result = false;
|
2014-04-07 07:07:27 -04:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2014-06-11 09:22:51 -04:00
|
|
|
static bool Remove(char *key)
|
2014-04-07 07:07:27 -04:00
|
|
|
{
|
|
|
|
bool ret = false;
|
|
|
|
try
|
|
|
|
{
|
2016-01-05 10:51:13 -05:00
|
|
|
util::SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
|
2014-04-07 07:07:27 -04:00
|
|
|
ret = boost::interprocess::shared_memory_object::remove(key);
|
2014-06-11 09:22:51 -04:00
|
|
|
}
|
|
|
|
catch (const boost::interprocess::interprocess_exception &e)
|
2014-04-07 07:07:27 -04:00
|
|
|
{
|
2014-06-11 09:22:51 -04:00
|
|
|
if (e.get_error_code() != boost::interprocess::not_found_error)
|
2014-04-07 07:07:27 -04:00
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
char key[500];
|
|
|
|
boost::interprocess::shared_memory_object shm;
|
|
|
|
boost::interprocess::mapped_region region;
|
|
|
|
shm_remove remover;
|
|
|
|
};
|
|
|
|
#endif
|
2013-09-17 08:23:06 -04:00
|
|
|
|
2016-01-07 13:19:55 -05:00
|
|
|
template <typename IdentifierT, typename LockFileT = OSRMLockFile>
|
|
|
|
SharedMemory *makeSharedMemory(const IdentifierT &id,
|
Takes care of proper special member generation globally, fixes #1689
Phew, a lot of classes were affected by this. The rationale for the
changes are as follows:
- When a type X declares any constructor, the default constructor is
not declared, so there is no need for X() = delete there. In fact,
there is brutal difference between those two: deleted members
participate in overload resolution, but not-declared members do not!
- When a type X wants to be non-copyable (e.g. to be only movable, like
threads, unique_ptrs, and so on), you can either do it by inheriting
from boost::noncopyable (the old way), or better declare both (!) the
copy constructor _and_ the copy assignment operator as deleted:
X(X const&) = delete;
X& operator=(X const&) = delete;
We had tons of types with deleted copy constructors that were lacking
a corresponding deleted copy assignment operator, making them still
copyable and you wouldn't even notice (read: scary)!
References:
- http://accu.org/content/conf2014/Howard_Hinnant_Accu_2014.pdf
- http://www.boost.org/doc/libs/master/libs/core/doc/html/core/noncopyable.html
Note: I know, I'm quoting Hinnant's extraordinary slides a lot, but
getting the sematic right here is so incredibly important.
2016-01-27 05:20:55 -05:00
|
|
|
const uint64_t size = 0,
|
|
|
|
bool read_write = false,
|
|
|
|
bool remove_prev = true)
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
Takes care of proper special member generation globally, fixes #1689
Phew, a lot of classes were affected by this. The rationale for the
changes are as follows:
- When a type X declares any constructor, the default constructor is
not declared, so there is no need for X() = delete there. In fact,
there is brutal difference between those two: deleted members
participate in overload resolution, but not-declared members do not!
- When a type X wants to be non-copyable (e.g. to be only movable, like
threads, unique_ptrs, and so on), you can either do it by inheriting
from boost::noncopyable (the old way), or better declare both (!) the
copy constructor _and_ the copy assignment operator as deleted:
X(X const&) = delete;
X& operator=(X const&) = delete;
We had tons of types with deleted copy constructors that were lacking
a corresponding deleted copy assignment operator, making them still
copyable and you wouldn't even notice (read: scary)!
References:
- http://accu.org/content/conf2014/Howard_Hinnant_Accu_2014.pdf
- http://www.boost.org/doc/libs/master/libs/core/doc/html/core/noncopyable.html
Note: I know, I'm quoting Hinnant's extraordinary slides a lot, but
getting the sematic right here is so incredibly important.
2016-01-27 05:20:55 -05:00
|
|
|
try
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
Takes care of proper special member generation globally, fixes #1689
Phew, a lot of classes were affected by this. The rationale for the
changes are as follows:
- When a type X declares any constructor, the default constructor is
not declared, so there is no need for X() = delete there. In fact,
there is brutal difference between those two: deleted members
participate in overload resolution, but not-declared members do not!
- When a type X wants to be non-copyable (e.g. to be only movable, like
threads, unique_ptrs, and so on), you can either do it by inheriting
from boost::noncopyable (the old way), or better declare both (!) the
copy constructor _and_ the copy assignment operator as deleted:
X(X const&) = delete;
X& operator=(X const&) = delete;
We had tons of types with deleted copy constructors that were lacking
a corresponding deleted copy assignment operator, making them still
copyable and you wouldn't even notice (read: scary)!
References:
- http://accu.org/content/conf2014/Howard_Hinnant_Accu_2014.pdf
- http://www.boost.org/doc/libs/master/libs/core/doc/html/core/noncopyable.html
Note: I know, I'm quoting Hinnant's extraordinary slides a lot, but
getting the sematic right here is so incredibly important.
2016-01-27 05:20:55 -05:00
|
|
|
LockFileT lock_file;
|
|
|
|
if (!boost::filesystem::exists(lock_file()))
|
|
|
|
{
|
|
|
|
if (0 == size)
|
|
|
|
{
|
|
|
|
throw util::exception("lock file does not exist, exiting");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
boost::filesystem::ofstream ofs(lock_file());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new SharedMemory(lock_file(), id, size, read_write, remove_prev);
|
|
|
|
}
|
|
|
|
catch (const boost::interprocess::interprocess_exception &e)
|
|
|
|
{
|
|
|
|
util::SimpleLogger().Write(logWARNING) << "caught exception: " << e.what() << ", code "
|
|
|
|
<< e.get_error_code();
|
|
|
|
throw util::exception(e.what());
|
2014-05-07 12:39:16 -04:00
|
|
|
}
|
2016-01-07 13:19:55 -05:00
|
|
|
}
|
2016-01-05 10:51:13 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-07 13:19:55 -05:00
|
|
|
#endif // SHARED_MEMORY_HPP
|