Please remove the duplicate mark for this question. Although the error was due to missing -ltbb flags, the main motive of the question was how to change the container_generator in boost graph to use your own specific container such as concurrent vector as provided by TBB. People may ignore the answered question because it is marked duplicate.
I was trying to define my custom container for my boost adjacency_list<> typedef. As per the documentation here, I tried to use tbb::concurrent_vector<>
as my custom container. Here is my code, and I get the following error:
#include <boost/graph/adjacency_list.hpp>
#include "tbb/concurrent_vector.h"
struct concVecS { };
namespace boost {
template <class ValueType>
struct container_gen<concVecS, ValueType> {
//typedef std::list<ValueType> type;
typedef tbb::concurrent_vector<ValueType> type;
};
template<>
struct parallel_edge_traits<concVecS > {
typedef allow_parallel_edge_tag type;
};
}
typedef boost::adjacency_list <concVecS, boost::vecS, boost::directedS> MyGraph;
int main(int, char*[])
{
MyGraph g(5);
return 0;
}
Error:
/tmp/cc3YbTER.o: In function
tbb::concurrent_vector<boost::detail::sep_<unsigned long, boost::no_property>, tbb::cache_aligned_allocator<boost::detail::sep_<unsigned long, boost::no_property> > >::~concurrent_vector()': /cm/shared/apps/intel-tbb-oss/intel64/42_20131003oss/include/tbb/concurrent_vector.h:888: undefined reference to
tbb::internal::concurrent_vector_base_v3::internal_clear(void ()(void, unsigned long))' /cm/shared/apps/intel-tbb-oss/intel64/42_20131003oss/include/tbb/concurrent_vector.h:890: undefined reference totbb::internal::concurrent_vector_base_v3::~concurrent_vector_base_v3()' /cm/shared/apps/intel-tbb-oss/intel64/42_20131003oss/include/tbb/concurrent_vector.h:890: undefined reference to
tbb::internal::concurrent_vector_base_v3::~concurrent_vector_base_v3()' /tmp/cc3YbTER.o: In functiontbb::cache_aligned_allocator<boost::detail::sep_<unsigned long, boost::no_property> >::deallocate(boost::detail::sep_<unsigned long, boost::no_property>*, unsigned long)': /cm/shared/apps/intel-tbb-oss/intel64/42_20131003oss/include/tbb/cache_aligned_allocator.h:96: undefined reference to
tbb::internal::NFS_Free(void*)' /tmp/cc3YbTER.o: In functiontbb::cache_aligned_allocator<boost::detail::sep_<unsigned long, boost::no_property> >::allocate(unsigned long, void const*)': /cm/shared/apps/intel-tbb-oss/intel64/42_20131003oss/include/tbb/cache_aligned_allocator.h:91: undefined reference to
tbb::internal::NFS_Allocate(unsigned long, unsigned long, void*)' collect2: error: ld returned 1 exit status
I dont know what wrong I am doing. I changed the container to std::list
and it works fine. Dont know what is it I have to add more. as per documentation, this is enough atleast to create a simple graph object.
Thanks to the comments provided by Dr. Jeremy Siek at this link here, I was able to define my own container type viz. concurrent_vector to the container_traits.hpp file in boost/pending/ folder.
I can now change the vecS to concurrentVecS and use my algorithm. Although std::vector<> is thread safe for reads, I wanted to try this with concurrent vector.
Here is the completed code.
//in container_traits.hpp --> added the following code
//boost/pending/container_traits.hpp file
//concurrent vector
struct concurrent_vector_tag :
virtual public random_access_container_tag,
virtual public back_insertion_sequence_tag { };
template <class T, class Alloc>
concurrent_vector_tag container_category(const tbb::concurrent_vector<T, Alloc>&) {
return concurrent_vector_tag();
}
template <class T, class Alloc>
unstable_tag iterator_stability(const tbb::concurrent_vector<T, Alloc>&) {
return unstable_tag();
}
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T, class Alloc>
struct container_traits< tbb::concurrent_vector <T, Alloc> > {
typedef concurrent_vector_tag category;
typedef unstable_tag iterator_stability;
};
#endif
//in my custom_container.hpp file
#include "tbb/concurrent_vector.h"
#include <boost/graph/adjacency_list.hpp>
namespace boost {
struct cvecS { }; //concurrent vector selector
template <class ValueType>
struct container_gen <cvecS, ValueType> {
typedef tbb::concurrent_vector <ValueType> type;
};
template<>
struct parallel_edge_traits<cvecS > {
typedef allow_parallel_edge_tag type;
};
}; //namespace
// in my main file
typedef boost::adjacency_list <boost::cvecS, boost::cvecS, boost::undirectedS> Graph_t
Graph_t g (5);
Graph_t::vertex_descriptor v1, v2;
v1 = boost::add_vertex(g);
v2 = boost::add_vertex(g);
boost::add_edge(v1, v2, g);
PS: I am not sure, but I am guessing, there was no need to add push() and erase() functions in this case as concurrent_vector.h file already provides them.