Skip to content

Instantly share code, notes, and snippets.

@aligusnet
Created April 24, 2017 13:16
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aligusnet/a5e22511f603517a592ada69c7ffacee to your computer and use it in GitHub Desktop.
Save aligusnet/a5e22511f603517a592ada69c7ffacee to your computer and use it in GitHub Desktop.
C++ multi-threading crash course.
#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