2012-06-07 18 views
5

Sto cercando di lanciare una funzione in un thread utilizzando std::packaged_taskstd :: packaged_task errore di compilazione w/gcc 4.6

Query query; /* protobuf object */   

/* fill Query object */ 

std::packaged_task<SearchResults(Query&)> task([](Query& q) ->SearchResults { 
    index::core::Merger merger; 
    return merger.search(q); 
    }); 

std::future<SearchResults> ftr = task.get_future(); 
std::thread(std::move(task),query).detach(); 

Edit2: Aggiornato il codice nuovo per correggere gli errori e incluso il messaggio di errore completo.

g ++ - 4.6 (su Ubuntu 10.04) è in grado di compilare il codice:

In file included from /usr/include/c++/4.6/memory:80:0, 
       from ../src/net/QueryConnection.cpp:8: 
/usr/include/c++/4.6/functional: In instantiation of ‘std::_Bind_result<void, 
std::packaged_task<SearchResults(Query&)>(Query)>’: 
/usr/include/c++/4.6/thread:135:9: instantiated from ‘std::thread::thread(_Callable&&, 
_Args&& ...) [with _Callable = std::packaged_task<SearchResults(Query&)>, _Args = 
{Query&}]’ 
../src/net/QueryConnection.cpp:77:36: instantiated from here 
/usr/include/c++/4.6/functional:1365:7: error: ‘std::_Bind_result<_Result, 
_Functor(_Bound_args ...)>::_Bind_result(const std::_Bind_result<_Result, 
_Functor(_Bound_args ...)>&) [with _Result = void, _Functor = 
std::packaged_task<SearchResults(Query&)>, _Bound_args = {Query}, 
std::_Bind_result<_Result, _Functor(_Bound_args ...)> = std::_Bind_result<void, 
std::packaged_task<SearchResults(Query&)>(Query)>]’ declared to take const reference, 
but implicit declaration would take non-const 
Build error occurred, build is stopped 

ho letto che questo è forse a causa di un bug: gcc-mailinglist

Sono nuovo di C++/C++ 11 - Quale sarebbe una buona alternativa di lavoro? Ho solo bisogno di avviare una discussione che mi dà un futuro, il cui metodo get() viene chiamato più tardi in un ciclo asincrono boost::asio.

+0

Un problema è che hai dichiarato che il pacchetto_packaged non accetta argomenti e restituisce un SearchResults, ma lambda accetta un singolo argomento. Mi aspetto che la tua dichiarazione sia 'std :: packageaged_task ' –

+0

Puoi davvero pubblicare il messaggio di errore completo? Sembra che tu abbia postato solo la metà. Ciò lo rende inintelligibile. –

+0

Ho modificato il codice per riflettere l'argomento mancante e ho aggiunto il messaggio di errore completo con il codice aggiornato. Ancora un sacco di problemi. –

risposta

3

Si tratta di un bug in GCC 4.6 (in realtà uno defect nello standard C++ 11) che ho già risolto in 4.7.

Come soluzione alternativa è possibile utilizzare std::async

Query query; 
std::future<SearchResults> ftr = std::async([](Query& q) ->SearchResults { 
     index::core::Merger merger; 
     return merger.search(q); 
    }, query); 

Questo funziona bene con GCC 4.6, ed è più semplice e più sicuro che la creazione di un packaged_task ed eseguirlo in un thread indipendente in ogni caso.

+0

Grazie! Funziona! –

1

Non so se questi sono la causa degli errori che GCC sta dando, ma sono comunque problematici.

[=](Query& q){ 
     index::core::Merger merger; 
     return merger.search(q); 
} 

Dal momento che questo lambda non consiste di una singola istruzione di ritorno, e nessun tipo di ritorno esplicito è stato dato, che ha un tipo di void ritorno. Sospetto che tu abbia inteso restituire un oggetto SearchResults. E ci vuole un parametro Query&, quindi la firma appropriata per l'attività pacchettizzata sarebbe SearchResults(Query&).

[=](Query& q) -> SearchResults { 
     index::core::Merger merger; 
     return merger.search(q); 
} 
+0

Grazie per la risposta, ho provato a cambiare subito a: 'std :: attività ([SearchResults] (Query & q) { Indice :: :: nucleo fusione Fusione; return merger.search (q); }); ' –

+0

@emteh Oh, mi dispiace per quello. Questa non è la sintassi corretta. L'ho modificato. Sono uscito per fare qualcos'altro e ho dimenticato di scrivere la sintassi corretta nella risposta ... –

+0

Grazie, è stato corretto. Gli errori relativi a quello svanirono. Ho ancora il messaggio di errore originale. '[=]' Vs. '[]' non fa differenza. –

0

Il codice aggiornato ha due problemi:

1) Il lambda non preveda che sia tipo di ritorno in modo corretto. La sintassi che vuoi è (ammesso che non c'è bisogno di copiare tutte le variabili locali) è:

[](Query& q) -> SearchResults { 
     index::core::Merger merger; 
     return merger.search(q); 
} 

2) Dato che il compito confezionato richiede un Query&, allora si avrà bisogno di passare un riferimento a un non Query costante come secondo argomento del costruttore std::thread, in modo che possa essere passato all'attività.

Ciò che non ricordo è se è possibile passare correttamente un riferimento di query non costante come secondo argomento a std::thread o se è necessario utilizzare std::ref(q) in modo che passi correttamente il secondo argomento per riferimento.

Come scritto, si sta tentando di chiamare il compito senza argomenti, come indicato dalla

/usr/include/c++/4.6/future:1272:7: nota: candidato si aspetta 1 argomento, a condizione 0

+0

'std :: thread' copierà gli argomenti per impostazione predefinita, quindi è necessario' std :: ref' –

+0

@davs: Grazie risolto ora, che ha risolto alcuni problemi. L'errore originale è ancora lì, attraverso. –

+0

@JonathanWakely: Grazie, 'std: ref (query)' non fa differenza attraverso. Ancora l'errore relativo a 'std :: bind'. –

Problemi correlati