Last active
June 23, 2017 09:57
-
-
Save Newlifer/5c94c5913db4b8aa911951505fb5b3a3 to your computer and use it in GitHub Desktop.
lock.cpp
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 <mutex> | |
namespace aim { | |
template <typename T> | |
struct MutexLock { | |
using value_type = typename T::value_type; | |
using container_type = T; | |
MutexLock() | |
{} | |
MutexLock(const MutexLock&) = delete; | |
value_type read() { | |
mutex.lock(); | |
auto result = container.pop(); | |
mutex.unlock(); | |
return result; | |
} | |
void write(value_type&& value) { | |
mutex.lock(); | |
container.push(std::move(value)); | |
mutex.unlock(); | |
} | |
value_type read_keep_lock() { | |
mutex.lock(); | |
return container.pop(); | |
} | |
void write_locked(value_type&& value) { | |
container.push(std::move(value)); | |
mutex.unlock(); | |
} | |
private: | |
std::mutex mutex; | |
container_type container; | |
}; | |
} | |
#include <iostream> | |
#include <unordered_map> | |
#include <queue> | |
#include <string> | |
#include <thread> | |
template <typename T=std::size_t> | |
struct ValueContainer { | |
using value_type = T; | |
value_type front() { | |
return value_; | |
} | |
value_type pop() { | |
return value_; | |
} | |
void push(value_type&& value) { | |
value_ = value; | |
} | |
private: | |
value_type value_ = 0; | |
}; | |
template <typename T, template <typename...> class Subcontainer> | |
struct Queue { | |
using subcontainer_t = Subcontainer<T>; | |
using value_type = T; | |
value_type front() const { | |
return cnt.front(); | |
} | |
value_type pop() { | |
auto ret = cnt.front(); | |
cnt.pop(); | |
return ret; | |
} | |
void push(value_type&& value) { | |
cnt.push(std::move(value)); | |
} | |
private: | |
subcontainer_t cnt; | |
}; | |
template <typename T> | |
using Queue_t = Queue<T, std::queue>; | |
aim::MutexLock<ValueContainer<std::size_t>> counter_container; | |
void inc() { | |
auto&& value = counter_container.read_keep_lock(); | |
value += 1; | |
counter_container.write_locked(std::move(value)); | |
} | |
std::mutex io_mutex; | |
void writter(const std::string& name, int value) { | |
do { | |
io_mutex.lock(); | |
std::cout << "Workning on " << name << " with value " << value << "\n"; | |
io_mutex.unlock(); | |
} while (counter_container.read() >= 2); | |
} | |
std::unordered_map<std::string, aim::MutexLock<Queue_t<int>>> queue_collection; | |
void foo(const std::string& queue_name) { | |
while (true) { | |
auto&& value = queue_collection[queue_name].read(); | |
writter(queue_name, value); | |
value *= 10; | |
if (value > 1000) { | |
inc(); | |
return; | |
} | |
queue_collection[queue_name].write(std::move(value)); | |
} | |
} | |
int main() { | |
const std::string first = "first"; | |
const std::string second = "second"; | |
queue_collection[first].write(12); | |
queue_collection[first].write(13); | |
queue_collection[first].write(14); | |
queue_collection[second].write(19); | |
std::thread first_thread(foo, first); | |
std::thread second_thread(foo, second); | |
first_thread.join(); | |
second_thread.join(); | |
std::cout << counter_container.read() << "\n"; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment