2

Note

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 to tbb::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 function tbb::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 totbb::internal::NFS_Free(void*)' /tmp/cc3YbTER.o: In function tbb::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 totbb::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.

Pogo
  • 475
  • 3
  • 19
  • It looks just like link error `undefined reference to xxx`, you should check the link/compile command to see if you have link against boost lib. – Mine Apr 28 '14 at 06:54
  • oh god. i forgot to compile it with -ltbb flag. thanks a lot – Pogo Apr 28 '14 at 06:56
  • Not sure why this is marked duplicate since the question asks about changing a container in a boost adjacency list but the supposed duplicate references 'undefined reference'. "question has already been answered here..." seems very misleading. – pbible Apr 29 '14 at 12:14
  • I have added my answer below. I was able to add concurrent vector from Intel TBB library and able to use it for both out_edge_list and vertex_list. and it works fine – Pogo Apr 29 '14 at 15:10
  • I think you should accept your answer. I think we should remove duplicate, but I don't know how. The referenced duplicate does not answer the stated question. – pbible Apr 29 '14 at 16:08
  • I can only accept my answer after 24 hrs of posting it !! still 11 hrs left :) – Pogo Apr 29 '14 at 18:57
  • Here is a link on non-duplicate - duplicates. http://meta.stackexchange.com/questions/194476/someone-flagged-my-question-as-already-answered-but-its-not/194495. Having this as duplicate might prevent useful answers and the other question does not address the issue of using custom containers with BGL. – pbible Apr 30 '14 at 12:26
  • 1
    Please edit the question in order to remove the `undefined reference` part before removing the duplication mark – Anton May 31 '14 at 04:45

1 Answers1

1

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.

Pogo
  • 475
  • 3
  • 19
  • This solution is functional on Boost 1.65 for me, but it requires a change to boost/pending/container_traits.hpp, a file belonging to the library. In other words, it is not possible to add custom storage entirely in user code. Also, the most recent version of BGL documentation (v1.75) still does not mention the need for the container_category update, some 16 years (!) after the initial recognition of this deficiency. – Connor Lawson Jul 30 '21 at 17:38