Created
April 24, 2017 13:16
-
-
Save aligusnet/a5e22511f603517a592ada69c7ffacee to your computer and use it in GitHub Desktop.
C++ multi-threading crash course.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <future> | |
#include <condition_variable> | |
#include <mutex> | |
#include <thread> | |
#include <queue> | |
// One Way Channel a.k.a. Message Queue | |
template <typename T> | |
class OneWayChannel { | |
public: | |
void push(T msg) { | |
std::lock_guard<std::mutex> lock(mutex_); | |
msgs_.push(std::move(msg)); | |
cond_.notify_one(); | |
} | |
T pop() { | |
std::unique_lock<std::mutex> lock(mutex_); | |
cond_.wait(lock, [this]{ return !msgs_.empty(); }); | |
T msg = std::move(msgs_.front()); | |
msgs_.pop(); | |
return msg; | |
} | |
private: | |
std::mutex mutex_; | |
std::condition_variable cond_; | |
std::queue<T> msgs_; | |
}; | |
void test_channel_async() { | |
OneWayChannel<std::string> queue; | |
std::future<void> fut = std::async(std::launch::async, [&queue]{ queue.push("Hello from thread"); }); | |
std::cout << "waiting from thread...\n"; | |
std::cout << queue.pop() << std::endl; | |
fut.wait(); | |
} | |
void test_channel_thread() { | |
OneWayChannel<std::string> queue; | |
std::thread th([](OneWayChannel<std::string> & queue) { queue.push("Hello from thread2"); }, std::ref(queue)); | |
std::cout << "waiting from thread...\n"; | |
std::cout << queue.pop() << std::endl; | |
th.join(); | |
} | |
void func(std::promise<std::string> && pr, bool flag) { | |
try { | |
if (flag) { | |
pr.set_value("Hello from thread 3"); | |
} else { | |
throw std::runtime_error("A-a-a-ah"); | |
} | |
} catch(...) { | |
pr.set_exception(std::current_exception()); | |
} | |
} | |
void test_promise(bool flag) { | |
std::promise<std::string> pr; | |
std::future<std::string> fut = pr.get_future(); | |
std::thread th(func, std::move(pr), flag); | |
try { | |
std::cout << "waiting from thread...\n"; | |
std::cout << fut.get() << std::endl; | |
} catch (const std::exception &ex) { | |
std::cout << "caught: " << ex.what() << std::endl; | |
} | |
th.join(); | |
} | |
std::string func2(bool flag) { | |
if (flag) { | |
return "Hello from thread 4"; | |
} else { | |
throw std::runtime_error("A-a-a-ah"); | |
} | |
} | |
void test_async(bool flag) { | |
std::future<std::string> fut = std::async(std::launch::async, func2, flag); | |
try { | |
std::cout << "waiting from thread...\n"; | |
std::cout << fut.get() << std::endl; | |
} catch (const std::exception &ex) { | |
std::cout << "caught: " << ex.what() << std::endl; | |
} | |
} | |
int main() { | |
std::cout << "One Way Channel test using async\n"; | |
test_channel_async(); | |
std::cout << "\nOne Way Channel test using threads\n"; | |
test_channel_thread(); | |
std::cout << "\nTest promise using threads\n"; | |
test_promise(true); | |
test_promise(false); | |
std::cout << "\nTest async (wrapper over threads and promise)\n"; | |
test_async(true); | |
test_async(false); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment