| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 
 | #include <iostream>
#include <future>
#include <chrono>
#include <tuple>
#include <type_traits>
#include <string>
 
namespace tupleit {
	// utilitaires pour la manipulation de tuple
	template<std::size_t I = 0, typename FuncT, typename... Tp>
	inline typename std::enable_if<I == sizeof...(Tp), void>::type
	for_each(std::tuple<Tp...>&, FuncT)
	{ }
 
	template<std::size_t I = 0, typename FuncT, typename... Tp>
	inline typename std::enable_if < I <sizeof...(Tp), void>::type
	for_each(std::tuple<Tp...>& t, FuncT f)
	{
		f(std::get<I>(t));
		for_each < I + 1 > (t, f);
	}
}
 
struct Cin 
{
	template <typename T>
	void operator()(T& t) {
		std::cin >> t;
	}
};
 
template <typename... Args>
class asyncin {
	std::future<void> ftr;
	std::tuple<Args...> ret;
public:
	asyncin() : ftr(std::async(std::launch::async, [this]() {
            tupleit::for_each(ret, Cin());
	}))
	{}
 
	template< class Rep, class Period >
	std::future_status  wait_for(const std::chrono::duration<Rep,Period>& timeout_duration) const {
		return ftr.wait_for(timeout_duration);
	}
 
	// fonction bloquante
	void get(Args&... args) const {
		ftr.wait();
		std::tie(args...) = ret; // todo : copy -> move
	}
 
};
 
int main()
{
	// entree asynchrone de myint et mystr
	int myint{};
	std::string mystr{};
	asyncin<int, std::string> acin{};
 
	// ... pendant un traitement quelconque ...
	for(auto i : {1, 2, 3, 4, 5, 6, 7 ,8 ,9}) {
		std::cout << i;
		std::this_thread::sleep_for(std::chrono::seconds(1));
	}
 
	// On attend myint et mystr
	if(std::future_status::ready == acin.wait_for(std::chrono::seconds(1))) {
		if(std::cin.good()) {
			acin.get(myint, mystr);
			std::cout << std::endl << "(Myint, Mystr) = (" << myint << ", " << mystr << ")";
		} 
		else {
			std::cout << std::endl << "Bad input" << std::endl;
			std::cin.clear();
		}
	}
	else {
		std::cout << "Timeout ! " << std::endl;
		// On ne peut pas annuler l'operation asynchrone en std C++11 (tuer le thread)
		// On a le choix :
		//  - reboucler et attendre indefiniment le thread 
		// OU
		//  - recuperer std::thread::native_handle et tuer le thread avec l'API native 
		//	  dans le destructeur de asyncin par exemple qui se chargerait de nettoyer egalement le buffer de cin.
	}
    return 0;
} | 
Partager