1737973
1737973

Reputation: 118

This weird clang compile error

I have a program that solves those two dimension mazes, it works quite fine to me, however I profiled it with gprof (and @jrfonseca's fancy gprof2dot), it seemed to me it was taking a hard time with some operations and decided to do some parallelisation tries.

Basically in a function that consumed 50% (cpu?) time I had two choices of parallelising (multiple consumers for a single queue and parallel call of same function with similar not equal arguments) yet wanted to do both at first independently to check an initial assumption on which one would be better, I don't always do C++ code, and by searching the Internet on how to get std::thread returning a value I read a nice answer with advices on std::future, then I copied that to my code, so would you please know what this gets to mean...

bash-4.3$ sh build.sh
In file included from find_path.cpp:6:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/Xco
deDefault.xctoolchain/usr/bin/../include/c++/v1/future:371:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/../include/c++/v1/thread:337:5: error:
      attempt to use a deleted function
    __invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_In...
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/../include/c++/v1/thread:347:5:
      in instantiation of function template specialization
      'std::__1::__thread_execute<void
      (*)(std::__1::priority_queue<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > >,
      std::__1::vector<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > >,
      std::__1::allocator<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > > >, NearerTarget> &,
      std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > &, std::__1::pair<int,
      int> &, int, int, int, int, unsigned char *,
      std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > &, int, int,
      std::__1::promise<bool> &&),
      std::__1::reference_wrapper<std::__1::priority_queue<std::__1::vector<std
::__1::pair<int,
      int>, std::__1::allocator<std::__1::pair<int, int> > >,
      std::__1::vector<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > >,
      std::__1::allocator<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > > >, NearerTarget> >,
      std::__1::reference_wrapper<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > >,
      std::__1::reference_wrapper<std::__1::pair<int, int> >, int, int, int,
      int, const unsigned char *,
      std::__1::reference_wrapper<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > >, int, int,
      std::__1::promise<bool> , 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12>'
      requested here
    __thread_execute(*__p, _Index());
    ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/../include/c++/v1/thread:359:42: note:
      in instantiation of function template specialization
      'std::__1::__thread_proxy<std::__1::tuple<void
      (*)(std::__1::priority_queue<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > >,
      std::__1::vector<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > >,
      std::__1::allocator<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > > >, NearerTarget> &,
      std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > &, std::__1::pair<int,
      int> &, int, int, int, int, unsigned char *,
      std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > &, int, int,
      std::__1::promise<bool> &&),
      std::__1::reference_wrapper<std::__1::priority_queue<std::__1::vector<std
::__1::pair<int,
      int>, std::__1::allocator<std::__1::pair<int, int> > >,
      std::__1::vector<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > >,
      std::__1::allocator<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > > >, NearerTarget> >,
      std::__1::reference_wrapper<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > >,
      std::__1::reference_wrapper<std::__1::pair<int, int> >, int, int, int,
      int, const unsigned char *,
      std::__1::reference_wrapper<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > >, int, int,
      std::__1::promise<bool> > >' requested here
    int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get());
                                         ^
find_path.cpp:258:25: note: in instantiation of function template specializatio
n
      'std::__1::thread::thread<void
      (*)(std::__1::priority_queue<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > >,
      std::__1::vector<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > >,
      std::__1::allocator<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > > >, NearerTarget> &,
      std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > &, std::__1::pair<int,
      int> &, int, int, int, int, unsigned char *,
      std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > &, int, int,
      std::__1::promise<bool> &&),
      std::__1::reference_wrapper<std::__1::priority_queue<std::__1::vector<std
::__1::pair<int,
      int>, std::__1::allocator<std::__1::pair<int, int> > >,
      std::__1::vector<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > >,
      std::__1::allocator<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > > >, NearerTarget> >,
      std::__1::reference_wrapper<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > >,
      std::__1::reference_wrapper<std::__1::pair<int, int> >, int &, int &,
      const int &, const int &, const unsigned char *&,
      std::__1::reference_wrapper<std::__1::vector<std::__1::pair<int, int>,
      std::__1::allocator<std::__1::pair<int, int> > > >, const int &, int,
      std::__1::promise<bool> , void>' requested here
            std::thread n(&move, std::ref(active_paths),
                        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/../include/c++/v1/type_traits:1043:5: note:
      '~__nat' has been explicitly marked deleted here
    ~__nat() = delete;
    ^
1 error generated.
bash-4.3$

... in this context?

Some find_path.cpp:

 1  //   For 'assert(expression)'.
 2  #include <cassert>
 3  //   For 'std::abs' (absolute value function, integers version)'.
 4  #include <cstdlib>
 5  //   For 'std::promise' and 'std::future'.
 6  #include <future>  // <--
 7  //   For 'std::mutex'.
 8  #include <mutex>
 9  //   For 'std::priority_queue'.
10  #include <queue>
11  //   For 'std::move'.
12  #include <utility>
13  //   For 'std::vector'.
14  #include <vector>
15  //   For 'std::thread'.
16  #include <thread>
17  //   For 'std::get', 'std::make_tuple' and 'std::tuple'.
18  #include <tuple>

Some more:

242             //   Do not add new paths unless deemed necessary.
243             bool add_north_move, add_west_move, add_south_move, add_east_move;
244             add_north_move = add_west_move = add_south_move = add_east_move =
245                 0;
246 
247             //   Another helper.
248             std::vector < std::pair < int, int > > active_paths_top =
249                 active_paths.top();
250             std::pair < int, int > active_paths_top_back =
251                 active_paths_top.back();
252 
253             //   Directions clockwise (0: 'N', 1: 'E', 2: 'S', 3: 'W').
254             int direction = 0;
255 
256             std::promise < bool > n_p;
257             auto n_f = n_p.get_future();
258             std::thread n(&move, std::ref(active_paths),  // <--
259                           std::ref(active_paths_top),
260                           std::ref(active_paths_top_back), new_move_back_x, new_move_back_y,
261               nMapWidth, nMapHeight, pMap, std::ref(north_move), nOutBufferSize, direction++, std::move(n_p)
262             );
263             std::promise < bool > e_p;
264             auto e_f = e_p.get_future();
265             std::thread e(&move, std::ref(active_paths),
266                           std::ref(active_paths_top),
267                           std::ref(active_paths_top_back), new_move_back_x, new_move_back_y,
268               nMapWidth, nMapHeight, pMap, std::ref(east_move), nOutBufferSize, direction++, std::move(e_p)
269             );

Contents in void move(12):

108 void move(std::priority_queue <
109         std::vector < std::pair < int, int > >,
110         std::vector < std::vector < std::pair < int, int > > >,
111         NearerTarget
112     > & active_paths,
113     std::vector < std::pair < int, int > > & active_paths_top,
114     std::pair < int, int > & active_paths_top_back, int new_move_back_x, int new_move_back_y,
115     int map_width, int map_height, unsigned char * map, std::vector < std::pair < int, int > > & move,
116     int out_buffer_size, int direction,
117     std::promise < bool > && add_move) {
118     assert(-1 < direction && 4 > direction);
119     std::pair < int, int > new_coord;
120     switch (direction) {
121     case 0:
122             //   Add move 'N'.
123             new_coord = std::make_pair(
124                     active_paths_top_back.first,
125                     active_paths_top_back.second + 1);
126             break;
127     case 1:
128             //   Add move 'E'.
129             new_coord = std::make_pair(
130                     active_paths_top_back.first + 1,
131                     active_paths_top_back.second);
132             break;
133     case 2:
134             //   Add move 'S'.
135             new_coord = std::make_pair(
136                     active_paths_top_back.first,
137                     active_paths_top_back.second - 1);
138             break;
139     case 3:
140             //   Add move 'W'.
141             new_coord = std::make_pair(
142                     active_paths_top_back.first - 1,
143                     active_paths_top_back.second);
144             break;
145     }
146 
147             //   Push it to the queue of paths only if the movement
148             // makes sense.
149             new_move_back_x = new_coord.first;
150             new_move_back_y = new_coord.second;
151             if (new_move_back_x > -1 && new_move_back_x < map_width &&
152                     new_move_back_y > -1 && new_move_back_y < map_height)
153             {
154                 //   Move is inside bounds.
155 
156                 //   Check collision detection.
157                 if (map[new_move_back_y * map_width + new_move_back_x])
158                 {
159                     //   Check not visited.
160                     if (! visited(
161                                 new_move_back_x,
162                                 new_move_back_y,
163                                 active_paths.top()))
164                     {
165                         move = active_paths_top;
166                         move.reserve(out_buffer_size);
167                         move.push_back(new_coord);
168                         add_move.set_value(true);
169                     }
170                 }
171             }
172 }

It tells I explicited marked deleted ~__nat, I don't remember even dreaming on doing such a thing.

Am somewhat used to pthreads, Python threads, the Java parallel model... not much versed on indeterminate selections, async in general, promises... Should I yield efforts leaving std::future use?

Upvotes: 0

Views: 1489

Answers (1)

Wolf Siberski
Wolf Siberski

Reputation: 51

The error message relates to a new C++ feature, 'deleting' default operators to make them inaccessible (before, the usual technique was to make them private).

In your case, it indicates an issue with the arguments to the thread constructor. Your code is quite complex, but you might have run into this issue: C++ std::thread "Attempt to use a deleted function"

I would certainly recommend to continue with std:future. For an introduction, the following talk by Herb Sutter on the new C++ concurrency features is highly recommended: https://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Herb-Sutter-Concurrency-and-Parallelism

Upvotes: 2

Related Questions