codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
#include <chrono> #include <cstdlib> #include <functional> #include <future> #include <iostream> #include <memory> #include <string> #include <thread> #include <utility> #include <vector> /// Waits until a predicate proves true, then calls a function. class when { public: /// Constructor. /// \tparam Predicate A callable object which returns true when a condition is met. /// \tparam Callable Another callable object. Will be called when the condition is met. /// \tparam Args A variadic list of argument types. /// \param p The predicate. /// \param c The function to call when the predicate is true. /// \param args The variadic list of arguments. template <class Predicate, class Callable, typename... Args> when(Predicate p, Callable c, Args... args) { std::thread thread(when_thread_entry<Predicate, Callable, Args...>(p, c, args...)); thread.detach(); } private: /// std::thread entry point for 'when'. /// \tparam Predicate A callable object which returns true when a condition is met. /// \tparam Callable Another callable object. Will be called when the condition is met. /// \tparam Args A variadic list of argument types. template <class Predicate, class Callable, typename... Args> struct when_thread_entry { /// Constructor. /// \param p The predicate. /// \param c The function to call when the predicate is true. /// \param args The variadic list of arguments. when_thread_entry(Predicate p, Callable c, Args... args) : predicate(p), function(c), tuple(args...) { // Do nothing. } /// Waits until the predicate becomes true, then calls the function. void operator()() { while (!(predicate())) std::this_thread::yield(); call_function(); } private: /// Stores the indices of a tuple. template <int... Indices> struct index {}; /// Generates a sequence of indices for a tuple. template <int N, int... Indices> struct gen_seq : gen_seq<N - 1, N - 1, Indices...> {}; /// Generates a sequence of indices for a tuple. template <int... Indices> struct gen_seq<0, Indices...> : index<Indices...> {}; /// The predicate. Predicate predicate; /// The function. Callable function; /// A tuple containing the arguments. std::tuple<Args...> tuple; /// Expands the arguments-tuple back into variadic arguments and calls the function. template <int... Indices> void call_function(index<Indices...>) { function(std::get<Indices>(tuple)...); } /// Calls the function with its arguments. void call_function() { call_function(gen_seq<sizeof...(Args)>{}); } }; }; /// Returns true when a pre-set timeout elapses. struct timeout_predicate { /// Constructor. /// \param duration The duration to wait. timeout_predicate(std::time_t duration) : end(curtime() + duration) { // Do nothing. } /// Returns true when the timeout elapses. bool operator()() { return (curtime() >= end); } private: /// The time at which the original duration will have elapsed. std::time_t end; /// Gets the current time as a time_t (because std::chrono is designed for editors running on the silver screen). std::time_t curtime() { return std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); } }; /// Calls a function after a timeout elapses. class after : public when { public: /// Constuctor. /// \tparam Callable A callable object. /// \tparam Args A variadic list of template argument types for Callable. /// \param timeout The timeout. /// \param c The callable object. /// \param args The variadic arguments. template <class Callable, typename... Args> after(std::time_t timeout, Callable c, Args... args) : when(timeout_predicate(timeout), c, args...) { // Do nothing. } }; /// Prints strings. struct string_printer { /// Constructor. /// \param stream The stream to print on. string_printer(std::ostream& stream) : m_stream(stream) { // Do nothing. } /// Prints a string. /// \param string The string to print. void operator()(const std::string& string) { m_stream << string; } private: /// The stream. std::ostream& m_stream; }; /// Flushes streams. struct stream_flusher { /// Constructor. /// \param stream The stream to print on. stream_flusher(std::ostream& stream) : m_stream(stream) { // Do nothing. } /// Flushes the stream. void operator()() { m_stream << std::flush; } private: /// The stream. std::ostream& m_stream; }; /// Exits the program. struct program_exiter { /// Exits the program. /// \param exit_code The exit status to return. void operator()(int exit_code = EXIT_SUCCESS) { std::exit(exit_code); } }; int main() { // Create function objects. string_printer printer(std::cout); stream_flusher flusher(std::cout); program_exiter exiter; // Create 'after' objects. After x seconds each one will call its function with whatever arguments we pass. after( 9, flusher); after( 7, printer, "hello, world\n"); after( 3, printer, "Message: "); after( 5, flusher); after(10, exiter, EXIT_SUCCESS); // Wait for all the threads to finish and the program to exit. // FIXME: Currently, when they go out of scope, the program breaks. If this was fixed, this loop would be // unnecessary. while (true) ; return 0; }
Private
[
?
]
Run code
Submit