#include <string>
#include <new>
-using boost::interprocess::managed_mapped_file;
-using boost::interprocess::open_or_create;
-using boost::interprocess::open_only;
-using boost::interprocess::open_read_only;
-using boost::interprocess::offset_ptr;
+using namespace boost::interprocess;
namespace isc {
namespace util {
+// We customize managed_mapped_file to make it completely lock free. In our
+// usage the application (or the system of applications) is expected to ensure
+// there's at most one writer process or concurrent writing the shared memory
+// segment is protected at a higher level. Using the null mutex is mainly for
+// eliminating unnecessary dependency; the default version would require
+// (probably depending on the system) Pthread library that is actually not
+// needed and could cause various build time troubles.
+typedef basic_managed_mapped_file<char,
+ rbtree_best_fit<null_mutex_family>,
+ iset_index> BaseSegment;
+
struct MemorySegmentMapped::Impl {
Impl(const std::string& filename, size_t initial_size) :
read_only_(false), filename_(filename),
- base_sgmt_(new managed_mapped_file(open_or_create, filename.c_str(),
- initial_size))
+ base_sgmt_(new BaseSegment(open_or_create, filename.c_str(),
+ initial_size))
{}
Impl(const std::string& filename, bool read_only) :
read_only_(read_only), filename_(filename),
base_sgmt_(read_only ?
- new managed_mapped_file(open_read_only, filename.c_str()) :
- new managed_mapped_file(open_only, filename.c_str()))
+ new BaseSegment(open_read_only, filename.c_str()) :
+ new BaseSegment(open_only, filename.c_str()))
{}
// Internal helper to grow the underlying mapped segment.
const size_t new_size = prev_size * 2;
assert(new_size != 0); // assume grow fails before size overflow
- if (!managed_mapped_file::grow(filename_.c_str(),
- new_size - prev_size))
+ if (!BaseSegment::grow(filename_.c_str(), new_size - prev_size))
{
throw std::bad_alloc();
}
// Remap the grown file; this should succeed, but it's not 100%
// guaranteed. If it fails we treat it as if we fail to create
// the new segment.
- base_sgmt_.reset(new managed_mapped_file(open_only,
- filename_.c_str()));
+ base_sgmt_.reset(new BaseSegment(open_only, filename_.c_str()));
} catch (const boost::interprocess::interprocess_exception& ex) {
throw std::bad_alloc();
}
const std::string filename_;
// actual Boost implementation of mapped segment.
- boost::scoped_ptr<managed_mapped_file> base_sgmt_;
+ boost::scoped_ptr<BaseSegment> base_sgmt_;
};
MemorySegmentMapped::MemorySegmentMapped(const std::string& filename) :
}
impl_->base_sgmt_.reset();
- managed_mapped_file::shrink_to_fit(impl_->filename_.c_str());
+ BaseSegment::shrink_to_fit(impl_->filename_.c_str());
try {
// Remap the grown file; this should succeed, but it's not 100%
// guaranteed. If it fails we treat it as if we fail to create
// the new segment.
impl_->base_sgmt_.reset(
- new managed_mapped_file(open_only, impl_->filename_.c_str()));
+ new BaseSegment(open_only, impl_->filename_.c_str()));
} catch (const boost::interprocess::interprocess_exception& ex) {
isc_throw(MemorySegmentError,
"remap after shrink failed; segment is now unusable");