Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flock based implementation for managed_nonpersistent_shared_memory #132

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions example/Jamfile.v2
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
# the run rule for each source, the result is a list of all
# the run rules, which we can pass on to the test_suite rule:

import ../config/checks/config : requires ;

rule test_all
{
local all_rules = ;
Expand Down Expand Up @@ -49,6 +51,22 @@ rule test_all
] ;
}

for local fileb in [ glob cpp11_*.cpp ]
{
all_rules += [ run $(fileb)
: # additional args
: # test-files
: # requirements
[ requires cxx11_lambdas cxx11_rvalue_references cxx11_final cxx11_auto_declarations ]
<toolset>acc:<linkflags>-lrt
<toolset>acc-pa_risc:<linkflags>-lrt
<toolset>gcc-mingw:<linkflags>"-lole32 -loleaut32 -lpsapi -ladvapi32"
<target-os>hpux,<toolset>gcc:<linkflags>"-Wl,+as,mpas"
<target-os>windows,<toolset>clang:<linkflags>"-lole32 -loleaut32 -lpsapi -ladvapi32"
<target-os>linux:<linkflags>"-lrt"
] ;
}

return $(all_rules) ;
}

Expand Down
116 changes: 116 additions & 0 deletions example/cpp11_nonpersistent_shared_memory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2006-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>

#if defined(BOOST_INTERPROCESS_BSD_DERIVATIVE) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)

//[doc_managed_nonpersistent_shared_memory
#include <boost/interprocess/managed_nonpersistent_shared_memory.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <semaphore.h>

namespace {
struct semaphore final {
semaphore(char const* pszName) noexcept
: m_psem(sem_open(pszName, O_CREAT, /* accessible by current user only */ S_IRUSR|S_IWUSR, 1))
{}

~semaphore() {
sem_close(m_psem);
}

void wait() const& noexcept {
sem_wait(m_psem);
}

void post() const& noexcept {
sem_post(m_psem);
}
private:
sem_t* m_psem;
};

struct SShared final {
char m_sz[12];
};
}

int main(int argc, char *argv[])
{
using namespace boost::interprocess;

bool bFirstProcess = false;
basic_managed_nonpersistent_shared_memory<char, rbtree_best_fit<mutex_family>, iset_index> shm(
open_or_create,
"MySharedMemory",
1000,
[&]() noexcept {
std::cout << "Shared memory segment created. Resetting semaphore.\n";
bFirstProcess = true;
if(-1==sem_unlink("MySharedSemaphore")) {
if(EINVAL!=errno && ENOENT!=errno) {
std::cerr << "Deleting semaphore returned unexpected error.\n";
std::exit(1);
}
}
}
);

semaphore sem("MySharedSemaphore");

sem.wait();

SShared* pshared = shm.find_or_construct<SShared>("A")();
char const str[] = { "Hello World" };

//Map the whole shared memory in this process
if(bFirstProcess) {
std::cout << "Acquired semaphore. Writing to shared memory.\n";
std::copy(std::begin(str), std::end(str), pshared->m_sz);

sem.post(); // release semaphore before starting process

std::cout << "Start child process.\n";
if(0 != std::system(argv[0])) {
std::cerr << "Child process failed.\n";
return 1;
}
} else {
std::cout << "Acquired semaphore. Reading shared memory.\n";
std::cout << pshared->m_sz << "\n";

bool const bEqual = std::equal(std::begin(str), std::end(str), pshared->m_sz);
sem.post();

if(!bEqual) {
std::cerr << "Error reading shared memory\n";
return 1;
}
}

return 0;
}
//]

#else //BOOST_INTERPROCESS_BSD_DERIVATIVE

int main()
{
return 0;
}

#endif //BOOST_INTERPROCESS_BSD_DERIVATIVE

#include <boost/interprocess/detail/config_end.hpp>
227 changes: 227 additions & 0 deletions include/boost/interprocess/managed_nonpersistent_shared_memory.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////

#ifndef BOOST_INTERPROCESS_MANAGED_ROBUST_SHARED_MEMORY_HPP
#define BOOST_INTERPROCESS_MANAGED_ROBUST_SHARED_MEMORY_HPP

#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif

#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>

#include <boost/interprocess/detail/managed_memory_impl.hpp>
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp>
#include <boost/interprocess/nonpersistent_shared_memory_object.hpp>
#include <boost/interprocess/creation_tags.hpp>
#include <boost/interprocess/permissions.hpp>
//These includes needed to fulfill default template parameters of
//predeclarations in interprocess_fwd.hpp
#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
#include <boost/interprocess/sync/mutex_family.hpp>

namespace boost {
namespace interprocess {

namespace ipcdetail {

template<class AllocationAlgorithm>
struct nonpersistentmem_open_or_create
{
typedef ipcdetail::managed_open_or_create_impl
< nonpersistent_shared_memory_object, AllocationAlgorithm::Alignment, true, true> type;
};

} //namespace ipcdetail {

//!A basic non-persistent shared memory named object creation class.
//!It emulates non-persistent shared memory with temporary files on
//!filesystems that support flock-style shared and exclusive locks.
//!When the shared memory is created, and the temporary file still exists
//!but is not accessed by any other process, its contents are cleared.
//!
//!Inherits all basic functionality from
//!basic_managed_memory_impl<CharType, AllocationAlgorithm, IndexType>*/
template
<
class CharType,
class AllocationAlgorithm,
template<class IndexConfig> class IndexType
>
class basic_managed_nonpersistent_shared_memory
: public ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType
,ipcdetail::nonpersistentmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset>
, private ipcdetail::nonpersistentmem_open_or_create<AllocationAlgorithm>::type
{
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef ipcdetail::basic_managed_memory_impl
<CharType, AllocationAlgorithm, IndexType,
ipcdetail::nonpersistentmem_open_or_create<AllocationAlgorithm>::type::ManagedOpenOrCreateUserOffset> base_t;
typedef typename ipcdetail::nonpersistentmem_open_or_create<AllocationAlgorithm>::type base2_t;

template<class BasicManagedMemoryImpl, class Func>
class create_open_func_callback : public ipcdetail::create_open_func<BasicManagedMemoryImpl> {
using base_t = ipcdetail::create_open_func<BasicManagedMemoryImpl>;
public:

create_open_func_callback(BasicManagedMemoryImpl * const frontend, ipcdetail::create_enum_t type, Func&& fn)
: base_t(frontend, type), m_func(std::forward<Func>(fn)) {}

bool operator()(void *addr, std::size_t size, bool created) const {
if(!base_t::operator()(addr, size, created)) return false; // return on failure

if(created) {
m_func();
}
return true;
}
private:
typename std::decay<Func>::type m_func;
};

basic_managed_nonpersistent_shared_memory *get_this_pointer()
{ return this; }

public:
typedef nonpersistent_shared_memory_object device_type;
typedef typename base_t::size_type size_type;

private:
typedef typename base_t::char_ptr_holder_t char_ptr_holder_t;
BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_nonpersistent_shared_memory)
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED

public: //functions

//!Destroys *this and indicates that the calling process is finished using
//!the resource. The destructor function will deallocate
//!any system resources allocated by the system for use by this process for
//!this resource. The resource can still be opened again calling
//!the open constructor overload. To erase the resource from the system
//!use remove().
~basic_managed_nonpersistent_shared_memory()
{}

//!Default constructor. Does nothing.
//!Useful in combination with move semantics
basic_managed_nonpersistent_shared_memory()
{}

//!Creates shared memory and creates and places the segment manager if
//!segment was not created, or if no process is accessing the shared memory.
// When the segment was already created, it connects to the segment.
//!This can throw.
template<typename Func>
basic_managed_nonpersistent_shared_memory (open_or_create_t,
const char *name,
size_type size,
Func&& OnCreation,
const void *addr = 0, const permissions& perm = permissions())
: base_t()
, base2_t(open_or_create, name, size, read_write, addr,
create_open_func_callback<base_t, Func>(get_this_pointer(), ipcdetail::DoOpenOrCreate, std::forward<Func>(OnCreation)),
perm)
{}

//!Moves the ownership of "moved"'s managed memory to *this.
//!Does not throw
basic_managed_nonpersistent_shared_memory(BOOST_RV_REF(basic_managed_nonpersistent_shared_memory) moved)
{
basic_managed_nonpersistent_shared_memory tmp;
this->swap(moved);
tmp.swap(moved);
}

//!Moves the ownership of "moved"'s managed memory to *this.
//!Does not throw
basic_managed_nonpersistent_shared_memory &operator=(BOOST_RV_REF(basic_managed_nonpersistent_shared_memory) moved)
{
basic_managed_nonpersistent_shared_memory tmp(boost::move(moved));
this->swap(tmp);
return *this;
}

//!Swaps the ownership of the managed shared memories managed by *this and other.
//!Never throws.
void swap(basic_managed_nonpersistent_shared_memory &other)
{
base_t::swap(other);
base2_t::swap(other);
}

#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)

//!Tries to find a previous named allocation address. Returns a memory
//!buffer and the object count. If not found returned pointer is 0.
//!Never throws.
template <class T>
std::pair<T*, size_type> find (char_ptr_holder_t name)
{
if(base2_t::get_mapped_region().get_mode() == read_only){
return base_t::template find_no_lock<T>(name);
}
else{
return base_t::template find<T>(name);
}
}

#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};

#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED

//!Typedef for a default basic_managed_shared_memory
//!of narrow characters
typedef basic_managed_nonpersistent_shared_memory
<char
,rbtree_best_fit<mutex_family>
,iset_index>
managed_nonpersistent_shared_memory;

//!Typedef for a default basic_managed_shared_memory
//!of wide characters
typedef basic_managed_nonpersistent_shared_memory
<wchar_t
,rbtree_best_fit<mutex_family>
,iset_index>
wmanaged_shared_memory;

//!Typedef for a default basic_managed_shared_memory
//!of narrow characters to be placed in a fixed address
typedef basic_managed_nonpersistent_shared_memory
<char
,rbtree_best_fit<mutex_family, void*>
,iset_index>
fixed_managed_shared_memory;

//!Typedef for a default basic_managed_shared_memory
//!of narrow characters to be placed in a fixed address
typedef basic_managed_nonpersistent_shared_memory
<wchar_t
,rbtree_best_fit<mutex_family, void*>
,iset_index>
wfixed_managed_shared_memory;


#endif //#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED

} //namespace interprocess {
} //namespace boost {

#include <boost/interprocess/detail/config_end.hpp>

#endif //BOOST_INTERPROCESS_MANAGED_ROBUST_SHARED_MEMORY_HPP

Loading