boost::interprocess Containers of containers NOT in shared memory - boost

I have the example demo program with a boost::interprocess Containers of containers type.
But I like to use the class also a normal class within my process memory.
Can someone help me to write a constructor which takes no arguments to have the class initialized in my current process memory.
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <shmfw/serialization/interprocess_vector.hpp>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
using namespace boost::interprocess;
//Alias an STL-like allocator of ints that allocates ints from the segment
typedef allocator<int, managed_shared_memory::segment_manager> ShmemAllocator;
//Alias a vector that uses the previous STL-like allocator
typedef vector<int, ShmemAllocator> MyVector;
typedef allocator<void, managed_shared_memory::segment_manager > void_allocator;
class MyStruct {
public:
MyVector myVector;
//Since void_allocator is convertible to any other allocator<T>, we can simplify
//the initialization taking just one allocator for all inner containers.
MyStruct ( const void_allocator &void_alloc )
: myVector ( void_alloc )
{}
// Thats what I like to have
//MyStruct ()
// : myVector ( ?? )
//{}
};
int main () {
// I would like to have something like that working and also the shm stuff below
// MyStruct x;
managed_shared_memory segment;
//A managed shared memory where we can construct objects
//associated with a c-string
try {
segment = managed_shared_memory( create_only, "MySharedMemory", 65536 );
} catch (...){
segment = managed_shared_memory( open_only, "MySharedMemory" );
}
//Initialize the STL-like allocator
const ShmemAllocator alloc_inst ( segment.get_segment_manager() );
MyStruct *myStruct_src = segment.find_or_construct<MyStruct> ( "MyStruct" ) ( alloc_inst );
srand (time(NULL));
myStruct_src->myVector.push_back ( rand() );
MyStruct *myStruct_des = segment.find_or_construct<MyStruct> ( "MyStruct" ) ( alloc_inst );
for ( size_t i = 0; i < myStruct_src->myVector.size(); i++ ) {
std::cout << i << ": " << myStruct_src->myVector[i] << " = " << myStruct_des->myVector[i] << std::endl;
if(myStruct_src->myVector[i] != myStruct_des->myVector[i]) {
std::cout << "Something went wrong!" << std::endl;
}
}
//segment.destroy<MyVector> ( "MyVector" );
return 0;
}

If you change the allocator type, you change the container (such is the nature of compile-time template instantiation).
Technically, you could devise a type-erased allocator (à la std::function or boost::any_iterator) but this would probably result in abysmal performance. Also, it would still require all the allocators to correspond in all the statically known properties, reducing flexibility.
In reality, I suggest just templatizing MyStruct on the Allocator type to be used for any embedded containers. Then specifically take such an allocator in the constructor:
// Variant to use on the heap:
using HeapStruct = MyStruct<std::allocator>;
// Variant to use in shared memory:
using ShmemStruct = MyStruct<BoundShmemAllocator>;
Demo Program:
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/range/algorithm.hpp>
#include <iostream>
#include <cassert>
namespace bip = boost::interprocess;
template <typename T>
using BoundShmemAllocator = bip::allocator<T, bip::managed_shared_memory::segment_manager>;
///////////////////////////////////////////////////////////////
// Your MyStruct, templatized for an Allocator class template
template <template<typename...> class Allocator>
class MyStruct {
public:
bip::vector<int, Allocator<int> > ints;
bip::vector<double, Allocator<double> > doubles;
MyStruct(const Allocator<void>& void_alloc = {})
: ints(void_alloc),
doubles(void_alloc)
{}
};
// Variant to use on the heap:
using HeapStruct = MyStruct<std::allocator>;
// Variant to use in shared memory:
using ShmemStruct = MyStruct<BoundShmemAllocator>;
//
///////////////////////////////////////////////////////////////
int main() {
srand(time(NULL));
// You can have something like this working:
HeapStruct x; // and also the shm stuff below
std::generate_n(std::back_inserter(x.ints), 20, &std::rand);
std::generate_n(std::back_inserter(x.doubles), 20, &std::rand);
// A managed shared memory where we can construct objects
bip::managed_shared_memory segment = bip::managed_shared_memory(bip::open_or_create, "MySharedMemory", 65536);
BoundShmemAllocator<int> const shmem_alloc(segment.get_segment_manager());
auto src = segment.find_or_construct<ShmemStruct>("MyStruct")(shmem_alloc);
src->ints.insert(src->ints.end(), x.ints.begin(), x.ints.end());
src->doubles.insert(src->doubles.end(), x.doubles.begin(), x.doubles.end());
auto des = segment.find_or_construct<ShmemStruct>("MyStruct")(shmem_alloc);
std::cout << "-------------------------";
boost::copy(src->ints, std::ostream_iterator<int>(std::cout << "\nsrc ints: ", "; "));
boost::copy(des->ints, std::ostream_iterator<int>(std::cout << "\ndes ints: ", "; "));
std::cout << "\n-------------------------";
boost::copy(src->doubles, std::ostream_iterator<double>(std::cout << "\nsrc doubles: ", "; "));
boost::copy(des->doubles, std::ostream_iterator<double>(std::cout << "\ndes doubles: ", "; "));
assert(src->ints.size() == des->ints.size());
assert(src->doubles.size() == des->doubles.size());
assert(boost::mismatch(src->ints, des->ints) == std::make_pair(src->ints.end(), des->ints.end()));
assert(boost::mismatch(src->doubles, des->doubles) == std::make_pair(src->doubles.end(), des->doubles.end()));
segment.destroy<ShmemStruct>("MyStruct");
}

Related

How to define the AST for this boost spirit rule?

I have a more complex rule, but this one will suffice for this question (I hope). Consider the rule:
result = double_ >> *(char_ > int_);
where result is declared in terms of a struct result in namespace ast:
qi::rule<Iterator, ast::result(), qi::space_type> result;
Then how does ast::result have to look like?
According to the boost::spirit docs (http://www.boost.org/doc/libs/develop/libs/spirit/doc/html/spirit/abstracts/attributes/compound_attributes.html), the attribute of
char_ > int_ is tuple<char, int> or std::pair<char, int>.
So, I tried:
namespace ast
{
using second_type = std::vector<std::pair<char, int>>;
struct result
{
double first;
second_type second;
};
} // namespace ast
in addition to
BOOST_FUSION_ADAPT_STRUCT(
ast::result,
(double, first),
(ast::second_type, second)
)
But this gives me the compile error:
error: no matching function for call to 'std::pair<char, int>::pair(const char&)'
This rule is simple, creating the AST struct that the result will be stored in should be simple too... but how?
Here is a complete test program with my attempt:
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <iostream>
#include <string>
#include <vector>
namespace ast
{
using second_type = std::vector<std::pair<char, int>>;
struct result
{
double first;
second_type second;
friend std::ostream& operator<<(std::ostream& os, result const& result);
};
std::ostream& operator<<(std::ostream& os, second_type::value_type val)
{
return os << val.first << ' ' << val.second;
}
std::ostream& operator<<(std::ostream& os, result const& result)
{
os << result.first;
for (auto& i : result.second)
os << ' ' << i;
return os;
}
} // namespace ast
BOOST_FUSION_ADAPT_STRUCT(
ast::result,
(double, first),
(ast::second_type, second)
)
namespace client
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
template <typename Iterator>
class test_grammar : public qi::grammar<Iterator, ast::result(), qi::space_type>
{
private:
qi::rule<Iterator, ast::result(), qi::space_type> result;
public:
test_grammar() : test_grammar::base_type(result, "result_grammar")
{
using qi::double_;
using qi::char_;
using qi::int_;
result = double_ >> *(char_ > int_);
}
};
} // namespace client
int main()
{
std::string const input{"3.4 a 5 b 6 c 7"};
using iterator_type = std::string::const_iterator;
using test_grammar = client::test_grammar<iterator_type>;
namespace qi = boost::spirit::qi;
test_grammar program;
iterator_type iter{input.begin()};
iterator_type const end{input.end()};
ast::result out;
bool r = qi::phrase_parse(iter, end, program, qi::space, out);
if (!r || iter != end)
{
std::cerr << "Parsing failed." << std::endl;
return 1;
}
std::cout << "Parsed: " << out << std::endl;
}
SirGuy changed the AST to suit the default synthesized attributes. At the cost of, indeed complicating the AST.
However, you could leverage attribute compatibity rules by adapting std::pair. In fact, that is as simple as including 1 header:
#include <boost/fusion/include/std_pair.hpp>
Then, everything compiles without change, printing:
Parsed: 3.4 a 5 b 6 c 7
I made the following changes:
#include <boost/fusion/tuple.hpp>
using second_type = std::vector<boost::fusion::tuple<char, int>>;
std::ostream& operator<<(std::ostream& os, second_type::value_type val)
{
return os << boost::fusion::get<0>(val) << ' ' << boost::fusion::get<1>(val);
}
and the result compiled for me. There are most certainly other solutions available too.

C++ range-for and boost::irange

I'm using boost::irange and created a helper function to simplify the code by removing the need for explicit template parameters. I don't understand why it doesn't work. Here's the code:
#include <iostream>
#include <boost/range/irange.hpp>
template<typename T>
boost::irange<T> range_from_zero(T limit)
{
return boost::irange<T>(T(), limit);
}
int main() {
size_t end = 100;
for (auto i : range_from_zero(0,end))
std::cout << i << ' ';
return 0;
}
There's a live version here https://ideone.com/VVvW6e, which produces compilation errors
prog.cpp:5:8: error: 'irange<T>' in namespace 'boost' does not name a type
boost::irange<T> range_from_zero(T limit)
^
prog.cpp: In function 'int main()':
prog.cpp:12:41: error: 'range_from_zero' was not declared in this scope
for (auto i : range_from_zero(0,end))
If I use boost::irange directly in the range-for, then it works:
#include <iostream>
#include <boost/range/irange.hpp>
int main() {
size_t end = 100;
for (auto i : boost::irange<size_t>(0,end))
std::cout << i << ' ';
return 0;
}
this works fine: https://ideone.com/TOWY6H
I thought maybe is was a problem using range-for on the return of a function, but it isn't; this works using a std::vector:
#include <iostream>
#include <boost/range/irange.hpp>
template<typename T>
std::vector<T> range_from_zero(T limit)
{
auto range = boost::irange<T>(T(), limit);
return { std::begin(range), std::end(range) };
}
int main() {
size_t end = 100;
for (auto i : range_from_zero(end))
std::cout << i << ' ';
return 0;
}
See https://ideone.com/TYRXnC
Any ideas, please?
But, first off, what's wrong with Live On Coliru
for (size_t i : irange(0, 100))
or even Live On Coliru
size_t end = 100;
for (auto i : irange(0ul, end))
irange is a function template, and it cannot be used as a return type.
The return type is integer_range or strided_integer_range. As such, irange is already the function you were looking for.
Only, you didn't pass arguments that could be unambiguously deduced. If you can to allow this, "copy" irange() implementation using separate template argument types for the boundary values and use e.g. std::common_type<T1,T2>::type as the range element.
Here's my stab at writing range_from_zero without naming implementation details in the interface:
Live On Coliru
#include <iostream>
#include <boost/range/irange.hpp>
template <typename T>
auto izrange(T upper) -> decltype(boost::irange(static_cast<T>(0), upper)) {
return boost::irange(static_cast<T>(0), upper);
}
int main() {
size_t end = 100;
for (size_t i : izrange(end))
std::cout << i << ' ';
}

Move or swap a stringstream

I want to move a stringstream, in the real world application I have some stringstream class data member, which I want to reuse for different string's during operation.
stringstream does not have a copy-assignment or copy constructor, which makes sense. However, according to cppreference.com and cplusplus.com std::stringstream should have a move assignment and swap operation defined. I tried both, and both fail.
Move assignment
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::stringstream
int main () {
std::stringstream stream("1234");
//stream = std::move(std::stringstream("5678"));
stream.operator=(std::move(std::stringstream("5678")));
//stream.operator=(std::stringstream("5678"));
return 0;
}
source: http://ideone.com/Izyanb
prog.cpp:11:56: error: use of deleted function ‘std::basic_stringstream<char>& std::basic_stringstream<char>::operator=(const std::basic_stringstream<char>&)’
stream.operator=(std::move(std::stringstream("5678")));
The compiler states that there is no copy assignment for all three statements, which is true. However, I fail to see why it is not using the move-assignment, especially since std::move is supposed to return a rvalue reference. Stringstream should have a move assignment, as shown here: http://en.cppreference.com/w/cpp/io/basic_stringstream/operator%3D
PS: I'm working with c++11, hence rvalue-references are part of the 'world'.
Swap
This I found really strange, I copied example code from cplusplus.com and it failed:
// swapping stringstream objects
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::stringstream
int main () {
std::stringstream foo;
std::stringstream bar;
foo << 100;
bar << 200;
foo.swap(bar);
int val;
foo >> val; std::cout << "foo: " << val << '\n';
bar >> val; std::cout << "bar: " << val << '\n';
return 0;
}
source: http://ideone.com/NI0xMS
cplusplus.com source: http://www.cplusplus.com/reference/sstream/stringstream/swap/
prog.cpp: In function ‘int main()’:
prog.cpp:14:7: error: ‘std::stringstream’ has no member named ‘swap’
foo.swap(bar);
What am I missing? Why can't I move or swap a stringstream? How should I swap or move a stringstream?
This is a missing feature on GCC : see bug 54316 , it has been fixed (you can thank Jonathan Wakely) for the next versions (gcc 5)
Clang with libc++ compiles this code :
int main () {
std::stringstream stream("1234");
std::stringstream stream2 = std::move(std::stringstream("5678"));
return 0;
}
Live demo
And it also compiles the example with std::stringstream::swap
I have an alternative to moving or swapping, one can also clear and set a stringstream to a new string:
#include <string> // std::string
#include <iostream> // std::cout
#include <sstream> // std::stringstream
int main () {
std::stringstream ss("1234");
ss.clear();
ss.str("5678");
int val;
ss >> val; std::cout << "val: " << val << '\n';
return 0;
}
It's a clean work around that does not require one to refactor code, except for the localized section where the swap is changed to a clear() and str().

Sorting a structure of arrays using Thrust

I am working on CUDA and facing the following problem.
I have a following structure of arrays:
typedef struct Edge{
int *from, *to, *weight;
}
I want to sort this structure on weight array such that the corresponding "from" and "to" arrays get updated too. I thought of using Thrust library but it works only on vectors is what I understood. I can sort_by_key and get two arrays sorted but I am not able to understand how to sort three arrays? I even looked at zip_iterator but did not understand how to use it to serve my purpose. Please help
First decouple the structure into 1) keys, and 2) paddings. Then sort the keys and reorder paddings accordingly. For example, break this structure:
typedef struct Edge{
int from, to, weight;
}
into:
int weight[N];
typedef struct Edge{
int from, to;
}
The full code is here:
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <cmath>
#include <thrust/sort.h>
typedef struct pad {
int from;
int to;
} padd;
__host__ padd randPad() {
padd p;
p.from = rand();
p.to = rand();
return p;
}
__host__ std::ostream& operator<< (std::ostream& os, const padd& p) {
os << "(" << p.to << " , " << p.from << " )";
return os;
}
int main(void)
{
// allocation
#define N 4
thrust::host_vector<int> h_keys(4);
thrust::host_vector<padd> h_pad(4);
// initilization
thrust::generate(h_keys.begin(), h_keys.end(), rand);
thrust::generate(h_pad.begin(), h_pad.end(), randPad);
// print unsorted data
std::cout<<"Unsorted keys\n";
thrust::copy(h_keys.begin(), h_keys.end(), std::ostream_iterator<int>(std::cout, "\n"));
std::cout<<"\nUnsorted paddings\n";
thrust::copy(h_pad.begin(), h_pad.end(), std::ostream_iterator<padd>(std::cout, "\n"));
// transfer to device
thrust::device_vector<int> d_keys = h_keys;
thrust::device_vector<padd> d_pad = h_pad;
//thrust::sort(d_keys.begin(), d_keys.end());
// sort
thrust::sort_by_key(d_keys.begin(), d_keys.end(), d_pad.begin());
// transfer back to host
thrust::copy(d_keys.begin(), d_keys.end(), h_keys.begin());
thrust::copy(d_pad.begin(), d_pad.end(), h_pad.begin());
// print the results
std::cout<<"\nSorted keys\n";
thrust::copy(h_keys.begin(), h_keys.end(), std::ostream_iterator<int>(std::cout, "\n"));
std::cout<<"\nSorted paddings\n";
thrust::copy(h_pad.begin(), h_pad.end(), std::ostream_iterator<padd>(std::cout, "\n"));
return 0;
}
The output would be something like this:
Unsorted keys
1804289383
846930886
1681692777
1714636915
Unsorted paddings
(424238335 , 1957747793 )
(1649760492 , 719885386 )
(1189641421 , 596516649 )
(1350490027 , 1025202362 )
Sorted keys
846930886
1681692777
1714636915
1804289383
Sorted paddings
(1649760492 , 719885386 )
(1189641421 , 596516649 )
(1350490027 , 1025202362 )
(424238335 , 1957747793 )

Assigning data to a given element in a vector within a rule

I'm trying to set up a parser which, given a value, can assign it to a certain element of a vector, but I'm not entirely sure how to implement it.
Let's say the following piece of code parses the string (0){**+*+}. It should increment bar.a[0] once for every +, and bar.b[0] once for every *. The issue I'm encountering is that I'm not sure how to get a reference to a vector's element using _a:
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <vector>
//The struct containing the vector.
struct testStruct {
std::vector<int> a, b;
};
BOOST_FUSION_ADAPT_STRUCT (
testStruct,
(std::vector<int>, a)
(std::vector<int>, b)
)
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
namespace ascii = boost::spirit::ascii;
template<typename Iterator>
struct foo : qi::grammar<Iterator, testStruct(), qi::locals<unsigned>, ascii::space_type> {
foo() : foo::base_type(start) {
using namespace qi::labels;
using qi::eps;
using qi::lit;
using qi::uint_;
using phoenix::at_c;
start = lit('(')
>> uint_ [_a = _1]
>> ')'
>> '{'
>> starsOrPlus(
at_c<_a>(at_c<0>(_val)), //This is where I'm not sure what to do.
at_c<_a>(at_c<1>(_val))
)
>> '}'
;
starsOrPlus = eps [_r1 = 0]
[_r2 = 0]
>> (
* (
(
+lit('+') [_r1 += 1]
)
^ (
+lit('*') [_r2 += 1]
)
)
)
;
}
qi::rule<Iterator, testStruct(), qi::locals<unsigned>, ascii::space_type> start;
//Parses stars and pluses. Sets the first uint8_t to the number of *, and the
//second to the number of +.
qi::rule<Iterator, void(int&, int&), ascii::space_type> starsOrPlus;
};
//Main program
int main() {
std::string testString = "(2){**++*+}";
typedef foo<std::string::const_iterator> foo;
foo grammar;
testStruct bar;
std::string::const_iterator iter = testString.begin();
std::string::const_iterator end = testString.end();
bool parsed = phrase_parse(iter, end, grammar, ascii::space, bar);
if (parsed) {
//Do something with the data...
}
return 0;
}
This fails to compile with the following errors:
main.cpp||In constructor 'foo<Iterator>::foo()':|
main.cpp|36|error: 'boost::spirit::_a' cannot appear in a constant-expression|
main.cpp|36|error: no matching function for call to 'at_c(boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::at_eval<0>, boost::fusion::vector<boost::spirit::attribute<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > >&)'|
main.cpp|37|error: 'boost::spirit::_a' cannot appear in a constant-expression|
main.cpp|37|error: no matching function for call to 'at_c(boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::at_eval<1>, boost::fusion::vector<boost::spirit::attribute<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > >&)'|
So, clearly, I can't use a placeholder value within at_c. I'm also aware that, even if I could, there would also be the issue of re-sizing the vector if the given position is out of range.
How would I implement something like this? Am I just going about this entirely the wrong way?
This should get you started:
#include <vector>
#include <string>
#include <iostream>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
struct testStruct
{
std::vector<int> a, b;
};
BOOST_FUSION_ADAPT_STRUCT
(
testStruct,
(std::vector<int>, a)
(std::vector<int>, b)
)
namespace bp = boost::phoenix;
namespace bs = boost::spirit;
namespace bsq = bs::qi;
template<typename Iterator>
struct foo : bsq::grammar<Iterator, testStruct(), bsq::locals<unsigned> >
{
foo() : foo::base_type(start)
{
using namespace bs::labels;
using bp::at_c;
using bp::resize;
using bs::lit;
using bs::uint_;
start
= '('
>> uint_
[
_a = _1,
resize(at_c<0>(_val), _1 + 1),
resize(at_c<1>(_val), _1 + 1)
]
>> "){"
>> starsOrPlus(at_c<0>(_val)[_a], at_c<1>(_val)[_a])
>> '}'
;
starsOrPlus
= *(
lit('+')[_r1 += 1]
| lit('*')[_r2 += 1]
)
;
}
bsq::rule<Iterator, testStruct(), bsq::locals<unsigned> > start;
bsq::rule<Iterator, void(int&, int&)> starsOrPlus;
};
void printvec(std::vector<int> const& vec)
{
bool first = true;
for (std::vector<int>::const_iterator it = vec.begin(), it_end = vec.end();
it != it_end;
++it)
{
if (first)
first = false;
else
std::cout << ", ";
std::cout << *it;
}
}
int main()
{
foo<std::string::const_iterator> grammar;
testStruct bar;
std::string const input = "(2){**++*}";
std::string::const_iterator first = input.begin(), last = input.end();
if (bsq::parse(first, last, grammar, bar) && first == last)
{
std::cout << "bar.a: ";
printvec(bar.a);
std::cout << "\nbar.b: ";
printvec(bar.b);
std::cout << '\n';
}
else
std::cout << "parse failed\n";
}
The notable changes here are:
The vectors inside of testStruct must be resized to a size sufficient for the desired index to be valid
operator[] is used instead of boost::phoenix::at_c to access the index of a vector, just as one would in "normal" code
Note that I took out the skip parser to simplify things (and because it didn't appear to be necessary); add it back if you need to -- it had no real relevance here.

Resources