Last active
March 1, 2024 01:36
-
-
Save farhangamary/ae9803f917059a3e5cb26a58277d8d53 to your computer and use it in GitHub Desktop.
A shared resource which can get read and written alternately among multiple threads
This file contains hidden or 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
| cmake_minimum_required(VERSION 3.18) | |
| project(multith | |
| VERSION 0.1 | |
| DESCRIPTION "A sample of a shared resource") | |
| set(CMAKE_CXX_STANDARD 17) | |
| add_executable(multith starter.cpp) |
This file contains hidden or 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 "Message.hpp" | |
| Message::Message() : value_(""), last_writer_id_(-1), last_reader_id_(-1) {} | |
| Message::~Message() {} | |
| void Message::set_value(std::string value, int writer_id) | |
| { | |
| std::unique_lock write_lock(mtx_); | |
| cv_.wait(write_lock, | |
| [writer_id, this] | |
| { return can_write(writer_id); }); | |
| value_ = value; | |
| last_writer_id_ = writer_id; | |
| cv_.notify_all(); | |
| } | |
| std::string Message::get_value(int reader_id) | |
| { | |
| std::unique_lock read_lock(mtx_); | |
| cv_.wait(read_lock, | |
| [reader_id, this] | |
| { return can_read(reader_id); }); | |
| last_reader_id_ = reader_id; | |
| cv_.notify_all(); | |
| return value_; | |
| } | |
| bool Message::can_write(int writer_id) | |
| { | |
| return writer_id == last_reader_id_ || value_.empty(); | |
| } | |
| bool Message::can_read(int reader_id) | |
| { | |
| return reader_id != last_writer_id_ && !value_.empty(); | |
| } |
This file contains hidden or 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 <thread> | |
| #include <mutex> | |
| #include <condition_variable> | |
| class Message | |
| { | |
| private: | |
| std::string value_; | |
| int last_writer_id_; | |
| int last_reader_id_; | |
| std::condition_variable cv_; | |
| std::mutex mtx_; | |
| public: | |
| Message(); | |
| virtual ~Message(); | |
| void set_value(std::string value, int writer_id); | |
| std::string get_value(int reader_id); | |
| bool can_read(int reader_id); | |
| bool can_write(int writer_id); | |
| }; |
This file contains hidden or 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
| $ cmake -S . -B bin | |
| -- The C compiler identification is GNU 11.4.0 | |
| -- The CXX compiler identification is GNU 11.4.0 | |
| -- Detecting C compiler ABI info | |
| -- Detecting C compiler ABI info - done | |
| -- Check for working C compiler: /usr/bin/cc - skipped | |
| -- Detecting C compile features | |
| -- Detecting C compile features - done | |
| -- Detecting CXX compiler ABI info | |
| -- Detecting CXX compiler ABI info - done | |
| -- Check for working CXX compiler: /usr/bin/c++ - skipped | |
| -- Detecting CXX compile features | |
| -- Detecting CXX compile features - done | |
| -- Configuring done | |
| -- Generating done | |
| -- Build files have been written to: /***/bin | |
| $ cmake --build bin | |
| [ 50%] Building CXX object CMakeFiles/multith.dir/starter.cpp.o | |
| [100%] Linking CXX executable multith | |
| [100%] Built target multith | |
| $ bin/multith | |
| Hello and welcome. | |
| Th#1 writes: "InitVAL" | |
| Th#2 read__: "InitVAL" | |
| Th#2 writes: "InitVAL0" | |
| Th#1 read__: "InitVAL0" | |
| Th#1 writes: "InitVAL00" | |
| Th#2 read__: "InitVAL00" | |
| Th#2 writes: "InitVAL001" | |
| Th#1 read__: "InitVAL001" | |
| Th#1 writes: "InitVAL0011" | |
| Th#2 read__: "InitVAL0011" | |
| Th#2 writes: "InitVAL00112" | |
| Th#1 read__: "InitVAL00112" | |
| Th#1 writes: "InitVAL001122" | |
| Th#2 read__: "InitVAL001122" | |
| Th#2 writes: "InitVAL0011223" | |
| Th#1 read__: "InitVAL0011223" | |
| Th#1 writes: "InitVAL00112233" | |
| Th#2 read__: "InitVAL00112233" | |
| Th#2 writes: "InitVAL001122334" | |
| Th#1 read__: "InitVAL001122334" | |
| Th#1 writes: "InitVAL0011223344" |
This file contains hidden or 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 <thread> | |
| #include "Message.cpp" | |
| using namespace std; | |
| shared_ptr<Message> msg; | |
| void chat(int id) | |
| { | |
| if (id == 1) | |
| { | |
| msg.get()->set_value("InitVAL", id); | |
| cout << "Th#" << id << " writes: \"InitVAL\"" << endl; | |
| this_thread::sleep_for(chrono::milliseconds(75)); | |
| } | |
| for (int i = 0; i < 5; ++i) | |
| { | |
| string current_msg = msg.get()->get_value(id); | |
| cout << "Th#" << id << " read__: \"" << current_msg << "\"" << endl; | |
| this_thread::sleep_for(chrono::milliseconds(75)); | |
| string new_message = current_msg + to_string(i); | |
| cout << "Th#" << id << " writes: \"" << new_message << "\"" << endl; | |
| msg.get()->set_value(new_message, id); | |
| this_thread::sleep_for(chrono::milliseconds(75)); | |
| } | |
| } | |
| int main(int args_count, char *args[]) | |
| { | |
| msg = make_shared<Message>(); | |
| cout << "Hello and welcome." << endl | |
| << endl; | |
| thread th_2(chat, 2); | |
| thread th_1(chat, 1); | |
| th_1.join(); | |
| th_2.join(); | |
| return EXIT_SUCCESS; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment