How can i get the return of the functions sent to the std::threads?
I'm working ina function that apllies a filter, created to 2d Images, in each channel of an color/multispectral image. But many of the functions previously implemented in this library have an image as return, i tried to create a function that takes the return image as a parameter, but it didn't work. Here's a copy of the code:
template< class D, class A >
template < typename... Args>
void Image < D, A >::VoidFunction( Image< D, A > &out, Image < D, A > function ( const Image< D, A >& , Args ... ),
const Image <D, A > &in, Args... args ) {
out = ( function ) ( in, args... );
return ;
}
template< class D, class A >
template < typename... Args>
Image < D, A > Image < D, A >::multiSpecImgFilter( Image < D, A > function ( const Image<D, A>& , Args ... ),
const Image <D, A > &img, Args... args ) {
if ( img.Dims() != 3 ) {
std::string msg( std::string( __FILE__ ) + ": " + std::to_string( __LINE__ ) + ": Image<D,A> " + "::" +
std::string( __FUNCTION__ ) + ": error: Image channels must have 2 dimensions" );
throw( std::logic_error( msg ) );
}
std::vector< Image < D, A > > channel = img.Split( );
// std::vector< std::thread > threads ;
// for( size_t thd = 0; thd < channel.size(); ++thd )
// threads[ thd ].join( );
try {
for ( int ch = 0; ch < channel.size() ; ch++ )
std::thread thd ( &VoidFunction, channel[ch], function, channel[ch], args... );
}
catch( ... ) {
for ( int ch = 0; ch < img.size(2) ; ch++ )
channel[ ch ] = ( function ) ( channel [ ch ], args... );
}
return ( Image< D, A >::Merge( channel, img.PixelSize().back(), img.Channel().back() ) );
}
You can use a lambda and store the result in it.
#include <iostream>
#include <thread>
int threadFunction()
{
return 8;
}
int main()
{
int retCode;
//retCode is captured by ref to be sure the modifs are also in the main thread
std::thread t([&retCode](){
std::cout << "thread function\n";
retCode=threadFunction();
});
std::cout << "main thread\n";//this will display 8
t.join();//to avoid a crash
return 0;
}
or pass by std::ref. This is an example from :
https://www.acodersjourney.com/c11-multithreading-tutorial-via-faq-thread-management-basics/
#include <string>
#include <thread>
#include <iostream>
#include <functional>
using namespace std;
void ChangeCurrentMissileTarget(string& targetCity)
{
targetCity = "Metropolis";
cout << " Changing The Target City To " << targetCity << endl;
}
int main()
{
string targetCity = "Star City";
thread t1(ChangeCurrentMissileTarget, std::ref(targetCity));
t1.join();
cout << "Current Target City is " << targetCity << endl;
return 0;
}
The canonical way of doing this, I suppose, is to use async.
#include <functional>
#include <future>
#include <iostream>
int main()
{
auto result = std::async(std::launch::async, std::plus<>{}, 42, 42);
std::cout << result.get() << "\n"; // outputs 84
}
(live demo)
I'd say this looks better than using an output parameter.
You can also directly use a packaged_task:
#include <functional>
#include <future>
#include <iostream>
int main()
{
std::packaged_task<int(int, int)> task{std::plus<>{}};
auto result = task.get_future();
std::thread t{std::move(task), 42, 42};
std::cout << result.get() << "\n"; // outputs 84
t.join();
}
(live demo)
Related
I want to pass in an arbitrary number of functions together with their arguments to a function called startThread so that it can run them concurrently.
My code is below but obviously, it has syntactic errors:
#include <iostream>
#include <thread>
#include <chrono>
#include <vector>
#include <exception>
int test1( int i, double d )
{
// do something...
using namespace std::chrono_literals;
std::this_thread::sleep_for( 3000ms );
return 0;
}
int test2( char c )
{
// do something...
using namespace std::chrono_literals;
std::this_thread::sleep_for( 2000ms );
return 0;
}
template< class Fn, class... Args > // how should I write the template and startThread params to
int startThread( Fn&&... fns, Args&&... args ) // get arbitrary functions as threads and their own arguments?
{
std::vector< std::thread > threads;
threads.push_back( std::thread( test1, 2, 65.2 ) ); // how to automate the task of starting the
threads.push_back( std::thread( test2, 'A' ) ); // threads instead of writing them one by one?
std::cout << "synchronizing all threads...\n";
for ( auto& th : threads ) th.join();
return 0;
}
int main( )
{
int successIndicator { };
try
{
successIndicator = startThread( test1( 2, 65.2 ), test2( 'A' ) ); // what should be passed to startThread?
} // How to pass the arguments?
catch ( const std::exception& e )
{
successIndicator = -1;
std::cerr << e.what( ) << '\n';
}
return successIndicator;
}
Thanks in advance.
This is how I would do it, using a recursive template function.
And std::async instead of std::thread
#include <future>
#include <chrono>
#include <thread>
#include <iostream>
void test1(int /*i*/, double /*d*/)
{
std::cout << "Test1 start\n";
std::this_thread::sleep_for(std::chrono::milliseconds(300));
std::cout << "Test1 done\n";
}
void test2(bool)
{
std::cout << "Test2 start\n";
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "Test2 done\n";
}
//-----------------------------------------------------------------------------
// Recursive template function that will start all passed functions
// and then waits for them to be finished one by one.
// this will still be limited by the slowest function
// so no need to store them in a collection or something
template<typename Fn, typename... Fns>
void run_parallel(Fn fn, Fns&&... fns)
{
// I prefer using std::async instead of std::thread
// it has a better abstraction and futures
// allow passing of exceptions back to the calling thread.
auto future = std::async(std::launch::async, fn);
// are there any more functions to start then do so
if constexpr (sizeof...(fns) > 0)
{
run_parallel(std::forward<Fns>(fns)...);
}
future.get();
}
//-----------------------------------------------------------------------------
int main()
{
std::cout << "main start\n";
// start all functions by creating lambdas for them
run_parallel(
[]() { test1(1, 1.10); },
[]() { test2(true); }
);
std::cout << "main done\n";
}
You can pack these functions into a tuple, and then pack the parameters corresponding to each function into a tuple, and then pass them into startThread() together, then expand the function through std::apply, and then expand the corresponding parameters through std::apply and pass them into the function. Something like this:
template<class FunTuple, class... ArgsTuple>
int startThread(FunTuple fun_tuple, ArgsTuple... args_tuple) {
std::vector<std::thread> threads;
std::apply([&](auto... fun) {
(threads.emplace_back(
[&] { std::apply([&](auto... args) { fun(args...); }, args_tuple); }
), ...);
}, fun_tuple);
std::cout << "synchronizing all threads...\n";
for (auto& th : threads ) th.join();
return 0;
}
Then you can invoke startThread() like this:
startThread(std::tuple(test1, test2), std::tuple(2, 65.2), std::tuple('A'));
Demo.
I was testing the following code, and a bit perplexed as to why count_if is returning me the total of texts?
Match function that takes string of Text as argument and returns true is the Text size is 4
bool Match(string Text)
{
if (Text.size() == 4)
return true;
}
numMatchwes produces the total number of Text in a vector
int numMatches(vector<string>Texts, bool (*Match)(string Text)) // Texts is an array
{
int count = 0;
for (int i = 0; i < Texts.size(); i++)
{
if (Match(Texts[i]) == 1)
// checking every string in vector and returns true
count++;
}
return count;
}
The main function
int main()
{
vector<string> texts;
texts.push_back("Bing");
texts.push_back("Pony");
texts.push_back("Mil");
texts.push_back("Sillty");
texts.push_back("Ballz");
texts.push_back("Mars");
cout << Match("Sind") << endl;
cout << "Matches are: " << numMatches(texts, Match) << endl;
cout << endl;
int num = count_if(texts.begin(), texts.end(), Match); // count_if is STL function
cout << num << endl;
}
Now I’m confused as to why count_if is giving me the total of texts?
The function Match has undefined behavior in case when the passed string does not have a length equal to 4.
Define it the following way
bool Match( const std::string &Text )
{
return Text.size() == 4;
}
Correspondingly the function numMatches can be defined the following way
auto numMatches( const std::vector<std::string> &Texts, bool Match(const std::string & ) )
{
std::vector<std::string>::size_type count = 0;
for ( const auto &s : Texts )
{
if ( Match( s ) ) ++count;
}
return count;
}
Here is your updated program.
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
auto numMatches( const std::vector<std::string> &Texts, bool Match(const std::string & ) )
{
std::vector<std::string>::size_type count = 0;
for ( const auto &s : Texts )
{
if ( Match( s ) ) ++count;
}
return count;
}
bool Match( const std::string &Text )
{
return Text.size() == 4;
}
int main()
{
std::vector<std::string> texts;
texts.push_back( "Bing" );
texts.push_back( "Pony" );
texts.push_back( "Mil" );
texts.push_back( "Sillty" );
texts.push_back( "Ballz" );
texts.push_back( "Mars" );
std::cout << std::boolalpha << Match( "Sind" ) << '\n';
std::cout << "Matches are: " << numMatches( texts, Match ) << '\n';
std::cout << '\n';
auto num = std::count_if( std::begin( texts ), std::end( texts ), Match );
std::cout << num << std::endl;
return 0;
}
The program output is
true
Matches are: 3
3
Could we replace a loop with a strcmp by something easier to read, something similar to the C# extension methods?
I maintain legacy C++ and wonder how to start a transition to a more modern C++ and there is profusion of code that looks like this one:
int numberOfPipe = 10;
char* collection[5] = { "pompe","pipe","turbine","pompe", "pipe" };
// Count the pipes in the collection
int nPipeFound = 0;
int nPipe = 5;
for (int idx = 0; idx < nPipe; idx++)
{
if (strcmp(collection[idx], "pipe") == 0)
nPipeFound++;
}
cout << nPipeFound << endl;
Use the standard library:
Use std::count and use the std::string comparison.
#include <algorithm>
#include <iostream>
#include <string>
int main() {
char const * collection[] = { "pompe","pipe","turbine","pompe","pipe" };
auto n_pipe_found = std::count( std::begin( collection ), std::end( collection ), std::string{"pipe"});
std::cout << n_pipe_found << '\n';
}
Use std::count_if and write a predicate which does C string comparison for you.
#include <algorithm>
#include <cstring>
#include <iostream>
int main() {
char const * collection[] = { "pompe","pipe","turbine","pompe","pipe" };
auto n_pipe_found = std::count_if( std::begin( collection ), std::end( collection ),
[](char const * a) { return std::strcmp(a,"pipe") == 0; } );
std::cout << n_pipe_found << '\n';
}
You could also use a predicate like [](std::string const& a) { return a == "pipe"; } and again make use of std::string comparison.
Use std::accumulate if you need more fine grained control over counting.
#include <numeric>
#include <iostream>
#include <string>
int main() {
char const * collection[] = { "pompe","pipe","turbine","pompe","pipe" };
auto n_pipe_found = std::accumulate( std::begin( collection ), std::end( collection ), int{0},
[](int a, std::string const& b) { return a + (b == "pipe"); });
std::cout << n_pipe_found << '\n';
}
During parsing I have a few attributes that I need to set in semantic action only ( as they are derived from data being parsed and I want to avoid global variables and dependency on BOOST_FUSION_ADAPT_STRUCT as well as my code should be generic so that I can reuse it for multiple types). If I use more than one variable passed into qi::phrase_parse I get very long list of compilation errors. I need a help badly :-)
#define BOOST_RESULT_OF_USE_DECLTYPE
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/function.hpp>
#include <boost/phoenix/fusion.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <string>
#include <climits>
namespace qi = boost::spirit::qi;
namespace ph = boost::phoenix;
namespace ascii = boost::spirit::ascii;
int main( int argc, char**argv )
{
bool rc;
std::string input("");
//Test case 1 works fine
{
auto iter( input.begin() );
auto last( input.end() );
int val1=33;
rc = qi::phrase_parse( iter, last, qi::eps[ qi::_val=11 ] ,
ascii::space, val1 ) && iter==last;
if( rc )
std::cout << "val1=" << val1 << std::endl;
}
//Test case 2 does not compile
{
auto iter( input.begin() );
auto last( input.end() );
int val1=33;
int val2=0;
rc = qi::phrase_parse( iter, last,
qi::eps[ ph::at_c<0>(qi::_val)=1,ph::at_c<1>(qi::_val)=2 ],
ascii::space, val1,val2 ) && iter==last;
if( rc )
std::cout << "val1=" << val1 <<
" val2=" << val2 << std::endl;
}
//Test case 3 works fine
{
auto iter( input.begin() );
auto last( input.end() );
int val1=33;
int val2=0;
rc = qi::phrase_parse( iter, last,
qi::attr(1)>>qi::attr(2),
ascii::space, val1,val2 ) && iter==last;
if( rc )
std::cout << "val1=" << val1 <<
" val2=" << val2 << std::endl;
}
return 0;
}
I took the "customized" my_phrase_parse from cv_and_he but it breaks compilation on the full test case that I want to get running:
template<typename T,typename R>
void testParser( R rule )
{
for ( const auto input : std::vector< std::string >{ "5 1.0 2.0 3.0 4.0 5.0", "1 1.0", "0" , "", "2 3 ab" } )
{
bool rc;
T maxValue;
T minValue;
auto iter( input.begin() );
auto last( input.end() );
std::vector< T > v;
rc = my_phrase_parse( iter, last,
qi::eps[
ph::at_c<0>(qi::_val)=std::numeric_limits<T>::max(),
ph::at_c<1>(qi::_val)=std::numeric_limits<T>::min()
]
>> -( qi::omit[ qi::int_]
>> *rule[ ph::if_(ph::at_c<0>(qi::_val)>qi::_1)[ ph::at_c<0>(qi::_val)=qi::_1 ],
ph::if_(ph::at_c<1>(qi::_val)<qi::_1)[ ph::at_c<1>(qi::_val)=qi::_1 ]
] )
,ascii::space, minValue, maxValue,v ) && iter==last;
std::cout << ( rc ? "ok :`" : "err:`" ) << input << "` -> ";
if( rc )
{
std::cout << "min=" << minValue << " max=" << maxValue << "\t";
std::copy( v.begin(), v.end(), std::ostream_iterator<T>( std::cout," " ));
}
else
std::cout << *iter;
std::cout << std::endl;
}
}
...
testParser<double>( qi::double_ );
The Phoenix placeholders that Spirit uses allow you to manipulate important information from a rule's Context. When you use them directly in an expression in a call to parse or phrase_parse there is no rule, and thus no context. Before version Boost 1.47.0 that didn't work, and in order to make this behaviour consistent a fix was applied to the single argument versions of those functions, but apparently not to the variadic ones.
One way to sidestep this problem is creating a rule that has as attribute a fusion::vector of references to the types you use in your call to phrase_parse.
Edit: removed "my_phrase_parse" since I'm not confident that it is correct
#define BOOST_RESULT_OF_USE_DECLTYPE
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/function.hpp>
#include <boost/phoenix/fusion.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <string>
namespace qi = boost::spirit::qi;
namespace ph = boost::phoenix;
namespace ascii = boost::spirit::ascii;
namespace fusion = boost::fusion;
int main( int argc, char**argv )
{
bool rc;
std::string input("");
//Test case works fine
{
auto iter( input.begin() );
auto last( input.end() );
int val1=33;
rc = qi::phrase_parse( iter, last, qi::eps[ qi::_val=11 ] ,
ascii::space, val1 ) && iter==last;
if( rc )
std::cout << "val1=" << val1 << std::endl;
}
//You can use a rule
{
auto iter( input.begin() );
auto last( input.end() );
int val1=33;
int val2=0;
qi::rule<decltype(iter),fusion::vector<int&, int&>(),ascii::space_type> parser=qi::eps[ ph::at_c<0>(qi::_val)=1,ph::at_c<1>(qi::_val)=2 ];
rc = qi::phrase_parse( iter, last,
parser,
ascii::space, val1,val2 ) && iter==last;
if( rc )
std::cout << "val1=" << val1 <<
" val2=" << val2 << std::endl;
}
return 0;
}
Edit 2: Added another way to approach the problem you want to solve in your edit
#define BOOST_RESULT_OF_USE_DECLTYPE
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi_core.hpp>
#include <boost/spirit/include/qi_omit.hpp>
#include <iostream>
#include <string>
#include <climits>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
template <typename T>
struct min_max_set
{
min_max_set():min(std::numeric_limits<T>::max()),max(std::numeric_limits<T>::min()),set(){}
T min;
T max;
std::vector<T> set;
};
namespace boost{ namespace spirit { namespace traits
{
template <typename T>
struct is_container<min_max_set<T>>
: boost::mpl::true_
{};
template <typename T>
struct container_value<min_max_set<T>>
{
typedef T type;
};
template <typename T>
struct push_back_container<min_max_set<T>,T>
{
static bool call(min_max_set<T>& cont, const T& val)
{
if(cont.min>val)
cont.min=val;
if(cont.max<val)
cont.max=val;
cont.set.push_back(val);
return true;
}
};
}}}
template<typename T,typename R>
void testParser( R rule )
{
for ( const auto input : std::vector< std::string >{ "5 1.0 2.0 3.0 4.0 5.0", "1 1.0", "0" , "", "2 3 ab" } )
{
bool rc;
auto iter( input.begin() );
auto last( input.end() );
min_max_set<T> accum;
rc = qi::phrase_parse( iter, last,
qi::omit[qi::int_] >> *rule
,ascii::space, accum ) && iter==last;
std::cout << ( rc ? "ok :`" : "err:`" ) << input << "` -> ";
if( rc )
{
std::cout << "min=" << accum.min << " max=" << accum.max << "\t";
std::copy( accum.set.begin(), accum.set.end(), std::ostream_iterator<T>( std::cout," " ));
}
else
std::cout << *iter;
std::cout << std::endl;
}
}
int main( int argc, char**argv )
{
testParser<double>(qi::double_);
return 0;
}
This is workaround for my initial problem:
#define BOOST_RESULT_OF_USE_DECLTYPE
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/function.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
#include <climits>
namespace qi = boost::spirit::qi;
namespace ph = boost::phoenix;
namespace ascii = boost::spirit::ascii;
template<typename T,typename R>
void testParser( R rule )
{
for ( const auto &input : std::vector< std::string >{ "5 1.0 2.0 3.0 4.0 5.0" } )
{
bool rc=false;
T maxValue, minValue;
auto iter( input.begin() ), last( input.end() );
std::vector< T > data;
qi::rule< decltype(iter),std::vector<T>( T&, T& ),qi::space_type > mrule;
mrule %=
qi::eps[ qi::_r1=std::numeric_limits<T>::max(),
qi::_r2=std::numeric_limits<T>::min() ] >>
-( qi::omit[ qi::int_[ ph::reserve( qi::_val,qi::_1 ) ] ]
>> *rule[ ph::if_(qi::_r1>qi::_1)[ qi::_r1=qi::_1 ],
ph::if_(qi::_r2<qi::_1)[ qi::_r2=qi::_1 ]
] );
rc = qi::phrase_parse( iter, last, mrule( ph::ref(minValue), ph::ref(maxValue) ), qi::space, data ) && iter==last;
std::cout << ( rc ? "ok :`" : "err:`" ) << input << "` -> ";
if( rc )
{
std::cout << "min=" << minValue << " max=" << maxValue << "\t";
std::copy( data.begin(), data.end(), std::ostream_iterator<T>( std::cout," " ));
}
else
std::cout << *iter;
std::cout << std::endl;
}
}
int main( int argc, char**argv )
{
testParser<double>( qi::double_ );
return 0;
}
I hope I see the problem correctly, but even if that's a little different, you can store several values without hassle:
struct data {
int _a;
int _b;
data(int a, int b) : _a(a), _b(b) {};
};
And construct it:
qi::eps[qi::_val = phx::construct<data>(1, 2)]
#include <iostream>
#include <queue>
using namespace std;
struct Call
{
Call( int callNum, long callTime, int callLength ) :
CallNum( callNum ), CallTime( callTime ), CallLength( callLength ) { }
int CallNum;
long CallTime;
int CallLength;
};
bool operator>( const Call& lhs, const Call& rhs ) {
return lhs.CallLength > rhs.CallLength;
}
ostream& operator<<( ostream& os, const Call& c ) {
os << c.CallNum << " " << c.CallTime << " " << c.CallLength;
return os;
}
int main()
{
priority_queue< Call, vector<Call>, greater<Call> > q;
q.push( Call( 1, 200, 150 ));
q.push( Call( 2, 300, 950 ));
q.push( Call( 3, 100, 450 ));
q.push( Call( 4, 150, 320 ));
unsigned i=0, n=q.size();
for ( i=0; i<n; ++i ) {
cout << q.top() << endl;
q.pop();
}
}
This is my code. My problem is, When I use q.top(); it prints to screen callNum, callTime, callLength. But I want to use them seperately.
I mean How can I print to screen just callTime? for ex: q.top(callTime); or something else? who can help me?
Are you just looking for:
cout << q.top().CallNum << endl;
and so on?