Run clang-format

This commit is contained in:
Bassem Girgis
2018-10-18 00:40:34 -05:00
parent fffe4528da
commit 31c32e368a
149 changed files with 5974 additions and 6287 deletions

View File

@@ -1,13 +1,15 @@
#include <iostream>
#include <thread>
void hello()
void
hello()
{
std::cout<<"Hello Concurrent World\n";
std::cout << "Hello Concurrent World\n";
}
int main()
int
main()
{
std::thread t(hello);
t.join();
std::thread t(hello);
t.join();
}

View File

@@ -1,42 +1,35 @@
void test_concurrent_push_and_pop_on_empty_queue()
void
test_concurrent_push_and_pop_on_empty_queue()
{
threadsafe_queue<int> q;
threadsafe_queue<int> q;
std::promise<void> go,push_ready,pop_ready;
std::shared_future<void> ready(go.get_future());
std::promise<void> go, push_ready, pop_ready;
std::shared_future<void> ready(go.get_future());
std::future<void> push_done;
std::future<int> pop_done;
std::future<void> push_done;
std::future<int> pop_done;
try
{
push_done=std::async(std::launch::async,
[&q,ready,&push_ready]()
{
push_ready.set_value();
ready.wait();
q.push(42);
}
);
pop_done=std::async(std::launch::async,
[&q,ready,&pop_ready]()
{
pop_ready.set_value();
ready.wait();
return q.pop();
}
);
push_ready.get_future().wait();
pop_ready.get_future().wait();
go.set_value();
try {
push_done = std::async(std::launch::async, [&q, ready, &push_ready]() {
push_ready.set_value();
ready.wait();
q.push(42);
});
pop_done = std::async(std::launch::async, [&q, ready, &pop_ready]() {
pop_ready.set_value();
ready.wait();
return q.pop();
});
push_ready.get_future().wait();
pop_ready.get_future().wait();
go.set_value();
push_done.get();
assert(pop_done.get()==42);
assert(q.empty());
}
catch(...)
{
go.set_value();
throw;
}
push_done.get();
assert(pop_done.get() == 42);
assert(q.empty());
}
catch (...) {
go.set_value();
throw;
}
}

View File

@@ -1,35 +1,35 @@
#include <thread>
void do_something(int& i)
void
do_something(int& i)
{
++i;
++i;
}
struct func
{
int& i;
struct func {
int& i;
func(int& i_):i(i_){}
func(int& i_) : i(i_) {}
void operator()()
{
for(unsigned j=0;j<1000000;++j)
{
do_something(i);
}
void operator()()
{
for (unsigned j = 0; j < 1000000; ++j) {
do_something(i);
}
}
};
void oops()
void
oops()
{
int some_local_state=0;
func my_func(some_local_state);
std::thread my_thread(my_func);
my_thread.detach();
int some_local_state = 0;
func my_func(some_local_state);
std::thread my_thread(my_func);
my_thread.detach();
}
int main()
int
main()
{
oops();
oops();
}

View File

@@ -1,46 +1,47 @@
#include <thread>
void do_something(int& i)
void
do_something(int& i)
{
++i;
++i;
}
struct func
{
int& i;
struct func {
int& i;
func(int& i_):i(i_){}
func(int& i_) : i(i_) {}
void operator()()
{
for(unsigned j=0;j<1000000;++j)
{
do_something(i);
}
void operator()()
{
for (unsigned j = 0; j < 1000000; ++j) {
do_something(i);
}
}
};
void do_something_in_current_thread()
{}
void f()
void
do_something_in_current_thread()
{
int some_local_state=0;
func my_func(some_local_state);
std::thread t(my_func);
try
{
do_something_in_current_thread();
}
catch(...)
{
t.join();
throw;
}
}
void
f()
{
int some_local_state = 0;
func my_func(some_local_state);
std::thread t(my_func);
try {
do_something_in_current_thread();
}
catch (...) {
t.join();
throw;
}
t.join();
}
int main()
int
main()
{
f();
f();
}

View File

@@ -1,58 +1,57 @@
#include <thread>
class thread_guard
{
std::thread& t;
class thread_guard {
std::thread& t;
public:
explicit thread_guard(std::thread& t_):
t(t_)
{}
~thread_guard()
{
if(t.joinable())
{
t.join();
}
explicit thread_guard(std::thread& t_) : t(t_) {}
~thread_guard()
{
if (t.joinable()) {
t.join();
}
thread_guard(thread_guard const&)=delete;
thread_guard& operator=(thread_guard const&)=delete;
}
thread_guard(thread_guard const&) = delete;
thread_guard& operator=(thread_guard const&) = delete;
};
void do_something(int& i)
void
do_something(int& i)
{
++i;
++i;
}
struct func
{
int& i;
struct func {
int& i;
func(int& i_):i(i_){}
func(int& i_) : i(i_) {}
void operator()()
{
for(unsigned j=0;j<1000000;++j)
{
do_something(i);
}
void operator()()
{
for (unsigned j = 0; j < 1000000; ++j) {
do_something(i);
}
}
};
void do_something_in_current_thread()
{}
void f()
void
do_something_in_current_thread()
{
int some_local_state;
func my_func(some_local_state);
std::thread t(my_func);
thread_guard g(t);
do_something_in_current_thread();
}
int main()
void
f()
{
f();
int some_local_state;
func my_func(some_local_state);
std::thread t(my_func);
thread_guard g(t);
do_something_in_current_thread();
}
int
main()
{
f();
}

View File

@@ -1,61 +1,61 @@
#include <thread>
#include <string>
#include <thread>
void open_document_and_display_gui(std::string const& filename)
{}
bool done_editing()
void
open_document_and_display_gui(std::string const& filename)
{
return true;
}
enum command_type{
open_new_document
bool
done_editing()
{
return true;
}
enum command_type { open_new_document };
struct user_command {
command_type type;
user_command() : type(open_new_document) {}
};
struct user_command
user_command
get_user_input()
{
command_type type;
user_command():
type(open_new_document)
{}
};
user_command get_user_input()
{
return user_command();
return user_command();
}
std::string get_filename_from_user()
std::string
get_filename_from_user()
{
return "foo.doc";
return "foo.doc";
}
void process_user_input(user_command const& cmd)
{}
void edit_document(std::string const& filename)
void
process_user_input(user_command const& cmd)
{
open_document_and_display_gui(filename);
while(!done_editing())
{
user_command cmd=get_user_input();
if(cmd.type==open_new_document)
{
std::string const new_name=get_filename_from_user();
std::thread t(edit_document,new_name);
t.detach();
}
else
{
process_user_input(cmd);
}
}
void
edit_document(std::string const& filename)
{
open_document_and_display_gui(filename);
while (!done_editing()) {
user_command cmd = get_user_input();
if (cmd.type == open_new_document) {
std::string const new_name = get_filename_from_user();
std::thread t(edit_document, new_name);
t.detach();
}
else {
process_user_input(cmd);
}
}
}
int main()
int
main()
{
edit_document("bar.doc");
edit_document("bar.doc");
}

View File

@@ -1,27 +1,34 @@
#include <thread>
void some_function()
{}
void some_other_function(int)
{}
std::thread f()
void
some_function()
{
void some_function();
return std::thread(some_function);
}
std::thread g()
{
void some_other_function(int);
std::thread t(some_other_function,42);
return t;
}
int main()
void
some_other_function(int)
{
std::thread t1=f();
t1.join();
std::thread t2=g();
t2.join();
}
std::thread
f()
{
void some_function();
return std::thread(some_function);
}
std::thread
g()
{
void some_other_function(int);
std::thread t(some_other_function, 42);
return t;
}
int
main()
{
std::thread t1 = f();
t1.join();
std::thread t2 = g();
t2.join();
}

View File

@@ -1,56 +1,55 @@
#include <thread>
#include <utility>
class scoped_thread
{
std::thread t;
class scoped_thread {
std::thread t;
public:
explicit scoped_thread(std::thread t_):
t(std::move(t_))
{
if(!t.joinable())
throw std::logic_error("No thread");
}
~scoped_thread()
{
t.join();
}
scoped_thread(scoped_thread const&)=delete;
scoped_thread& operator=(scoped_thread const&)=delete;
explicit scoped_thread(std::thread t_) : t(std::move(t_))
{
if (!t.joinable())
throw std::logic_error("No thread");
}
~scoped_thread() { t.join(); }
scoped_thread(scoped_thread const&) = delete;
scoped_thread& operator=(scoped_thread const&) = delete;
};
void do_something(int& i)
void
do_something(int& i)
{
++i;
++i;
}
struct func
{
int& i;
struct func {
int& i;
func(int& i_):i(i_){}
func(int& i_) : i(i_) {}
void operator()()
{
for(unsigned j=0;j<1000000;++j)
{
do_something(i);
}
void operator()()
{
for (unsigned j = 0; j < 1000000; ++j) {
do_something(i);
}
}
};
void do_something_in_current_thread()
{}
void f()
void
do_something_in_current_thread()
{
int some_local_state;
scoped_thread t(std::thread(func(some_local_state)));
do_something_in_current_thread();
}
int main()
void
f()
{
f();
int some_local_state;
scoped_thread t(std::thread(func(some_local_state)));
do_something_in_current_thread();
}
int
main()
{
f();
}

View File

@@ -1,23 +1,26 @@
#include <vector>
#include <thread>
#include <algorithm>
#include <functional>
#include <thread>
#include <vector>
void do_work(unsigned id)
{}
void f()
void
do_work(unsigned id)
{
std::vector<std::thread> threads;
for(unsigned i=0;i<20;++i)
{
threads.push_back(std::thread(do_work,i));
}
std::for_each(threads.begin(),threads.end(),
std::mem_fn(&std::thread::join));
}
int main()
void
f()
{
f();
std::vector<std::thread> threads;
for (unsigned i = 0; i < 20; ++i) {
threads.push_back(std::thread(do_work, i));
}
std::for_each(
threads.begin(), threads.end(), std::mem_fn(&std::thread::join));
}
int
main()
{
f();
}

View File

@@ -1,67 +1,66 @@
#include <thread>
#include <numeric>
#include <algorithm>
#include <functional>
#include <vector>
#include <iostream>
#include <numeric>
#include <thread>
#include <vector>
template<typename Iterator,typename T>
struct accumulate_block
{
void operator()(Iterator first,Iterator last,T& result)
{
result=std::accumulate(first,last,result);
}
template <typename Iterator, typename T>
struct accumulate_block {
void operator()(Iterator first, Iterator last, T& result)
{
result = std::accumulate(first, last, result);
}
};
template<typename Iterator,typename T>
T parallel_accumulate(Iterator first,Iterator last,T init)
template <typename Iterator, typename T>
T
parallel_accumulate(Iterator first, Iterator last, T init)
{
unsigned long const length=std::distance(first,last);
unsigned long const length = std::distance(first, last);
if(!length)
return init;
if (!length)
return init;
unsigned long const min_per_thread=25;
unsigned long const max_threads=
(length+min_per_thread-1)/min_per_thread;
unsigned long const min_per_thread = 25;
unsigned long const max_threads =
(length + min_per_thread - 1) / min_per_thread;
unsigned long const hardware_threads=
std::thread::hardware_concurrency();
unsigned long const hardware_threads = std::thread::hardware_concurrency();
unsigned long const num_threads=
std::min(hardware_threads!=0?hardware_threads:2,max_threads);
unsigned long const num_threads =
std::min(hardware_threads != 0 ? hardware_threads : 2, max_threads);
unsigned long const block_size=length/num_threads;
unsigned long const block_size = length / num_threads;
std::vector<T> results(num_threads);
std::vector<std::thread> threads(num_threads-1);
std::vector<T> results(num_threads);
std::vector<std::thread> threads(num_threads - 1);
Iterator block_start=first;
for(unsigned long i=0;i<(num_threads-1);++i)
{
Iterator block_end=block_start;
std::advance(block_end,block_size);
threads[i]=std::thread(
accumulate_block<Iterator,T>(),
block_start,block_end,std::ref(results[i]));
block_start=block_end;
}
accumulate_block<Iterator,T>()(block_start,last,results[num_threads-1]);
std::for_each(threads.begin(),threads.end(),
std::mem_fn(&std::thread::join));
Iterator block_start = first;
for (unsigned long i = 0; i < (num_threads - 1); ++i) {
Iterator block_end = block_start;
std::advance(block_end, block_size);
threads[i] = std::thread(accumulate_block<Iterator, T>(),
block_start,
block_end,
std::ref(results[i]));
block_start = block_end;
}
accumulate_block<Iterator, T>()(block_start, last, results[num_threads - 1]);
return std::accumulate(results.begin(),results.end(),init);
std::for_each(
threads.begin(), threads.end(), std::mem_fn(&std::thread::join));
return std::accumulate(results.begin(), results.end(), init);
}
int main()
int
main()
{
std::vector<int> vi;
for(int i=0;i<10;++i)
{
vi.push_back(10);
}
int sum=parallel_accumulate(vi.begin(),vi.end(),5);
std::cout<<"sum="<<sum<<std::endl;
std::vector<int> vi;
for (int i = 0; i < 10; ++i) {
vi.push_back(10);
}
int sum = parallel_accumulate(vi.begin(), vi.end(), 5);
std::cout << "sum=" << sum << std::endl;
}

View File

@@ -1,26 +1,30 @@
#include <algorithm>
#include <list>
#include <mutex>
#include <algorithm>
std::list<int> some_list;
std::mutex some_mutex;
void add_to_list(int new_value)
void
add_to_list(int new_value)
{
std::lock_guard<std::mutex> guard(some_mutex);
some_list.push_back(new_value);
std::lock_guard<std::mutex> guard(some_mutex);
some_list.push_back(new_value);
}
bool list_contains(int value_to_find)
bool
list_contains(int value_to_find)
{
std::lock_guard<std::mutex> guard(some_mutex);
return std::find(some_list.begin(),some_list.end(),value_to_find)
!= some_list.end();
std::lock_guard<std::mutex> guard(some_mutex);
return std::find(some_list.begin(), some_list.end(), value_to_find) !=
some_list.end();
}
#include <iostream>
int main()
int
main()
{
add_to_list(42);
std::cout<<"contains(1)="<<list_contains(1)<<", contains(42)="<<list_contains(42)<<std::endl;
add_to_list(42);
std::cout << "contains(1)=" << list_contains(1)
<< ", contains(42)=" << list_contains(42) << std::endl;
}

View File

@@ -1,27 +1,29 @@
#include <mutex>
class Y
{
class Y {
private:
int some_detail;
mutable std::mutex m;
int some_detail;
mutable std::mutex m;
int get_detail() const
{
std::lock_guard<std::mutex> lock_a(m);
return some_detail;
}
int get_detail() const
{
std::lock_guard<std::mutex> lock_a(m);
return some_detail;
}
public:
Y(int sd):some_detail(sd){}
Y(int sd) : some_detail(sd) {}
friend bool operator==(Y const& lhs, Y const& rhs)
{
if(&lhs==&rhs)
return true;
int const lhs_value=lhs.get_detail();
int const rhs_value=rhs.get_detail();
return lhs_value==rhs_value;
}
friend bool operator==(Y const& lhs, Y const& rhs)
{
if (&lhs == &rhs)
return true;
int const lhs_value = lhs.get_detail();
int const rhs_value = rhs.get_detail();
return lhs_value == rhs_value;
}
};
int main()
{}
int
main()
{
}

View File

@@ -1,28 +1,25 @@
#include <memory>
#include <mutex>
struct some_resource
{
void do_something()
{}
struct some_resource {
void do_something() {}
};
std::shared_ptr<some_resource> resource_ptr;
std::mutex resource_mutex;
void foo()
void
foo()
{
std::unique_lock<std::mutex> lk(resource_mutex);
if(!resource_ptr)
{
resource_ptr.reset(new some_resource);
}
lk.unlock();
resource_ptr->do_something();
std::unique_lock<std::mutex> lk(resource_mutex);
if (!resource_ptr) {
resource_ptr.reset(new some_resource);
}
lk.unlock();
resource_ptr->do_something();
}
int main()
int
main()
{
foo();
foo();
}

View File

@@ -1,56 +1,49 @@
#include <mutex>
struct connection_info
{};
struct data_packet
{};
struct connection_handle
{
void send_data(data_packet const&)
{}
data_packet receive_data()
{
return data_packet();
}
struct connection_info {
};
struct remote_connection_manager
{
connection_handle open(connection_info const&)
{
return connection_handle();
}
struct data_packet {
};
struct connection_handle {
void send_data(data_packet const&) {}
data_packet receive_data() { return data_packet(); }
};
struct remote_connection_manager {
connection_handle open(connection_info const&) { return connection_handle(); }
} connection_manager;
class X
{
class X {
private:
connection_info connection_details;
connection_handle connection;
std::once_flag connection_init_flag;
connection_info connection_details;
connection_handle connection;
std::once_flag connection_init_flag;
void open_connection()
{
connection = connection_manager.open(connection_details);
}
void open_connection()
{
connection=connection_manager.open(connection_details);
}
public:
X(connection_info const& connection_details_):
connection_details(connection_details_)
{}
void send_data(data_packet const& data)
{
std::call_once(connection_init_flag,&X::open_connection,this);
connection.send_data(data);
}
data_packet receive_data()
{
std::call_once(connection_init_flag,&X::open_connection,this);
return connection.receive_data();
}
X(connection_info const& connection_details_)
: connection_details(connection_details_)
{
}
void send_data(data_packet const& data)
{
std::call_once(connection_init_flag, &X::open_connection, this);
connection.send_data(data);
}
data_packet receive_data()
{
std::call_once(connection_init_flag, &X::open_connection, this);
return connection.receive_data();
}
};
int main()
{}
int
main()
{
}

View File

@@ -1,30 +1,32 @@
#include <map>
#include <string>
#include <mutex>
#include <boost/thread/shared_mutex.hpp>
#include <map>
#include <mutex>
#include <string>
class dns_entry
{};
class dns_cache
{
std::map<std::string,dns_entry> entries;
boost::shared_mutex entry_mutex;
public:
dns_entry find_entry(std::string const& domain)
{
boost::shared_lock<boost::shared_mutex> lk(entry_mutex);
std::map<std::string,dns_entry>::const_iterator const it=
entries.find(domain);
return (it==entries.end())?dns_entry():it->second;
}
void update_or_add_entry(std::string const& domain,
dns_entry const& dns_details)
{
std::lock_guard<boost::shared_mutex> lk(entry_mutex);
entries[domain]=dns_details;
}
class dns_entry {
};
int main()
{}
class dns_cache {
std::map<std::string, dns_entry> entries;
boost::shared_mutex entry_mutex;
public:
dns_entry find_entry(std::string const& domain)
{
boost::shared_lock<boost::shared_mutex> lk(entry_mutex);
std::map<std::string, dns_entry>::const_iterator const it =
entries.find(domain);
return (it == entries.end()) ? dns_entry() : it->second;
}
void update_or_add_entry(std::string const& domain,
dns_entry const& dns_details)
{
std::lock_guard<boost::shared_mutex> lk(entry_mutex);
entries[domain] = dns_details;
}
};
int
main()
{
}

View File

@@ -1,44 +1,46 @@
#include <mutex>
class some_data
{
int a;
std::string b;
class some_data {
int a;
std::string b;
public:
void do_something()
{}
void do_something() {}
};
class data_wrapper
{
class data_wrapper {
private:
some_data data;
std::mutex m;
some_data data;
std::mutex m;
public:
template<typename Function>
void process_data(Function func)
{
std::lock_guard<std::mutex> l(m);
func(data);
}
template <typename Function>
void process_data(Function func)
{
std::lock_guard<std::mutex> l(m);
func(data);
}
};
some_data* unprotected;
void malicious_function(some_data& protected_data)
void
malicious_function(some_data& protected_data)
{
unprotected=&protected_data;
unprotected = &protected_data;
}
data_wrapper x;
void foo()
void
foo()
{
x.process_data(malicious_function);
unprotected->do_something();
x.process_data(malicious_function);
unprotected->do_something();
}
int main()
int
main()
{
foo();
foo();
}

View File

@@ -1,24 +1,29 @@
#include <deque>
template<typename T,typename Container=std::deque<T> >
class stack
{
template <typename T, typename Container = std::deque<T>>
class stack {
public:
explicit stack(const Container&);
explicit stack(Container&& = Container());
template <class Alloc> explicit stack(const Alloc&);
template <class Alloc> stack(const Container&, const Alloc&);
template <class Alloc> stack(Container&&, const Alloc&);
template <class Alloc> stack(stack&&, const Alloc&);
explicit stack(const Container&);
explicit stack(Container&& = Container());
template <class Alloc>
explicit stack(const Alloc&);
template <class Alloc>
stack(const Container&, const Alloc&);
template <class Alloc>
stack(Container&&, const Alloc&);
template <class Alloc>
stack(stack&&, const Alloc&);
bool empty() const;
size_t size() const;
T& top();
T const& top() const;
void push(T const&);
void push(T&&);
void pop();
void swap(stack&&);
bool empty() const;
size_t size() const;
T& top();
T const& top() const;
void push(T const&);
void push(T&&);
void pop();
void swap(stack&&);
};
int main()
{}
int
main()
{
}

View File

@@ -1,24 +1,24 @@
#include <exception>
#include <memory>
struct empty_stack: std::exception
{
const char* what() const throw();
struct empty_stack : std::exception {
const char* what() const throw();
};
template<typename T>
class threadsafe_stack
{
template <typename T>
class threadsafe_stack {
public:
threadsafe_stack();
threadsafe_stack(const threadsafe_stack&);
threadsafe_stack& operator=(const threadsafe_stack&) = delete;
threadsafe_stack();
threadsafe_stack(const threadsafe_stack&);
threadsafe_stack& operator=(const threadsafe_stack&) = delete;
void push(T new_value);
std::shared_ptr<T> pop();
void pop(T& value);
bool empty() const;
void push(T new_value);
std::shared_ptr<T> pop();
void pop(T& value);
bool empty() const;
};
int main()
{}
int
main()
{
}

View File

@@ -1,68 +1,64 @@
#include <exception>
#include <stack>
#include <mutex>
#include <memory>
#include <mutex>
#include <stack>
struct empty_stack: std::exception
{
const char* what() const throw()
{
return "empty stack";
}
struct empty_stack : std::exception {
const char* what() const throw() { return "empty stack"; }
};
template<typename T>
class threadsafe_stack
{
template <typename T>
class threadsafe_stack {
private:
std::stack<T> data;
mutable std::mutex m;
public:
threadsafe_stack(){}
threadsafe_stack(const threadsafe_stack& other)
{
std::lock_guard<std::mutex> lock(other.m);
data=other.data;
}
threadsafe_stack& operator=(const threadsafe_stack&) = delete;
std::stack<T> data;
mutable std::mutex m;
void push(T new_value)
{
std::lock_guard<std::mutex> lock(m);
data.push(new_value);
}
std::shared_ptr<T> pop()
{
std::lock_guard<std::mutex> lock(m);
if(data.empty()) throw empty_stack();
std::shared_ptr<T> const res(std::make_shared<T>(data.top()));
data.pop();
return res;
}
void pop(T& value)
{
std::lock_guard<std::mutex> lock(m);
if(data.empty()) throw empty_stack();
value=data.top();
data.pop();
}
bool empty() const
{
std::lock_guard<std::mutex> lock(m);
return data.empty();
}
public:
threadsafe_stack() {}
threadsafe_stack(const threadsafe_stack& other)
{
std::lock_guard<std::mutex> lock(other.m);
data = other.data;
}
threadsafe_stack& operator=(const threadsafe_stack&) = delete;
void push(T new_value)
{
std::lock_guard<std::mutex> lock(m);
data.push(new_value);
}
std::shared_ptr<T> pop()
{
std::lock_guard<std::mutex> lock(m);
if (data.empty())
throw empty_stack();
std::shared_ptr<T> const res(std::make_shared<T>(data.top()));
data.pop();
return res;
}
void pop(T& value)
{
std::lock_guard<std::mutex> lock(m);
if (data.empty())
throw empty_stack();
value = data.top();
data.pop();
}
bool empty() const
{
std::lock_guard<std::mutex> lock(m);
return data.empty();
}
};
int main()
int
main()
{
threadsafe_stack<int> si;
si.push(5);
si.pop();
if(!si.empty())
{
int x;
si.pop(x);
}
threadsafe_stack<int> si;
si.push(5);
si.pop();
if (!si.empty()) {
int x;
si.pop(x);
}
}

View File

@@ -1,29 +1,33 @@
#include <mutex>
class some_big_object
{};
void swap(some_big_object& lhs,some_big_object& rhs)
{}
class X
{
private:
some_big_object some_detail;
mutable std::mutex m;
public:
X(some_big_object const& sd):some_detail(sd){}
friend void swap(X& lhs, X& rhs)
{
if(&lhs==&rhs)
return;
std::lock(lhs.m,rhs.m);
std::lock_guard<std::mutex> lock_a(lhs.m,std::adopt_lock);
std::lock_guard<std::mutex> lock_b(rhs.m,std::adopt_lock);
swap(lhs.some_detail,rhs.some_detail);
}
class some_big_object {
};
int main()
{}
void
swap(some_big_object& lhs, some_big_object& rhs)
{
}
class X {
private:
some_big_object some_detail;
mutable std::mutex m;
public:
X(some_big_object const& sd) : some_detail(sd) {}
friend void swap(X& lhs, X& rhs)
{
if (&lhs == &rhs)
return;
std::lock(lhs.m, rhs.m);
std::lock_guard<std::mutex> lock_a(lhs.m, std::adopt_lock);
std::lock_guard<std::mutex> lock_b(rhs.m, std::adopt_lock);
swap(lhs.some_detail, rhs.some_detail);
}
};
int
main()
{
}

View File

@@ -1,64 +1,68 @@
#include <mutex>
class hierarchical_mutex
{
class hierarchical_mutex {
public:
explicit hierarchical_mutex(unsigned level)
{}
void lock()
{}
void unlock()
{}
};
explicit hierarchical_mutex(unsigned level) {}
void lock() {}
void unlock() {}
};
hierarchical_mutex high_level_mutex(10000);
hierarchical_mutex low_level_mutex(5000);
int do_low_level_stuff()
int
do_low_level_stuff()
{
return 42;
return 42;
}
int low_level_func()
int
low_level_func()
{
std::lock_guard<hierarchical_mutex> lk(low_level_mutex);
return do_low_level_stuff();
std::lock_guard<hierarchical_mutex> lk(low_level_mutex);
return do_low_level_stuff();
}
void high_level_stuff(int some_param)
{}
void high_level_func()
void
high_level_stuff(int some_param)
{
std::lock_guard<hierarchical_mutex> lk(high_level_mutex);
high_level_stuff(low_level_func());
}
void thread_a()
void
high_level_func()
{
high_level_func();
std::lock_guard<hierarchical_mutex> lk(high_level_mutex);
high_level_stuff(low_level_func());
}
void
thread_a()
{
high_level_func();
}
hierarchical_mutex other_mutex(100);
void do_other_stuff()
{}
void other_stuff()
void
do_other_stuff()
{
high_level_func();
do_other_stuff();
}
void thread_b()
void
other_stuff()
{
std::lock_guard<hierarchical_mutex> lk(other_mutex);
other_stuff();
high_level_func();
do_other_stuff();
}
int main()
{}
void
thread_b()
{
std::lock_guard<hierarchical_mutex> lk(other_mutex);
other_stuff();
}
int
main()
{
}

View File

@@ -1,56 +1,55 @@
#include <mutex>
#include <stdexcept>
class hierarchical_mutex
{
std::mutex internal_mutex;
unsigned long const hierarchy_value;
unsigned long previous_hierarchy_value;
static thread_local unsigned long this_thread_hierarchy_value;
class hierarchical_mutex {
std::mutex internal_mutex;
unsigned long const hierarchy_value;
unsigned long previous_hierarchy_value;
static thread_local unsigned long this_thread_hierarchy_value;
void check_for_hierarchy_violation()
{
if(this_thread_hierarchy_value <= hierarchy_value)
{
throw std::logic_error("mutex hierarchy violated");
}
}
void update_hierarchy_value()
{
previous_hierarchy_value=this_thread_hierarchy_value;
this_thread_hierarchy_value=hierarchy_value;
void check_for_hierarchy_violation()
{
if (this_thread_hierarchy_value <= hierarchy_value) {
throw std::logic_error("mutex hierarchy violated");
}
}
void update_hierarchy_value()
{
previous_hierarchy_value = this_thread_hierarchy_value;
this_thread_hierarchy_value = hierarchy_value;
}
public:
explicit hierarchical_mutex(unsigned long value):
hierarchy_value(value),
previous_hierarchy_value(0)
{}
void lock()
{
check_for_hierarchy_violation();
internal_mutex.lock();
update_hierarchy_value();
}
void unlock()
{
this_thread_hierarchy_value=previous_hierarchy_value;
internal_mutex.unlock();
}
bool try_lock()
{
check_for_hierarchy_violation();
if(!internal_mutex.try_lock())
return false;
update_hierarchy_value();
return true;
}
explicit hierarchical_mutex(unsigned long value)
: hierarchy_value(value), previous_hierarchy_value(0)
{
}
void lock()
{
check_for_hierarchy_violation();
internal_mutex.lock();
update_hierarchy_value();
}
void unlock()
{
this_thread_hierarchy_value = previous_hierarchy_value;
internal_mutex.unlock();
}
bool try_lock()
{
check_for_hierarchy_violation();
if (!internal_mutex.try_lock())
return false;
update_hierarchy_value();
return true;
}
};
thread_local unsigned long
hierarchical_mutex::this_thread_hierarchy_value(ULONG_MAX);
thread_local unsigned long hierarchical_mutex::this_thread_hierarchy_value(
ULONG_MAX);
int main()
int
main()
{
hierarchical_mutex m1(42);
hierarchical_mutex m2(2000);
hierarchical_mutex m1(42);
hierarchical_mutex m2(2000);
}

View File

@@ -1,29 +1,33 @@
#include <mutex>
class some_big_object
{};
void swap(some_big_object& lhs,some_big_object& rhs)
{}
class X
{
private:
some_big_object some_detail;
mutable std::mutex m;
public:
X(some_big_object const& sd):some_detail(sd){}
friend void swap(X& lhs, X& rhs)
{
if(&lhs==&rhs)
return;
std::unique_lock<std::mutex> lock_a(lhs.m,std::defer_lock);
std::unique_lock<std::mutex> lock_b(rhs.m,std::defer_lock);
std::lock(lock_a,lock_b);
swap(lhs.some_detail,rhs.some_detail);
}
class some_big_object {
};
int main()
{}
void
swap(some_big_object& lhs, some_big_object& rhs)
{
}
class X {
private:
some_big_object some_detail;
mutable std::mutex m;
public:
X(some_big_object const& sd) : some_detail(sd) {}
friend void swap(X& lhs, X& rhs)
{
if (&lhs == &rhs)
return;
std::unique_lock<std::mutex> lock_a(lhs.m, std::defer_lock);
std::unique_lock<std::mutex> lock_b(rhs.m, std::defer_lock);
std::lock(lock_a, lock_b);
swap(lhs.some_detail, rhs.some_detail);
}
};
int
main()
{
}

View File

@@ -1,64 +1,70 @@
#include <mutex>
#include <condition_variable>
#include <thread>
#include <mutex>
#include <queue>
#include <thread>
bool more_data_to_prepare()
bool
more_data_to_prepare()
{
return false;
return false;
}
struct data_chunk
{};
struct data_chunk {
};
data_chunk prepare_data()
data_chunk
prepare_data()
{
return data_chunk();
return data_chunk();
}
void process(data_chunk&)
{}
bool is_last_chunk(data_chunk&)
void
process(data_chunk&)
{
return true;
}
bool
is_last_chunk(data_chunk&)
{
return true;
}
std::mutex mut;
std::queue<data_chunk> data_queue;
std::condition_variable data_cond;
void data_preparation_thread()
void
data_preparation_thread()
{
while(more_data_to_prepare())
{
data_chunk const data=prepare_data();
std::lock_guard<std::mutex> lk(mut);
data_queue.push(data);
data_cond.notify_one();
}
while (more_data_to_prepare()) {
data_chunk const data = prepare_data();
std::lock_guard<std::mutex> lk(mut);
data_queue.push(data);
data_cond.notify_one();
}
}
void data_processing_thread()
void
data_processing_thread()
{
while(true)
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk,[]{return !data_queue.empty();});
data_chunk data=data_queue.front();
data_queue.pop();
lk.unlock();
process(data);
if(is_last_chunk(data))
break;
}
while (true) {
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk, [] { return !data_queue.empty(); });
data_chunk data = data_queue.front();
data_queue.pop();
lk.unlock();
process(data);
if (is_last_chunk(data))
break;
}
}
int main()
int
main()
{
std::thread t1(data_preparation_thread);
std::thread t2(data_processing_thread);
t1.join();
t2.join();
std::thread t1(data_preparation_thread);
std::thread t2(data_processing_thread);
t1.join();
t2.join();
}

View File

@@ -1,27 +1,22 @@
#include <future>
void process_connections(connection_set& connections)
void
process_connections(connection_set& connections)
{
while(!done(connections))
{
for(connection_iterator
connection=connections.begin(),end=connections.end();
connection!=end;
++connection)
{
if(connection->has_incoming_data())
{
data_packet data=connection->incoming();
std::promise<payload_type>& p=
connection->get_promise(data.id);
p.set_value(data.payload);
}
if(connection->has_outgoing_data())
{
outgoing_packet data=
connection->top_of_outgoing_queue();
connection->send(data.payload);
data.promise.set_value(true);
}
}
while (!done(connections)) {
for (connection_iterator connection = connections.begin(),
end = connections.end();
connection != end;
++connection) {
if (connection->has_incoming_data()) {
data_packet data = connection->incoming();
std::promise<payload_type>& p = connection->get_promise(data.id);
p.set_value(data.payload);
}
if (connection->has_outgoing_data()) {
outgoing_packet data = connection->top_of_outgoing_queue();
connection->send(data.payload);
data.promise.set_value(true);
}
}
}
}

View File

@@ -1,18 +1,18 @@
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <chrono>
std::condition_variable cv;
bool done;
std::mutex m;
bool wait_loop()
bool
wait_loop()
{
auto const timeout= std::chrono::steady_clock::now()+
std::chrono::milliseconds(500);
std::unique_lock<std::mutex> lk(m);
while(!done)
{
if(cv.wait_until(lk,timeout)==std::cv_status::timeout)
break;
}
return done;
auto const timeout =
std::chrono::steady_clock::now() + std::chrono::milliseconds(500);
std::unique_lock<std::mutex> lk(m);
while (!done) {
if (cv.wait_until(lk, timeout) == std::cv_status::timeout)
break;
}
return done;
}

View File

@@ -1,24 +1,21 @@
template<typename T>
std::list<T> sequential_quick_sort(std::list<T> input)
template <typename T>
std::list<T>
sequential_quick_sort(std::list<T> input)
{
if(input.empty())
{
return input;
}
std::list<T> result;
result.splice(result.begin(),input,input.begin());
T const& pivot=*result.begin();
auto divide_point=std::partition(input.begin(),input.end(),
[&](T const& t){return t<pivot;});
std::list<T> lower_part;
lower_part.splice(lower_part.end(),input,input.begin(),
divide_point);
auto new_lower(
sequential_quick_sort(std::move(lower_part)));
auto new_higher(
sequential_quick_sort(std::move(input)));
result.splice(result.end(),new_higher);
Using synchronization of operations to simplify code
result.splice(result.begin(),new_lower);
return result;
if (input.empty()) {
return input;
}
std::list<T> result;
result.splice(result.begin(), input, input.begin());
T const& pivot = *result.begin();
auto divide_point = std::partition(
input.begin(), input.end(), [&](T const& t) { return t < pivot; });
std::list<T> lower_part;
lower_part.splice(lower_part.end(), input, input.begin(), divide_point);
auto new_lower(sequential_quick_sort(std::move(lower_part)));
auto new_higher(sequential_quick_sort(std::move(input)));
result.splice(result.end(), new_higher);
Using synchronization of operations to simplify code result.splice(
result.begin(), new_lower);
return result;
}

View File

@@ -1,23 +1,21 @@
template<typename T>
std::list<T> parallel_quick_sort(std::list<T> input)
template <typename T>
std::list<T>
parallel_quick_sort(std::list<T> input)
{
if(input.empty())
{
return input;
}
std::list<T> result;
result.splice(result.begin(),input,input.begin());
T const& pivot=*result.begin();
auto divide_point=std::partition(input.begin(),input.end(),
[&](T const& t){return t<pivot;});
std::list<T> lower_part;
lower_part.splice(lower_part.end(),input,input.begin(),
divide_point);
std::future<std::list<T> > new_lower(
std::async(&parallel_quick_sort<T>,std::move(lower_part)));
auto new_higher(
parallel_quick_sort(std::move(input)));
result.splice(result.end(),new_higher);
result.splice(result.begin(),new_lower.get());
return result;
if (input.empty()) {
return input;
}
std::list<T> result;
result.splice(result.begin(), input, input.begin());
T const& pivot = *result.begin();
auto divide_point = std::partition(
input.begin(), input.end(), [&](T const& t) { return t < pivot; });
std::list<T> lower_part;
lower_part.splice(lower_part.end(), input, input.begin(), divide_point);
std::future<std::list<T>> new_lower(
std::async(&parallel_quick_sort<T>, std::move(lower_part)));
auto new_higher(parallel_quick_sort(std::move(input)));
result.splice(result.end(), new_higher);
result.splice(result.begin(), new_lower.get());
return result;
}

View File

@@ -1,12 +1,11 @@
template<typename F,typename A>
template <typename F, typename A>
std::future<std::result_of<F(A&&)>::type>
spawn_task(F&& f,A&& a)
spawn_task(F&& f, A&& a)
{
typedef std::result_of<F(A&&)>::type result_type;
std::packaged_task<result_type(A&&)>
task(std::move(f));
std::future<result_type> res(task.get_future());
std::thread t(std::move(task),std::move(a));
t.detach();
return res;
typedef std::result_of<F(A &&)>::type result_type;
std::packaged_task<result_type(A &&)> task(std::move(f));
std::future<result_type> res(task.get_future());
std::thread t(std::move(task), std::move(a));
t.detach();
return res;
}

View File

@@ -1,43 +1,35 @@
struct card_inserted
{
std::string account;
struct card_inserted {
std::string account;
};
class atm
{
messaging::receiver incoming;
messaging::sender bank;
messaging::sender interface_hardware;
void (atm::*state)();
std::string account;
std::string pin;
void waiting_for_card()
{
interface_hardware.send(display_enter_card());
incoming.wait()
.handle<card_inserted>(
[&](card_inserted const& msg)
{
account=msg.account;
pin="";
interface_hardware.send(display_enter_pin());
state=&atm::getting_pin;
}
);
}
void getting_pin();
class atm {
messaging::receiver incoming;
messaging::sender bank;
messaging::sender interface_hardware;
void (atm::*state)();
std::string account;
std::string pin;
void waiting_for_card()
{
interface_hardware.send(display_enter_card());
incoming.wait().handle<card_inserted>([&](card_inserted const& msg) {
account = msg.account;
pin = "";
interface_hardware.send(display_enter_pin());
state = &atm::getting_pin;
});
}
void getting_pin();
public:
void run()
{
state=&atm::waiting_for_card;
try
{
for(;;)
{
(this->*state)();
}
}
catch(messaging::close_queue const&)
{
}
void run()
{
state = &atm::waiting_for_card;
try {
for (;;) {
(this->*state)();
}
}
catch (messaging::close_queue const&) {
}
}
};

View File

@@ -1,31 +1,20 @@
void atm::getting_pin()
void
atm::getting_pin()
{
incoming.wait()
.handle<digit_pressed>(
[&](digit_pressed const& msg)
{
unsigned const pin_length=4;
pin+=msg.digit;
if(pin.length()==pin_length)
{
bank.send(verify_pin(account,pin,incoming));
state=&atm::verifying_pin;
}
}
)
.handle<clear_last_pressed>(
[&](clear_last_pressed const& msg)
{
if(!pin.empty())
{
pin.resize(pin.length()-1);
}
}
)
.handle<cancel_pressed>(
[&](cancel_pressed const& msg)
{
state=&atm::done_processing;
}
);
incoming.wait()
.handle<digit_pressed>([&](digit_pressed const& msg) {
unsigned const pin_length = 4;
pin += msg.digit;
if (pin.length() == pin_length) {
bank.send(verify_pin(account, pin, incoming));
state = &atm::verifying_pin;
}
})
.handle<clear_last_pressed>([&](clear_last_pressed const& msg) {
if (!pin.empty()) {
pin.resize(pin.length() - 1);
}
})
.handle<cancel_pressed>(
[&](cancel_pressed const& msg) { state = &atm::done_processing; });
}

View File

@@ -1,30 +1,36 @@
template <class T, class Container = std::deque<T> >
template <class T, class Container = std::deque<T>>
class queue {
public:
explicit queue(const Container&);
explicit queue(Container&& = Container());
queue(queue&& q);
explicit queue(const Container&);
explicit queue(Container&& = Container());
queue(queue&& q);
template <class Alloc> explicit queue(const Alloc&);
template <class Alloc> queue(const Container&, const Alloc&);
template <class Alloc> queue(Container&&, const Alloc&);
template <class Alloc> queue(queue&&, const Alloc&);
template <class Alloc>
explicit queue(const Alloc&);
template <class Alloc>
queue(const Container&, const Alloc&);
template <class Alloc>
queue(Container&&, const Alloc&);
template <class Alloc>
queue(queue&&, const Alloc&);
queue& operator=(queue&& q);
void swap(queue&& q);
queue& operator=(queue&& q);
void swap(queue&& q);
bool empty() const;
size_type size() const;
bool empty() const;
size_type size() const;
T& front();
const T& front() const;
T& back();
const T& back() const;
T& front();
const T& front() const;
T& back();
const T& back() const;
void push(const T& x);
void push(T&& x);
void pop();
void push(const T& x);
void push(T&& x);
void pop();
};
int main()
{}
int
main()
{
}

View File

@@ -1,22 +1,23 @@
#include <memory>
template<typename T>
class threadsafe_queue
{
template <typename T>
class threadsafe_queue {
public:
threadsafe_queue();
threadsafe_queue(const threadsafe_queue&);
threadsafe_queue& operator=(const threadsafe_queue&) = delete;
threadsafe_queue();
threadsafe_queue(const threadsafe_queue&);
threadsafe_queue& operator=(const threadsafe_queue&) = delete;
void push(T new_value);
bool try_pop(T& value);
std::shared_ptr<T> try_pop();
void push(T new_value);
void wait_and_pop(T& value);
std::shared_ptr<T> wait_and_pop();
bool try_pop(T& value);
std::shared_ptr<T> try_pop();
bool empty() const;
void wait_and_pop(T& value);
std::shared_ptr<T> wait_and_pop();
bool empty() const;
};
int main()
{}
int
main()
{
}

View File

@@ -1,33 +1,32 @@
#include <mutex>
#include <condition_variable>
#include <mutex>
#include <queue>
template<typename T>
class threadsafe_queue
{
template <typename T>
class threadsafe_queue {
private:
std::mutex mut;
std::queue<T> data_queue;
std::condition_variable data_cond;
public:
void push(T new_value)
{
std::lock_guard<std::mutex> lk(mut);
data_queue.push(new_value);
data_cond.notify_one();
}
std::mutex mut;
std::queue<T> data_queue;
std::condition_variable data_cond;
void wait_and_pop(T& value)
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk,[this]{return !data_queue.empty();});
value=data_queue.front();
data_queue.pop();
}
public:
void push(T new_value)
{
std::lock_guard<std::mutex> lk(mut);
data_queue.push(new_value);
data_cond.notify_one();
}
void wait_and_pop(T& value)
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk, [this] { return !data_queue.empty(); });
value = data_queue.front();
data_queue.pop();
}
};
struct data_chunk
{};
struct data_chunk {
};
data_chunk prepare_data();
bool more_data_to_prepare();
@@ -36,23 +35,23 @@ bool is_last_chunk(data_chunk);
threadsafe_queue<data_chunk> data_queue;
void data_preparation_thread()
void
data_preparation_thread()
{
while(more_data_to_prepare())
{
data_chunk const data=prepare_data();
data_queue.push(data);
}
while (more_data_to_prepare()) {
data_chunk const data = prepare_data();
data_queue.push(data);
}
}
void data_processing_thread()
void
data_processing_thread()
{
while(true)
{
data_chunk data;
data_queue.wait_and_pop(data);
process(data);
if(is_last_chunk(data))
break;
}
while (true) {
data_chunk data;
data_queue.wait_and_pop(data);
process(data);
if (is_last_chunk(data))
break;
}
}

View File

@@ -1,73 +1,74 @@
#include <mutex>
#include <condition_variable>
#include <queue>
#include <memory>
#include <mutex>
#include <queue>
template<typename T>
class threadsafe_queue
{
template <typename T>
class threadsafe_queue {
private:
mutable std::mutex mut;
std::queue<T> data_queue;
std::condition_variable data_cond;
mutable std::mutex mut;
std::queue<T> data_queue;
std::condition_variable data_cond;
public:
threadsafe_queue()
{}
threadsafe_queue(threadsafe_queue const& other)
{
std::lock_guard<std::mutex> lk(other.mut);
data_queue=other.data_queue;
}
threadsafe_queue() {}
threadsafe_queue(threadsafe_queue const& other)
{
std::lock_guard<std::mutex> lk(other.mut);
data_queue = other.data_queue;
}
void push(T new_value)
{
std::lock_guard<std::mutex> lk(mut);
data_queue.push(new_value);
data_cond.notify_one();
}
void push(T new_value)
{
std::lock_guard<std::mutex> lk(mut);
data_queue.push(new_value);
data_cond.notify_one();
}
void wait_and_pop(T& value)
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk,[this]{return !data_queue.empty();});
value=data_queue.front();
data_queue.pop();
}
void wait_and_pop(T& value)
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk, [this] { return !data_queue.empty(); });
value = data_queue.front();
data_queue.pop();
}
std::shared_ptr<T> wait_and_pop()
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk,[this]{return !data_queue.empty();});
std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));
data_queue.pop();
return res;
}
std::shared_ptr<T> wait_and_pop()
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk, [this] { return !data_queue.empty(); });
std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));
data_queue.pop();
return res;
}
bool try_pop(T& value)
{
std::lock_guard<std::mutex> lk(mut);
if(data_queue.empty)
return false;
value=data_queue.front();
data_queue.pop();
}
bool try_pop(T& value)
{
std::lock_guard<std::mutex> lk(mut);
if (data_queue.empty)
return false;
value = data_queue.front();
data_queue.pop();
}
std::shared_ptr<T> try_pop()
{
std::lock_guard<std::mutex> lk(mut);
if(data_queue.empty())
return std::shared_ptr<T>();
std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));
data_queue.pop();
return res;
}
std::shared_ptr<T> try_pop()
{
std::lock_guard<std::mutex> lk(mut);
if (data_queue.empty())
return std::shared_ptr<T>();
std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));
data_queue.pop();
return res;
}
bool empty() const
{
std::lock_guard<std::mutex> lk(mut);
return data_queue.empty();
}
bool empty() const
{
std::lock_guard<std::mutex> lk(mut);
return data_queue.empty();
}
};
int main()
{}
int
main()
{
}

View File

@@ -1,16 +1,20 @@
#include <future>
#include <iostream>
int find_the_answer_to_ltuae()
int
find_the_answer_to_ltuae()
{
return 42;
return 42;
}
void do_other_stuff()
{}
int main()
void
do_other_stuff()
{
std::future<int> the_answer=std::async(find_the_answer_to_ltuae);
do_other_stuff();
std::cout<<"The answer is "<<the_answer.get()<<std::endl;
}
int
main()
{
std::future<int> the_answer = std::async(find_the_answer_to_ltuae);
do_other_stuff();
std::cout << "The answer is " << the_answer.get() << std::endl;
}

View File

@@ -1,34 +1,30 @@
#include <string>
#include <future>
#include <string>
struct X
{
void foo(int,std::string const&);
std::string bar(std::string const&);
struct X {
void foo(int, std::string const&);
std::string bar(std::string const&);
};
X x;
auto f1=std::async(&X::foo,&x,42,"hello");
auto f2=std::async(&X::bar,x,"goodbye");
auto f1 = std::async(&X::foo, &x, 42, "hello");
auto f2 = std::async(&X::bar, x, "goodbye");
struct Y
{
double operator()(double);
struct Y {
double operator()(double);
};
Y y;
auto f3=std::async(Y(),3.141);
auto f4=std::async(std::ref(y),2.718);
auto f3 = std::async(Y(), 3.141);
auto f4 = std::async(std::ref(y), 2.718);
X baz(X&);
auto f6=std::async(baz,std::ref(x));
class move_only
{
auto f6 = std::async(baz, std::ref(x));
class move_only {
public:
move_only();
move_only(move_only&&);
move_only(move_only const&) = delete;
move_only& operator=(move_only&&);
move_only& operator=(move_only const&) = delete;
void operator()();
move_only();
move_only(move_only&&);
move_only(move_only const&) = delete;
move_only& operator =(move_only&&);
move_only& operator=(move_only const&) = delete;
void operator()();
};
auto f5=std::async(move_only());
auto f5 = std::async(move_only());

View File

@@ -1,9 +1,8 @@
template<>
class packaged_task<std::string(std::vector<char>*,int)>
{
template <>
class packaged_task<std::string(std::vector<char>*, int)> {
public:
template<typename Callable>
explicit packaged_task(Callable&& f);
std::future<std::string> get_future();
void operator()(std::vector<char>*,int);
template <typename Callable>
explicit packaged_task(Callable&& f);
std::future<std::string> get_future();
void operator()(std::vector<char>*, int);
};

View File

@@ -1,40 +1,41 @@
#include <deque>
#include <mutex>
#include <future>
#include <mutex>
#include <thread>
#include <utility>
std::mutex m;
std::deque<std::packaged_task<void()> > tasks;
std::deque<std::packaged_task<void()>> tasks;
bool gui_shutdown_message_received();
void get_and_process_gui_message();
void gui_thread()
void
gui_thread()
{
while(!gui_shutdown_message_received())
while (!gui_shutdown_message_received()) {
get_and_process_gui_message();
std::packaged_task<void()> task;
{
get_and_process_gui_message();
std::packaged_task<void()> task;
{
std::lock_guard<std::mutex> lk(m);
if(tasks.empty())
continue;
task=std::move(tasks.front());
tasks.pop_front();
}
task();
std::lock_guard<std::mutex> lk(m);
if (tasks.empty())
continue;
task = std::move(tasks.front());
tasks.pop_front();
}
task();
}
}
std::thread gui_bg_thread(gui_thread);
template<typename Func>
std::future<void> post_task_for_gui_thread(Func f)
template <typename Func>
std::future<void>
post_task_for_gui_thread(Func f)
{
std::packaged_task<void()> task(f);
std::future<void> res=task.get_future();
std::lock_guard<std::mutex> lk(m);
tasks.push_back(std::move(task));
return res;
std::packaged_task<void()> task(f);
std::future<void> res = task.get_future();
std::lock_guard<std::mutex> lk(m);
tasks.push_back(std::move(task));
return res;
}

View File

@@ -1,16 +1,12 @@
class spinlock_mutex
{
std::atomic_flag flag;
class spinlock_mutex {
std::atomic_flag flag;
public:
spinlock_mutex():
flag(ATOMIC_FLAG_INIT)
{}
void lock()
{
while(flag.test_and_set(std::memory_order_acquire));
}
void unlock()
{
flag.clear(std::memory_order_release);
}
spinlock_mutex() : flag(ATOMIC_FLAG_INIT) {}
void lock()
{
while (flag.test_and_set(std::memory_order_acquire))
;
}
void unlock() { flag.clear(std::memory_order_release); }
};

View File

@@ -1,39 +1,40 @@
#include <assert.h>
#include <atomic>
#include <string>
#include <thread>
#include <atomic>
#include <assert.h>
struct X
{
int i;
std::string s;
struct X {
int i;
std::string s;
};
std::atomic<X*> p;
std::atomic<int> a;
void create_x()
void
create_x()
{
X* x=new X;
x->i=42;
x->s="hello";
a.store(99,std::memory_order_relaxed);
p.store(x,std::memory_order_release);
X* x = new X;
x->i = 42;
x->s = "hello";
a.store(99, std::memory_order_relaxed);
p.store(x, std::memory_order_release);
}
void use_x()
void
use_x()
{
X* x;
while(!(x=p.load(std::memory_order_consume)))
std::this_thread::sleep_for(std::chrono::microseconds(1));
assert(x->i==42);
assert(x->s=="hello");
assert(a.load(std::memory_order_relaxed)==99);
X* x;
while (!(x = p.load(std::memory_order_consume)))
std::this_thread::sleep_for(std::chrono::microseconds(1));
assert(x->i == 42);
assert(x->s == "hello");
assert(a.load(std::memory_order_relaxed) == 99);
}
int main()
int
main()
{
std::thread t1(create_x);
std::thread t2(use_x);
t1.join();
t2.join();
std::thread t1(create_x);
std::thread t2(use_x);
t1.join();
t2.join();
}

View File

@@ -4,38 +4,38 @@
std::vector<int> queue_data;
std::atomic<int> count;
void populate_queue()
void
populate_queue()
{
unsigned const number_of_items=20;
queue_data.clear();
for(unsigned i=0;i<number_of_items;++i)
{
queue_data.push_back(i);
}
count.store(number_of_items,std::memory_order_release);
unsigned const number_of_items = 20;
queue_data.clear();
for (unsigned i = 0; i < number_of_items; ++i) {
queue_data.push_back(i);
}
count.store(number_of_items, std::memory_order_release);
}
void consume_queue_items()
void
consume_queue_items()
{
while(true)
{
int item_index;
if((item_index=count.fetch_sub(1,std::memory_order_acquire))<=0)
{
wait_for_more_items();
continue;
}
process(queue_data[item_index-1]);
while (true) {
int item_index;
if ((item_index = count.fetch_sub(1, std::memory_order_acquire)) <= 0) {
wait_for_more_items();
continue;
}
process(queue_data[item_index - 1]);
}
}
int main()
int
main()
{
std::thread a(populate_queue);
std::thread b(consume_queue_items);
std::thread c(consume_queue_items);
a.join();
b.join();
c.join();
std::thread a(populate_queue);
std::thread b(consume_queue_items);
std::thread c(consume_queue_items);
a.join();
b.join();
c.join();
}

View File

@@ -1,33 +1,37 @@
#include <assert.h>
#include <atomic>
#include <thread>
#include <assert.h>
std::atomic<bool> x,y;
std::atomic<bool> x, y;
std::atomic<int> z;
void write_x_then_y()
void
write_x_then_y()
{
x.store(true,std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_release);
y.store(true,std::memory_order_relaxed);
x.store(true, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_release);
y.store(true, std::memory_order_relaxed);
}
void read_y_then_x()
void
read_y_then_x()
{
while(!y.load(std::memory_order_relaxed));
std::atomic_thread_fence(std::memory_order_acquire);
if(x.load(std::memory_order_relaxed))
++z;
while (!y.load(std::memory_order_relaxed))
;
std::atomic_thread_fence(std::memory_order_acquire);
if (x.load(std::memory_order_relaxed))
++z;
}
int main()
int
main()
{
x=false;
y=false;
z=0;
std::thread a(write_x_then_y);
std::thread b(read_y_then_x);
a.join();
b.join();
assert(z.load()!=0);
x = false;
y = false;
z = 0;
std::thread a(write_x_then_y);
std::thread b(read_y_then_x);
a.join();
b.join();
assert(z.load() != 0);
}

View File

@@ -1,34 +1,38 @@
#include <assert.h>
#include <atomic>
#include <thread>
#include <assert.h>
bool x=false;
bool x = false;
std::atomic<bool> y;
std::atomic<int> z;
void write_x_then_y()
void
write_x_then_y()
{
x=true;
std::atomic_thread_fence(std::memory_order_release);
y.store(true,std::memory_order_relaxed);
x = true;
std::atomic_thread_fence(std::memory_order_release);
y.store(true, std::memory_order_relaxed);
}
void read_y_then_x()
void
read_y_then_x()
{
while(!y.load(std::memory_order_relaxed));
std::atomic_thread_fence(std::memory_order_acquire);
if(x)
++z;
while (!y.load(std::memory_order_relaxed))
;
std::atomic_thread_fence(std::memory_order_acquire);
if (x)
++z;
}
int main()
int
main()
{
x=false;
y=false;
z=0;
std::thread a(write_x_then_y);
std::thread b(read_y_then_x);
a.join();
b.join();
assert(z.load()!=0);
x = false;
y = false;
z = 0;
std::thread a(write_x_then_y);
std::thread b(read_y_then_x);
a.join();
b.join();
assert(z.load() != 0);
}

View File

@@ -1,22 +1,23 @@
#include <vector>
#include <atomic>
#include <iostream>
#include <chrono>
#include <iostream>
#include <thread>
#include <vector>
std::vector<int> data;
std::atomic_bool data_ready(false);
void reader_thread()
void
reader_thread()
{
while(!data_ready.load())
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
std::cout<<"The answer="<<data[0]<<"\n";
while (!data_ready.load()) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
std::cout << "The answer=" << data[0] << "\n";
}
void writer_thread()
void
writer_thread()
{
data.push_back(42);
data_ready=true;
data.push_back(42);
data_ready = true;
}

View File

@@ -1,17 +1,20 @@
#include <iostream>
void foo(int a,int b)
void
foo(int a, int b)
{
std::cout<<a<<,<<b<<std::endl;
std::cout << a <<,<< b << std::endl;
}
int get_num()
int
get_num()
{
static int i=0;
return ++i;
static int i = 0;
return ++i;
}
int main()
int
main()
{
foo(get_num(),get_num());
foo(get_num(), get_num());
}

View File

@@ -1,46 +1,53 @@
#include <assert.h>
#include <atomic>
#include <thread>
#include <assert.h>
std::atomic<bool> x,y;
std::atomic<bool> x, y;
std::atomic<int> z;
void write_x()
void
write_x()
{
x.store(true,std::memory_order_seq_cst);
x.store(true, std::memory_order_seq_cst);
}
void write_y()
void
write_y()
{
y.store(true,std::memory_order_seq_cst);
y.store(true, std::memory_order_seq_cst);
}
void read_x_then_y()
void
read_x_then_y()
{
while(!x.load(std::memory_order_seq_cst));
if(y.load(std::memory_order_seq_cst))
++z;
while (!x.load(std::memory_order_seq_cst))
;
if (y.load(std::memory_order_seq_cst))
++z;
}
void read_y_then_x()
void
read_y_then_x()
{
while(!y.load(std::memory_order_seq_cst));
if(x.load(std::memory_order_seq_cst))
++z;
while (!y.load(std::memory_order_seq_cst))
;
if (x.load(std::memory_order_seq_cst))
++z;
}
int main()
int
main()
{
x=false;
y=false;
z=0;
std::thread a(write_x);
std::thread b(write_y);
std::thread c(read_x_then_y);
std::thread d(read_y_then_x);
a.join();
b.join();
c.join();
d.join();
assert(z.load()!=0);
x = false;
y = false;
z = 0;
std::thread a(write_x);
std::thread b(write_y);
std::thread c(read_x_then_y);
std::thread d(read_y_then_x);
a.join();
b.join();
c.join();
d.join();
assert(z.load() != 0);
}

View File

@@ -1,31 +1,35 @@
#include <assert.h>
#include <atomic>
#include <thread>
#include <assert.h>
std::atomic<bool> x,y;
std::atomic<bool> x, y;
std::atomic<int> z;
void write_x_then_y()
void
write_x_then_y()
{
x.store(true,std::memory_order_relaxed);
y.store(true,std::memory_order_relaxed);
x.store(true, std::memory_order_relaxed);
y.store(true, std::memory_order_relaxed);
}
void read_y_then_x()
void
read_y_then_x()
{
while(!y.load(std::memory_order_relaxed));
if(x.load(std::memory_order_relaxed))
++z;
while (!y.load(std::memory_order_relaxed))
;
if (x.load(std::memory_order_relaxed))
++z;
}
int main()
int
main()
{
x=false;
y=false;
z=0;
std::thread a(write_x_then_y);
std::thread b(read_y_then_x);
a.join();
b.join();
assert(z.load()!=0);
x = false;
y = false;
z = 0;
std::thread a(write_x_then_y);
std::thread b(read_y_then_x);
a.join();
b.join();
assert(z.load() != 0);
}

View File

@@ -1,74 +1,72 @@
#include <thread>
#include <atomic>
#include <iostream>
#include <thread>
std::atomic<int> x(0),y(0),z(0);
std::atomic<int> x(0), y(0), z(0);
std::atomic<bool> go(false);
unsigned const loop_count=10;
unsigned const loop_count = 10;
struct read_values
{
int x,y,z;
struct read_values {
int x, y, z;
};
read_values values1[loop_count];
read_values values2[loop_count];
read_values values3[loop_count];
read_values values4[loop_count];
read_values values5[loop_count];
void increment(std::atomic<int>* var_to_inc,read_values* values)
void
increment(std::atomic<int>* var_to_inc, read_values* values)
{
while(!go)
std::this_thread::yield();
for(unsigned i=0;i<loop_count;++i)
{
values[i].x=x.load(std::memory_order_relaxed);
values[i].y=y.load(std::memory_order_relaxed);
values[i].z=z.load(std::memory_order_relaxed);
var_to_inc->store(i+1,std::memory_order_relaxed);
std::this_thread::yield();
}
while (!go) std::this_thread::yield();
for (unsigned i = 0; i < loop_count; ++i) {
values[i].x = x.load(std::memory_order_relaxed);
values[i].y = y.load(std::memory_order_relaxed);
values[i].z = z.load(std::memory_order_relaxed);
var_to_inc->store(i + 1, std::memory_order_relaxed);
std::this_thread::yield();
}
}
void read_vals(read_values* values)
void
read_vals(read_values* values)
{
while(!go)
std::this_thread::yield();
for(unsigned i=0;i<loop_count;++i)
{
values[i].x=x.load(std::memory_order_relaxed);
values[i].y=y.load(std::memory_order_relaxed);
values[i].z=z.load(std::memory_order_relaxed);
std::this_thread::yield();
}
while (!go) std::this_thread::yield();
for (unsigned i = 0; i < loop_count; ++i) {
values[i].x = x.load(std::memory_order_relaxed);
values[i].y = y.load(std::memory_order_relaxed);
values[i].z = z.load(std::memory_order_relaxed);
std::this_thread::yield();
}
}
void print(read_values* v)
void
print(read_values* v)
{
for(unsigned i=0;i<loop_count;++i)
{
if(i)
std::cout<<",";
std::cout<<"("<<v[i].x<<","<<v[i].y<<","<<v[i].z<<")";
}
std::cout<<std::endl;
for (unsigned i = 0; i < loop_count; ++i) {
if (i)
std::cout << ",";
std::cout << "(" << v[i].x << "," << v[i].y << "," << v[i].z << ")";
}
std::cout << std::endl;
}
int main()
int
main()
{
std::thread t1(increment,&x,values1);
std::thread t2(increment,&y,values2);
std::thread t3(increment,&z,values3);
std::thread t4(read_vals,values4);
std::thread t5(read_vals,values5);
go=true;
t5.join();
t4.join();
t3.join();
t2.join();
t1.join();
print(values1);
print(values2);
print(values3);
print(values4);
print(values5);
std::thread t1(increment, &x, values1);
std::thread t2(increment, &y, values2);
std::thread t3(increment, &z, values3);
std::thread t4(read_vals, values4);
std::thread t5(read_vals, values5);
go = true;
t5.join();
t4.join();
t3.join();
t2.join();
t1.join();
print(values1);
print(values2);
print(values3);
print(values4);
print(values5);
}

View File

@@ -1,46 +1,53 @@
#include <assert.h>
#include <atomic>
#include <thread>
#include <assert.h>
std::atomic<bool> x,y;
std::atomic<bool> x, y;
std::atomic<int> z;
void write_x()
void
write_x()
{
x.store(true,std::memory_order_release);
x.store(true, std::memory_order_release);
}
void write_y()
void
write_y()
{
y.store(true,std::memory_order_release);
y.store(true, std::memory_order_release);
}
void read_x_then_y()
void
read_x_then_y()
{
while(!x.load(std::memory_order_acquire));
if(y.load(std::memory_order_acquire))
++z;
while (!x.load(std::memory_order_acquire))
;
if (y.load(std::memory_order_acquire))
++z;
}
void read_y_then_x()
void
read_y_then_x()
{
while(!y.load(std::memory_order_acquire));
if(x.load(std::memory_order_acquire))
++z;
while (!y.load(std::memory_order_acquire))
;
if (x.load(std::memory_order_acquire))
++z;
}
int main()
int
main()
{
x=false;
y=false;
z=0;
std::thread a(write_x);
std::thread b(write_y);
std::thread c(read_x_then_y);
std::thread d(read_y_then_x);
a.join();
b.join();
c.join();
d.join();
assert(z.load()!=0);
x = false;
y = false;
z = 0;
std::thread a(write_x);
std::thread b(write_y);
std::thread c(read_x_then_y);
std::thread d(read_y_then_x);
a.join();
b.join();
c.join();
d.join();
assert(z.load() != 0);
}

View File

@@ -1,31 +1,35 @@
#include <assert.h>
#include <atomic>
#include <thread>
#include <assert.h>
std::atomic<bool> x,y;
std::atomic<bool> x, y;
std::atomic<int> z;
void write_x_then_y()
void
write_x_then_y()
{
x.store(true,std::memory_order_relaxed);
y.store(true,std::memory_order_release);
x.store(true, std::memory_order_relaxed);
y.store(true, std::memory_order_release);
}
void read_y_then_x()
void
read_y_then_x()
{
while(!y.load(std::memory_order_acquire));
if(x.load(std::memory_order_relaxed))
++z;
while (!y.load(std::memory_order_acquire))
;
if (x.load(std::memory_order_relaxed))
++z;
}
int main()
int
main()
{
x=false;
y=false;
z=0;
std::thread a(write_x_then_y);
std::thread b(read_y_then_x);
a.join();
b.join();
assert(z.load()!=0);
x = false;
y = false;
z = 0;
std::thread a(write_x_then_y);
std::thread b(read_y_then_x);
a.join();
b.join();
assert(z.load() != 0);
}

View File

@@ -1,42 +1,48 @@
#include <assert.h>
#include <atomic>
#include <thread>
#include <assert.h>
std::atomic<int> data[5];
std::atomic<bool> sync1(false),sync2(false);
std::atomic<bool> sync1(false), sync2(false);
void thread_1()
void
thread_1()
{
data[0].store(42,std::memory_order_relaxed);
data[1].store(97,std::memory_order_relaxed);
data[2].store(17,std::memory_order_relaxed);
data[3].store(-141,std::memory_order_relaxed);
data[4].store(2003,std::memory_order_relaxed);
sync1.store(true,std::memory_order_release);
data[0].store(42, std::memory_order_relaxed);
data[1].store(97, std::memory_order_relaxed);
data[2].store(17, std::memory_order_relaxed);
data[3].store(-141, std::memory_order_relaxed);
data[4].store(2003, std::memory_order_relaxed);
sync1.store(true, std::memory_order_release);
}
void thread_2()
void
thread_2()
{
while(!sync1.load(std::memory_order_acquire));
sync2.store(std::memory_order_release);
while (!sync1.load(std::memory_order_acquire))
;
sync2.store(std::memory_order_release);
}
void thread_3()
void
thread_3()
{
while(!sync2.load(std::memory_order_acquire));
assert(data[0].load(std::memory_order_relaxed)==42);
assert(data[1].load(std::memory_order_relaxed)==97);
assert(data[2].load(std::memory_order_relaxed)==17);
assert(data[3].load(std::memory_order_relaxed)==-141);
assert(data[4].load(std::memory_order_relaxed)==2003);
while (!sync2.load(std::memory_order_acquire))
;
assert(data[0].load(std::memory_order_relaxed) == 42);
assert(data[1].load(std::memory_order_relaxed) == 97);
assert(data[2].load(std::memory_order_relaxed) == 17);
assert(data[3].load(std::memory_order_relaxed) == -141);
assert(data[4].load(std::memory_order_relaxed) == 2003);
}
int main()
int
main()
{
std::thread t1(thread_1);
std::thread t2(thread_2);
std::thread t3(thread_3);
t1.join();
t2.join();
t3.join();
std::thread t1(thread_1);
std::thread t2(thread_2);
std::thread t3(thread_3);
t1.join();
t2.join();
t3.join();
}

View File

@@ -1,56 +1,52 @@
#include <exception>
#include <stack>
#include <mutex>
#include <memory>
#include <mutex>
#include <stack>
struct empty_stack: std::exception
{
const char* what() const throw()
{
return "empty stack";
}
struct empty_stack : std::exception {
const char* what() const throw() { return "empty stack"; }
};
template<typename T>
class threadsafe_stack
{
template <typename T>
class threadsafe_stack {
private:
std::stack<T> data;
mutable std::mutex m;
std::stack<T> data;
mutable std::mutex m;
public:
threadsafe_stack(){}
threadsafe_stack(const threadsafe_stack& other)
{
std::lock_guard<std::mutex> lock(other.m);
data=other.data;
}
threadsafe_stack& operator=(const threadsafe_stack&) = delete;
threadsafe_stack() {}
threadsafe_stack(const threadsafe_stack& other)
{
std::lock_guard<std::mutex> lock(other.m);
data = other.data;
}
threadsafe_stack& operator=(const threadsafe_stack&) = delete;
void push(T new_value)
{
std::lock_guard<std::mutex> lock(m);
data.push(std::move(new_value));
}
std::shared_ptr<T> pop()
{
std::lock_guard<std::mutex> lock(m);
if(data.empty()) throw empty_stack();
std::shared_ptr<T> const res(
std::make_shared<T>(std::move(data.top())));
data.pop();
return res;
}
void pop(T& value)
{
std::lock_guard<std::mutex> lock(m);
if(data.empty()) throw empty_stack();
value=std::move(data.top());
data.pop();
}
bool empty() const
{
std::lock_guard<std::mutex> lock(m);
return data.empty();
}
void push(T new_value)
{
std::lock_guard<std::mutex> lock(m);
data.push(std::move(new_value));
}
std::shared_ptr<T> pop()
{
std::lock_guard<std::mutex> lock(m);
if (data.empty())
throw empty_stack();
std::shared_ptr<T> const res(std::make_shared<T>(std::move(data.top())));
data.pop();
return res;
}
void pop(T& value)
{
std::lock_guard<std::mutex> lock(m);
if (data.empty())
throw empty_stack();
value = std::move(data.top());
data.pop();
}
bool empty() const
{
std::lock_guard<std::mutex> lock(m);
return data.empty();
}
};

View File

@@ -1,44 +1,41 @@
template<typename T>
class threadsafe_queue
{
template <typename T>
class threadsafe_queue {
private:
std::unique_ptr<node> try_pop_head()
{
std::lock_guard<std::mutex> head_lock(head_mutex);
if(head.get()==get_tail())
{
return std::unique_ptr<node>();
}
return pop_head();
std::unique_ptr<node> try_pop_head()
{
std::lock_guard<std::mutex> head_lock(head_mutex);
if (head.get() == get_tail()) {
return std::unique_ptr<node>();
}
return pop_head();
}
std::unique_ptr<node> try_pop_head(T& value)
{
std::lock_guard<std::mutex> head_lock(head_mutex);
if(head.get()==get_tail())
{
return std::unique_ptr<node>();
}
value=std::move(*head->data);
return pop_head();
std::unique_ptr<node> try_pop_head(T& value)
{
std::lock_guard<std::mutex> head_lock(head_mutex);
if (head.get() == get_tail()) {
return std::unique_ptr<node>();
}
value = std::move(*head->data);
return pop_head();
}
public:
std::shared_ptr<T> try_pop()
{
std::unique_ptr<node> const old_head=try_pop_head();
return old_head?old_head->data:std::shared_ptr<T>();
}
std::shared_ptr<T> try_pop()
{
std::unique_ptr<node> const old_head = try_pop_head();
return old_head ? old_head->data : std::shared_ptr<T>();
}
bool try_pop(T& value)
{
std::unique_ptr<node> const old_head=try_pop_head(value);
return old_head;
}
bool try_pop(T& value)
{
std::unique_ptr<node> const old_head = try_pop_head(value);
return old_head;
}
void empty()
{
std::lock_guard<std::mutex> head_lock(head_mutex);
return (head==get_tail());
}
void empty()
{
std::lock_guard<std::mutex> head_lock(head_mutex);
return (head == get_tail());
}
};

View File

@@ -1,108 +1,97 @@
#include <vector>
#include <memory>
#include <mutex>
#include <boost/thread/shared_mutex.hpp>
#include <functional>
#include <list>
#include <memory>
#include <mutex>
#include <utility>
#include <boost/thread/shared_mutex.hpp>
#include <vector>
template<typename Key,typename Value,typename Hash=std::hash<Key> >
class threadsafe_lookup_table
{
template <typename Key, typename Value, typename Hash = std::hash<Key>>
class threadsafe_lookup_table {
private:
class bucket_type
class bucket_type {
private:
typedef std::pair<Key, Value> bucket_value;
typedef std::list<bucket_value> bucket_data;
typedef typename bucket_data::iterator bucket_iterator;
bucket_data data;
mutable boost::shared_mutex mutex;
bucket_iterator find_entry_for(Key const& key) const
{
private:
typedef std::pair<Key,Value> bucket_value;
typedef std::list<bucket_value> bucket_data;
typedef typename bucket_data::iterator bucket_iterator;
bucket_data data;
mutable boost::shared_mutex mutex;
bucket_iterator find_entry_for(Key const& key) const
{
return std::find_if(data.begin(),data.end(),
[&](bucket_value const& item)
{return item.first==key;});
}
public:
Value value_for(Key const& key,Value const& default_value) const
{
boost::shared_lock<boost::shared_mutex> lock(mutex);
bucket_iterator const found_entry=find_entry_for(key);
return (found_entry==data.end())?
default_value : found_entry->second;
}
void add_or_update_mapping(Key const& key,Value const& value)
{
std::unique_lock<boost::shared_mutex> lock(mutex);
bucket_iterator const found_entry=find_entry_for(key);
if(found_entry==data.end())
{
data.push_back(bucket_value(key,value));
}
else
{
found_entry->second=value;
}
}
void remove_mapping(Key const& key)
{
std::unique_lock<boost::shared_mutex> lock(mutex);
bucket_iterator const found_entry=find_entry_for(key);
if(found_entry!=data.end())
{
data.erase(found_entry);
}
}
};
std::vector<std::unique_ptr<bucket_type> > buckets;
Hash hasher;
bucket_type& get_bucket(Key const& key) const
{
std::size_t const bucket_index=hasher(key)%buckets.size();
return *buckets[bucket_index];
return std::find_if(
data.begin(), data.end(), [&](bucket_value const& item) {
return item.first == key;
});
}
public:
typedef Key key_type;
typedef Value mapped_type;
typedef Hash hash_type;
threadsafe_lookup_table(
unsigned num_buckets=19, Hash const& hasher_=Hash()):
buckets(num_buckets),hasher(hasher_)
public:
Value value_for(Key const& key, Value const& default_value) const
{
for(unsigned i=0;i<num_buckets;++i)
{
buckets[i].reset(new bucket_type);
}
boost::shared_lock<boost::shared_mutex> lock(mutex);
bucket_iterator const found_entry = find_entry_for(key);
return (found_entry == data.end()) ? default_value : found_entry->second;
}
threadsafe_lookup_table(threadsafe_lookup_table const& other)=delete;
threadsafe_lookup_table& operator=(
threadsafe_lookup_table const& other)=delete;
Value value_for(Key const& key,
Value const& default_value=Value()) const
void add_or_update_mapping(Key const& key, Value const& value)
{
return get_bucket(key).value_for(key,default_value);
std::unique_lock<boost::shared_mutex> lock(mutex);
bucket_iterator const found_entry = find_entry_for(key);
if (found_entry == data.end()) {
data.push_back(bucket_value(key, value));
}
else {
found_entry->second = value;
}
}
void add_or_update_mapping(Key const& key,Value const& value)
{
get_bucket(key).add_or_update_mapping(key,value);
}
void remove_mapping(Key const& key)
{
get_bucket(key).remove_mapping(key);
std::unique_lock<boost::shared_mutex> lock(mutex);
bucket_iterator const found_entry = find_entry_for(key);
if (found_entry != data.end()) {
data.erase(found_entry);
}
}
};
std::vector<std::unique_ptr<bucket_type>> buckets;
Hash hasher;
bucket_type& get_bucket(Key const& key) const
{
std::size_t const bucket_index = hasher(key) % buckets.size();
return *buckets[bucket_index];
}
public:
typedef Key key_type;
typedef Value mapped_type;
typedef Hash hash_type;
threadsafe_lookup_table(unsigned num_buckets = 19,
Hash const& hasher_ = Hash())
: buckets(num_buckets), hasher(hasher_)
{
for (unsigned i = 0; i < num_buckets; ++i) {
buckets[i].reset(new bucket_type);
}
}
threadsafe_lookup_table(threadsafe_lookup_table const& other) = delete;
threadsafe_lookup_table& operator=(threadsafe_lookup_table const& other) =
delete;
Value value_for(Key const& key, Value const& default_value = Value()) const
{
return get_bucket(key).value_for(key, default_value);
}
void add_or_update_mapping(Key const& key, Value const& value)
{
get_bucket(key).add_or_update_mapping(key, value);
}
void remove_mapping(Key const& key) { get_bucket(key).remove_mapping(key); }
};

View File

@@ -1,20 +1,17 @@
std::map<Key,Value> threadsafe_lookup_table::get_map() const
std::map<Key, Value>
threadsafe_lookup_table::get_map() const
{
std::vector<std::unique_lock<boost::shared_mutex> > locks;
for(unsigned i=0;i<buckets.size();++i)
{
locks.push_back(
std::unique_lock<boost::shared_mutex>(buckets[i].mutex));
std::vector<std::unique_lock<boost::shared_mutex>> locks;
for (unsigned i = 0; i < buckets.size(); ++i) {
locks.push_back(std::unique_lock<boost::shared_mutex>(buckets[i].mutex));
}
std::map<Key, Value> res;
for (unsigned i = 0; i < buckets.size(); ++i) {
for (bucket_iterator it = buckets[i].data.begin();
it != buckets[i].data.end();
++it) {
res.insert(*it);
}
std::map<Key,Value> res;
for(unsigned i=0;i<buckets.size();++i)
{
for(bucket_iterator it=buckets[i].data.begin();
it!=buckets[i].data.end();
++it)
{
res.insert(*it);
}
}
return res;
}
return res;
}

View File

@@ -1,101 +1,87 @@
#include <memory>
#include <mutex>
template<typename T>
class threadsafe_list
{
struct node
{
std::mutex m;
std::shared_ptr<T> data;
std::unique_ptr<node> next;
template <typename T>
class threadsafe_list {
struct node {
std::mutex m;
std::shared_ptr<T> data;
std::unique_ptr<node> next;
node():
next()
{}
node(T const& value):
data(std::make_shared<T>(value))
{}
};
node head;
node() : next() {}
node(T const& value) : data(std::make_shared<T>(value)) {}
};
node head;
public:
threadsafe_list()
{}
threadsafe_list() {}
~threadsafe_list()
{
remove_if([](T const&){return true;});
}
~threadsafe_list()
{
remove_if([](T const&) { return true; });
}
threadsafe_list(threadsafe_list const& other)=delete;
threadsafe_list& operator=(threadsafe_list const& other)=delete;
void push_front(T const& value)
{
std::unique_ptr<node> new_node(new node(value));
std::lock_guard<std::mutex> lk(head.m);
new_node->next=std::move(head.next);
head.next=std::move(new_node);
}
threadsafe_list(threadsafe_list const& other) = delete;
threadsafe_list& operator=(threadsafe_list const& other) = delete;
template<typename Function>
void for_each(Function f)
{
node* current=&head;
std::unique_lock<std::mutex> lk(head.m);
while(node* const next=current->next.get())
{
std::unique_lock<std::mutex> next_lk(next->m);
lk.unlock();
f(*next->data);
current=next;
lk=std::move(next_lk);
}
}
void push_front(T const& value)
{
std::unique_ptr<node> new_node(new node(value));
std::lock_guard<std::mutex> lk(head.m);
new_node->next = std::move(head.next);
head.next = std::move(new_node);
}
template<typename Predicate>
std::shared_ptr<T> find_first_if(Predicate p)
{
node* current=&head;
std::unique_lock<std::mutex> lk(head.m);
while(node* const next=current->next.get())
{
std::unique_lock<std::mutex> next_lk(next->m);
lk.unlock();
if(p(*next->data))
{
return next->data;
}
current=next;
lk=std::move(next_lk);
}
return std::shared_ptr<T>();
template <typename Function>
void for_each(Function f)
{
node* current = &head;
std::unique_lock<std::mutex> lk(head.m);
while (node* const next = current->next.get()) {
std::unique_lock<std::mutex> next_lk(next->m);
lk.unlock();
f(*next->data);
current = next;
lk = std::move(next_lk);
}
}
template<typename Predicate>
void remove_if(Predicate p)
{
node* current=&head;
std::unique_lock<std::mutex> lk(head.m);
while(node* const next=current->next.get())
{
std::unique_lock<std::mutex> next_lk(next->m);
if(p(*next->data))
{
std::unique_ptr<node> old_next=std::move(current->next);
current->next=std::move(next->next);
next_lk.unlock();
}
else
{
lk.unlock();
current=next;
lk=std::move(next_lk);
}
}
template <typename Predicate>
std::shared_ptr<T> find_first_if(Predicate p)
{
node* current = &head;
std::unique_lock<std::mutex> lk(head.m);
while (node* const next = current->next.get()) {
std::unique_lock<std::mutex> next_lk(next->m);
lk.unlock();
if (p(*next->data)) {
return next->data;
}
current = next;
lk = std::move(next_lk);
}
return std::shared_ptr<T>();
}
template <typename Predicate>
void remove_if(Predicate p)
{
node* current = &head;
std::unique_lock<std::mutex> lk(head.m);
while (node* const next = current->next.get()) {
std::unique_lock<std::mutex> next_lk(next->m);
if (p(*next->data)) {
std::unique_ptr<node> old_next = std::move(current->next);
current->next = std::move(next->next);
next_lk.unlock();
}
else {
lk.unlock();
current = next;
lk = std::move(next_lk);
}
}
}
};

View File

@@ -1,72 +1,70 @@
#include <queue>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <queue>
template<typename T>
class threadsafe_queue
{
template <typename T>
class threadsafe_queue {
private:
mutable std::mutex mut;
std::queue<T> data_queue;
std::condition_variable data_cond;
mutable std::mutex mut;
std::queue<T> data_queue;
std::condition_variable data_cond;
public:
threadsafe_queue()
{}
threadsafe_queue() {}
void push(T new_value)
{
std::lock_guard<std::mutex> lk(mut);
data_queue.push(std::move(new_value));
data_cond.notify_one();
}
void push(T new_value)
{
std::lock_guard<std::mutex> lk(mut);
data_queue.push(std::move(new_value));
data_cond.notify_one();
}
void wait_and_pop(T& value)
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk,[this]{return !data_queue.empty();});
value=std::move(data_queue.front());
data_queue.pop();
}
void wait_and_pop(T& value)
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk, [this] { return !data_queue.empty(); });
value = std::move(data_queue.front());
data_queue.pop();
}
std::shared_ptr<T> wait_and_pop()
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk,[this]{return !data_queue.empty();});
std::shared_ptr<T> res(
std::make_shared<T>(std::move(data_queue.front())));
data_queue.pop();
return res;
}
std::shared_ptr<T> wait_and_pop()
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk, [this] { return !data_queue.empty(); });
std::shared_ptr<T> res(std::make_shared<T>(std::move(data_queue.front())));
data_queue.pop();
return res;
}
bool try_pop(T& value)
{
std::lock_guard<std::mutex> lk(mut);
if(data_queue.empty())
return false;
value=std::move(data_queue.front());
data_queue.pop();
}
bool try_pop(T& value)
{
std::lock_guard<std::mutex> lk(mut);
if (data_queue.empty())
return false;
value = std::move(data_queue.front());
data_queue.pop();
}
std::shared_ptr<T> try_pop()
{
std::lock_guard<std::mutex> lk(mut);
if(data_queue.empty())
return std::shared_ptr<T>();
std::shared_ptr<T> res(
std::make_shared<T>(std::move(data_queue.front())));
data_queue.pop();
return res;
}
std::shared_ptr<T> try_pop()
{
std::lock_guard<std::mutex> lk(mut);
if (data_queue.empty())
return std::shared_ptr<T>();
std::shared_ptr<T> res(std::make_shared<T>(std::move(data_queue.front())));
data_queue.pop();
return res;
}
bool empty() const
{
std::lock_guard<std::mutex> lk(mut);
return data_queue.empty();
}
bool empty() const
{
std::lock_guard<std::mutex> lk(mut);
return data_queue.empty();
}
};
int main()
int
main()
{
threadsafe_queue<int> rq;
threadsafe_queue<int> rq;
}

View File

@@ -1,68 +1,65 @@
#include <queue>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <queue>
template<typename T>
class threadsafe_queue
{
template <typename T>
class threadsafe_queue {
private:
mutable std::mutex mut;
std::queue<std::shared_ptr<T> > data_queue;
std::condition_variable data_cond;
mutable std::mutex mut;
std::queue<std::shared_ptr<T>> data_queue;
std::condition_variable data_cond;
public:
threadsafe_queue()
{}
threadsafe_queue() {}
void wait_and_pop(T& value)
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk,[this]{return !data_queue.empty();});
value=std::move(*data_queue.front());
data_queue.pop();
}
void wait_and_pop(T& value)
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk, [this] { return !data_queue.empty(); });
value = std::move(*data_queue.front());
data_queue.pop();
}
bool try_pop(T& value)
{
std::lock_guard<std::mutex> lk(mut);
if(data_queue.empty())
return false;
value=std::move(*data_queue.front());
data_queue.pop();
}
bool try_pop(T& value)
{
std::lock_guard<std::mutex> lk(mut);
if (data_queue.empty())
return false;
value = std::move(*data_queue.front());
data_queue.pop();
}
std::shared_ptr<T> wait_and_pop()
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk,[this]{return !data_queue.empty();});
std::shared_ptr<T> res=data_queue.front();
data_queue.pop();
return res;
}
std::shared_ptr<T> wait_and_pop()
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk, [this] { return !data_queue.empty(); });
std::shared_ptr<T> res = data_queue.front();
data_queue.pop();
return res;
}
std::shared_ptr<T> try_pop()
{
std::lock_guard<std::mutex> lk(mut);
if(data_queue.empty())
return std::shared_ptr<T>();
std::shared_ptr<T> res=data_queue.front();
data_queue.pop();
return res;
}
std::shared_ptr<T> try_pop()
{
std::lock_guard<std::mutex> lk(mut);
if (data_queue.empty())
return std::shared_ptr<T>();
std::shared_ptr<T> res = data_queue.front();
data_queue.pop();
return res;
}
bool empty() const
{
std::lock_guard<std::mutex> lk(mut);
return data_queue.empty();
}
void push(T new_value)
{
std::shared_ptr<T> data(
std::make_shared<T>(std::move(new_value)));
std::lock_guard<std::mutex> lk(mut);
data_queue.push(data);
data_cond.notify_one();
}
bool empty() const
{
std::lock_guard<std::mutex> lk(mut);
return data_queue.empty();
}
void push(T new_value)
{
std::shared_ptr<T> data(std::make_shared<T>(std::move(new_value)));
std::lock_guard<std::mutex> lk(mut);
data_queue.push(data);
data_cond.notify_one();
}
};

View File

@@ -1,56 +1,45 @@
#include <memory>
template<typename T>
class queue
{
template <typename T>
class queue {
private:
struct node
{
T data;
std::unique_ptr<node> next;
struct node {
T data;
std::unique_ptr<node> next;
node(T data_) : data(std::move(data_)) {}
};
std::unique_ptr<node> head;
node* tail;
node(T data_):
data(std::move(data_))
{}
};
std::unique_ptr<node> head;
node* tail;
public:
queue():
tail(nullptr)
{}
queue() : tail(nullptr) {}
queue(const queue& other)=delete;
queue& operator=(const queue& other)=delete;
queue(const queue& other) = delete;
queue& operator=(const queue& other) = delete;
std::shared_ptr<T> try_pop()
{
if(!head)
{
return std::shared_ptr<T>();
}
std::shared_ptr<T> const res(
std::make_shared<T>(std::move(head->data)));
std::unique_ptr<node> const old_head=std::move(head);
head=std::move(old_head->next);
return res;
std::shared_ptr<T> try_pop()
{
if (!head) {
return std::shared_ptr<T>();
}
void push(T new_value)
{
std::unique_ptr<node> p(new node(std::move(new_value)));
node* const new_tail=p.get();
if(tail)
{
tail->next=std::move(p);
}
else
{
head=std::move(p);
}
tail=new_tail;
std::shared_ptr<T> const res(std::make_shared<T>(std::move(head->data)));
std::unique_ptr<node> const old_head = std::move(head);
head = std::move(old_head->next);
return res;
}
void push(T new_value)
{
std::unique_ptr<node> p(new node(std::move(new_value)));
node* const new_tail = p.get();
if (tail) {
tail->next = std::move(p);
}
else {
head = std::move(p);
}
tail = new_tail;
}
};

View File

@@ -1,46 +1,39 @@
#include <memory>
template<typename T>
class queue
{
template <typename T>
class queue {
private:
struct node
{
std::shared_ptr<T> data;
std::unique_ptr<node> next;
};
std::unique_ptr<node> head;
node* tail;
struct node {
std::shared_ptr<T> data;
std::unique_ptr<node> next;
};
std::unique_ptr<node> head;
node* tail;
public:
queue():
head(new node),tail(head.get())
{}
queue() : head(new node), tail(head.get()) {}
queue(const queue& other)=delete;
queue& operator=(const queue& other)=delete;
queue(const queue& other) = delete;
queue& operator=(const queue& other) = delete;
std::shared_ptr<T> try_pop()
{
if(head.get()==tail)
{
return std::shared_ptr<T>();
}
std::shared_ptr<T> const res(head->data);
std::unique_ptr<node> const old_head=std::move(head);
head=std::move(old_head->next);
return res;
}
void push(T new_value)
{
std::shared_ptr<T> new_data(
std::make_shared<T>(std::move(new_value)));
std::unique_ptr<node> p(new node);
tail->data=new_data;
node* const new_tail=p.get();
tail->next=std::move(p);
tail=new_tail;
std::shared_ptr<T> try_pop()
{
if (head.get() == tail) {
return std::shared_ptr<T>();
}
std::shared_ptr<T> const res(head->data);
std::unique_ptr<node> const old_head = std::move(head);
head = std::move(old_head->next);
return res;
}
void push(T new_value)
{
std::shared_ptr<T> new_data(std::make_shared<T>(std::move(new_value)));
std::unique_ptr<node> p(new node);
tail->data = new_data;
node* const new_tail = p.get();
tail->next = std::move(p);
tail = new_tail;
}
};

View File

@@ -1,64 +1,56 @@
#include <memory>
#include <mutex>
template<typename T>
class threadsafe_queue
{
template <typename T>
class threadsafe_queue {
private:
struct node
{
std::shared_ptr<T> data;
std::unique_ptr<node> next;
};
std::mutex head_mutex;
std::unique_ptr<node> head;
std::mutex tail_mutex;
node* tail;
node* get_tail()
{
std::lock_guard<std::mutex> tail_lock(tail_mutex);
return tail;
}
struct node {
std::shared_ptr<T> data;
std::unique_ptr<node> next;
};
std::unique_ptr<node> pop_head()
{
std::lock_guard<std::mutex> head_lock(head_mutex);
if(head.get()==get_tail())
{
return nullptr;
}
std::unique_ptr<node> const old_head=std::move(head);
head=std::move(old_head->next);
return old_head;
std::mutex head_mutex;
std::unique_ptr<node> head;
std::mutex tail_mutex;
node* tail;
node* get_tail()
{
std::lock_guard<std::mutex> tail_lock(tail_mutex);
return tail;
}
std::unique_ptr<node> pop_head()
{
std::lock_guard<std::mutex> head_lock(head_mutex);
if (head.get() == get_tail()) {
return nullptr;
}
std::unique_ptr<node> const old_head = std::move(head);
head = std::move(old_head->next);
return old_head;
}
public:
threadsafe_queue():
head(new node),tail(head.get())
{}
threadsafe_queue() : head(new node), tail(head.get()) {}
threadsafe_queue(const threadsafe_queue& other)=delete;
threadsafe_queue& operator=(const threadsafe_queue& other)=delete;
threadsafe_queue(const threadsafe_queue& other) = delete;
threadsafe_queue& operator=(const threadsafe_queue& other) = delete;
std::shared_ptr<T> try_pop()
{
std::unique_ptr<node> old_head=pop_head();
return old_head?old_head->data:std::shared_ptr<T>();
}
void push(T new_value)
{
std::shared_ptr<T> new_data(
std::make_shared<T>(std::move(new_value)));
std::unique_ptr<node> p(new node);
node* const new_tail=p.get();
std::lock_guard<std::mutex> tail_lock(tail_mutex);
tail->data=new_data;
tail->next=std::move(p);
tail=new_tail;
}
std::shared_ptr<T> try_pop()
{
std::unique_ptr<node> old_head = pop_head();
return old_head ? old_head->data : std::shared_ptr<T>();
}
void push(T new_value)
{
std::shared_ptr<T> new_data(std::make_shared<T>(std::move(new_value)));
std::unique_ptr<node> p(new node);
node* const new_tail = p.get();
std::lock_guard<std::mutex> tail_lock(tail_mutex);
tail->data = new_data;
tail->next = std::move(p);
tail = new_tail;
}
};

View File

@@ -1,29 +1,26 @@
template<typename T>
class threadsafe_queue
{
template <typename T>
class threadsafe_queue {
private:
struct node
{
std::shared_ptr<T> data;
std::unique_ptr<node> next;
};
std::mutex head_mutex;
std::unique_ptr<node> head;
std::mutex tail_mutex;
node* tail;
std::condition_variable data_cond;
public:
threadsafe_queue():
head(new node),tail(head.get())
{}
threadsafe_queue(const threadsafe_queue& other)=delete;
threadsafe_queue& operator=(const threadsafe_queue& other)=delete;
struct node {
std::shared_ptr<T> data;
std::unique_ptr<node> next;
};
std::shared_ptr<T> try_pop();
bool try_pop(T& value);
std::shared_ptr<T> wait_and_pop();
void wait_and_pop(T& value);
void push(T new_value);
void empty();
std::mutex head_mutex;
std::unique_ptr<node> head;
std::mutex tail_mutex;
node* tail;
std::condition_variable data_cond;
public:
threadsafe_queue() : head(new node), tail(head.get()) {}
threadsafe_queue(const threadsafe_queue& other) = delete;
threadsafe_queue& operator=(const threadsafe_queue& other) = delete;
std::shared_ptr<T> try_pop();
bool try_pop(T& value);
std::shared_ptr<T> wait_and_pop();
void wait_and_pop(T& value);
void push(T new_value);
void empty();
};

View File

@@ -1,15 +1,15 @@
template<typename T>
void threadsafe_queue<T>::push(T new_value)
template <typename T>
void
threadsafe_queue<T>::push(T new_value)
{
std::shared_ptr<T> new_data(
std::make_shared<T>(std::move(new_value)));
std::unique_ptr<node> p(new node);
{
std::lock_guard<std::mutex> tail_lock(tail_mutex);
tail->data=new_data;
node* const new_tail=p.get();
tail->next=std::move(p);
tail=new_tail;
}
data_cond.notify_one();
std::shared_ptr<T> new_data(std::make_shared<T>(std::move(new_value)));
std::unique_ptr<node> p(new node);
{
std::lock_guard<std::mutex> tail_lock(tail_mutex);
tail->data = new_data;
node* const new_tail = p.get();
tail->next = std::move(p);
tail = new_tail;
}
data_cond.notify_one();
}

View File

@@ -1,49 +1,48 @@
template<typename T>
class threadsafe_queue
{
template <typename T>
class threadsafe_queue {
private:
node* get_tail()
{
std::lock_guard<std::mutex> tail_lock(tail_mutex);
return tail;
}
node* get_tail()
{
std::lock_guard<std::mutex> tail_lock(tail_mutex);
return tail;
}
std::unique_ptr<node> pop_head()
{
std::unique_ptr<node> const old_head=std::move(head);
head=std::move(old_head->next);
return old_head;
}
std::unique_ptr<node> pop_head()
{
std::unique_ptr<node> const old_head = std::move(head);
head = std::move(old_head->next);
return old_head;
}
std::unique_lock<std::mutex> wait_for_data()
{
std::unique_lock<std::mutex> head_lock(head_mutex);
data_cond.wait(head_lock,[&]{return head!=get_tail();});
return std::move(head_lock);
}
std::unique_lock<std::mutex> wait_for_data()
{
std::unique_lock<std::mutex> head_lock(head_mutex);
data_cond.wait(head_lock, [&] { return head != get_tail(); });
return std::move(head_lock);
}
std::unique_ptr<node> wait_pop_head()
{
std::unique_lock<std::mutex> head_lock(wait_for_data());
return pop_head();
}
std::unique_ptr<node> wait_pop_head()
{
std::unique_lock<std::mutex> head_lock(wait_for_data());
return pop_head();
}
std::unique_ptr<node> wait_pop_head(T& value)
{
std::unique_lock<std::mutex> head_lock(wait_for_data());
value = std::move(*head->data);
return pop_head();
}
std::unique_ptr<node> wait_pop_head(T& value)
{
std::unique_lock<std::mutex> head_lock(wait_for_data());
value=std::move(*head->data);
return pop_head();
}
public:
std::shared_ptr<T> wait_and_pop()
{
std::unique_ptr<node> const old_head=wait_pop_head();
return old_head->data;
}
std::shared_ptr<T> wait_and_pop()
{
std::unique_ptr<node> const old_head = wait_pop_head();
return old_head->data;
}
void wait_and_pop(T& value)
{
std::unique_ptr<node> const old_head=wait_pop_head(value);
}
void wait_and_pop(T& value)
{
std::unique_ptr<node> const old_head = wait_pop_head(value);
}
};

View File

@@ -1,18 +1,14 @@
#include <atomic>
class spinlock_mutex
{
std::atomic_flag flag;
class spinlock_mutex {
std::atomic_flag flag;
public:
spinlock_mutex():
flag(ATOMIC_FLAG_INIT)
{}
void lock()
{
while(flag.test_and_set(std::memory_order_acquire));
}
void unlock()
{
flag.clear(std::memory_order_release);
}
spinlock_mutex() : flag(ATOMIC_FLAG_INIT) {}
void lock()
{
while (flag.test_and_set(std::memory_order_acquire))
;
}
void unlock() { flag.clear(std::memory_order_release); }
};

View File

@@ -1,38 +1,37 @@
#include <atomic>
#include <memory>
template<typename T>
class lock_free_stack
{
template <typename T>
class lock_free_stack {
private:
struct node;
struct counted_node_ptr
struct node;
struct counted_node_ptr {
int external_count;
node* ptr;
};
struct node {
std::shared_ptr<T> data;
std::atomic<int> internal_count;
counted_node_ptr next;
node(T const& data_) : data(std::make_shared<T>(data_)), internal_count(0)
{
int external_count;
node* ptr;
};
struct node
{
std::shared_ptr<T> data;
std::atomic<int> internal_count;
counted_node_ptr next;
node(T const& data_):
data(std::make_shared<T>(data_)),
internal_count(0)
{}
};
std::atomic<counted_node_ptr> head;
}
};
std::atomic<counted_node_ptr> head;
public:
~lock_free_stack()
{
while(pop());
}
void push(T const& data)
{
counted_node_ptr new_node;
new_node.ptr=new node(data);
new_node.external_count=1;
new_node.ptr->next=head.load();
while(!head.compare_exchange_weak(new_node.ptr->next,new_node));
}
~lock_free_stack()
{
while (pop())
;
}
void push(T const& data)
{
counted_node_ptr new_node;
new_node.ptr = new node(data);
new_node.external_count = 1;
new_node.ptr->next = head.load();
while (!head.compare_exchange_weak(new_node.ptr->next, new_node))
;
}
};

View File

@@ -1,46 +1,38 @@
template<typename T>
class lock_free_stack
{
template <typename T>
class lock_free_stack {
private:
void increase_head_count(counted_node_ptr& old_counter)
{
counted_node_ptr new_counter;
do
{
new_counter=old_counter;
++new_counter.external_count;
}
while(!head.compare_exchange_strong(old_counter,new_counter));
old_counter.external_count=new_counter.external_count;
}
void increase_head_count(counted_node_ptr& old_counter)
{
counted_node_ptr new_counter;
do {
new_counter = old_counter;
++new_counter.external_count;
} while (!head.compare_exchange_strong(old_counter, new_counter));
old_counter.external_count = new_counter.external_count;
}
public:
std::shared_ptr<T> pop()
{
counted_node_ptr old_head=head.load();
for(;;)
{
increase_head_count(old_head);
node* const ptr=old_head.ptr;
if(!ptr)
{
return std::shared_ptr<T>();
}
if(head.compare_exchange_strong(old_head,ptr->next))
{
std::shared_ptr<T> res;
res.swap(ptr->data);
int const count_increase=old_head.external_count-2;
if(ptr->internal_count.fetch_add(count_increase)==
-count_increase)
{
delete ptr;
}
return res;
}
else if(ptr->internal_count.fetch_sub(1)==1)
{
delete ptr;
}
std::shared_ptr<T> pop()
{
counted_node_ptr old_head = head.load();
for (;;) {
increase_head_count(old_head);
node* const ptr = old_head.ptr;
if (!ptr) {
return std::shared_ptr<T>();
}
if (head.compare_exchange_strong(old_head, ptr->next)) {
std::shared_ptr<T> res;
res.swap(ptr->data);
int const count_increase = old_head.external_count - 2;
if (ptr->internal_count.fetch_add(count_increase) == -count_increase) {
delete ptr;
}
return res;
}
else if (ptr->internal_count.fetch_sub(1) == 1) {
delete ptr;
}
}
}
};

View File

@@ -1,88 +1,78 @@
#include <atomic>
#include <memory>
template<typename T>
class lock_free_stack
{
template <typename T>
class lock_free_stack {
private:
struct node;
struct counted_node_ptr
struct node;
struct counted_node_ptr {
int external_count;
node* ptr;
};
struct node {
std::shared_ptr<T> data;
std::atomic<int> internal_count;
counted_node_ptr next;
node(T const& data_) : data(std::make_shared<T>(data_)), internal_count(0)
{
int external_count;
node* ptr;
};
struct node
{
std::shared_ptr<T> data;
std::atomic<int> internal_count;
counted_node_ptr next;
node(T const& data_):
data(std::make_shared<T>(data_)),
internal_count(0)
{}
};
std::atomic<counted_node_ptr> head;
void increase_head_count(counted_node_ptr& old_counter)
{
counted_node_ptr new_counter;
do
{
new_counter=old_counter;
++new_counter.external_count;
}
while(!head.compare_exchange_strong(
old_counter,new_counter,
std::memory_order_acquire,
std::memory_order_relaxed));
old_counter.external_count=new_counter.external_count;
}
};
std::atomic<counted_node_ptr> head;
void increase_head_count(counted_node_ptr& old_counter)
{
counted_node_ptr new_counter;
do {
new_counter = old_counter;
++new_counter.external_count;
} while (!head.compare_exchange_strong(old_counter,
new_counter,
std::memory_order_acquire,
std::memory_order_relaxed));
old_counter.external_count = new_counter.external_count;
}
public:
~lock_free_stack()
{
while(pop());
}
void push(T const& data)
{
counted_node_ptr new_node;
new_node.ptr=new node(data);
new_node.external_count=1;
new_node.ptr->next=head.load(std::memory_order_relaxed)
while(!head.compare_exchange_weak(
new_node.ptr->next,new_node,
std::memory_order_release,
std::memory_order_relaxed));
}
std::shared_ptr<T> pop()
{
counted_node_ptr old_head=
head.load(std::memory_order_relaxed);
for(;;)
{
increase_head_count(old_head);
node* const ptr=old_head.ptr;
if(!ptr)
{
return std::shared_ptr<T>();
}
if(head.compare_exchange_strong(
old_head,ptr->next,std::memory_order_relaxed))
{
std::shared_ptr<T> res;
res.swap(ptr->data);
int const count_increase=old_head.external_count-2;
if(ptr->internal_count.fetch_add(
count_increase,std::memory_order_release)==-count_increase)
{
delete ptr;
}
return res;
}
else if(ptr->internal_count.fetch_add(
-1,std::memory_order_relaxed)==1)
{
ptr->internal_count.load(std::memory_order_acquire);
delete ptr;
}
~lock_free_stack()
{
while (pop())
;
}
void push(T const& data)
{
counted_node_ptr new_node;
new_node.ptr = new node(data);
new_node.external_count = 1;
new_node.ptr->next = head.load(std::memory_order_relaxed) while (
!head.compare_exchange_weak(new_node.ptr->next,
new_node,
std::memory_order_release,
std::memory_order_relaxed));
}
std::shared_ptr<T> pop()
{
counted_node_ptr old_head = head.load(std::memory_order_relaxed);
for (;;) {
increase_head_count(old_head);
node* const ptr = old_head.ptr;
if (!ptr) {
return std::shared_ptr<T>();
}
if (head.compare_exchange_strong(
old_head, ptr->next, std::memory_order_relaxed)) {
std::shared_ptr<T> res;
res.swap(ptr->data);
int const count_increase = old_head.external_count - 2;
if (ptr->internal_count.fetch_add(
count_increase, std::memory_order_release) == -count_increase) {
delete ptr;
}
return res;
}
else if (ptr->internal_count.fetch_add(-1, std::memory_order_relaxed) ==
1) {
ptr->internal_count.load(std::memory_order_acquire);
delete ptr;
}
}
}
};

View File

@@ -1,62 +1,54 @@
#include <memory>
#include <atomic>
#include <memory>
template<typename T>
class lock_free_queue
{
template <typename T>
class lock_free_queue {
private:
struct node
{
std::shared_ptr<T> data;
node* next;
node():
next(nullptr)
{}
};
std::atomic<node*> head;
std::atomic<node*> tail;
node* pop_head()
{
node* const old_head=head.load();
if(old_head==tail.load())
{
return nullptr;
}
head.store(old_head->next);
return old_head;
struct node {
std::shared_ptr<T> data;
node* next;
node() : next(nullptr) {}
};
std::atomic<node*> head;
std::atomic<node*> tail;
node* pop_head()
{
node* const old_head = head.load();
if (old_head == tail.load()) {
return nullptr;
}
head.store(old_head->next);
return old_head;
}
public:
lock_free_queue():
head(new node),tail(head.load())
{}
lock_free_queue(const lock_free_queue& other)=delete;
lock_free_queue& operator=(const lock_free_queue& other)=delete;
~lock_free_queue()
{
while(node* const old_head=head.load())
{
head.store(old_head->next);
delete old_head;
}
lock_free_queue() : head(new node), tail(head.load()) {}
lock_free_queue(const lock_free_queue& other) = delete;
lock_free_queue& operator=(const lock_free_queue& other) = delete;
~lock_free_queue()
{
while (node* const old_head = head.load()) {
head.store(old_head->next);
delete old_head;
}
std::shared_ptr<T> pop()
{
node* old_head=pop_head();
if(!old_head)
{
return std::shared_ptr<T>();
}
std::shared_ptr<T> const res(old_head->data);
delete old_head;
return res;
}
void push(T new_value)
{
std::shared_ptr<T> new_data(std::make_shared<T>(new_value));
node* p=new node;
node* const old_tail=tail.load();
old_tail->data.swap(new_data);
old_tail->next=p;
tail.store(p);
}
std::shared_ptr<T> pop()
{
node* old_head = pop_head();
if (!old_head) {
return std::shared_ptr<T>();
}
std::shared_ptr<T> const res(old_head->data);
delete old_head;
return res;
}
void push(T new_value)
{
std::shared_ptr<T> new_data(std::make_shared<T>(new_value));
node* p = new node;
node* const old_tail = tail.load();
old_tail->data.swap(new_data);
old_tail->next = p;
tail.store(p);
}
};

View File

@@ -1,20 +1,18 @@
void push(T new_value)
void
push(T new_value)
{
std::unique_ptr<T> new_data(new T(new_value));
counted_node_ptr new_next;
new_next.ptr=new node;
new_next.external_count=1;
for(;;)
{
node* const old_tail=tail.load();
T* old_data=nullptr;
if(old_tail->data.compare_exchange_strong(
old_data,new_data.get()))
{
old_tail->next=new_next;
tail.store(new_next.ptr);
new_data.release();
break;
}
std::unique_ptr<T> new_data(new T(new_value));
counted_node_ptr new_next;
new_next.ptr = new node;
new_next.external_count = 1;
for (;;) {
node* const old_tail = tail.load();
T* old_data = nullptr;
if (old_tail->data.compare_exchange_strong(old_data, new_data.get())) {
old_tail->next = new_next;
tail.store(new_next.ptr);
new_data.release();
break;
}
}
}

View File

@@ -1,59 +1,54 @@
#include <atomic>
template<typename T>
class lock_free_queue
{
template <typename T>
class lock_free_queue {
private:
struct node;
struct counted_node_ptr
struct node;
struct counted_node_ptr {
int external_count;
node* ptr;
};
std::atomic<counted_node_ptr> head;
std::atomic<counted_node_ptr> tail;
struct node_counter {
unsigned internal_count : 30;
unsigned external_counters : 2;
};
struct node {
std::atomic<T*> data;
std::atomic<node_counter> count;
counted_node_ptr next;
node()
{
int external_count;
node* ptr;
};
std::atomic<counted_node_ptr> head;
std::atomic<counted_node_ptr> tail;
struct node_counter
{
unsigned internal_count:30;
unsigned external_counters:2;
};
struct node
{
std::atomic<T*> data;
std::atomic<node_counter> count;
counted_node_ptr next;
node()
{
node_counter new_count;
new_count.internal_count=0;
new_count.external_counters=2;
count.store(new_count);
next.ptr=nullptr;
next.external_count=0;
}
};
public:
void push(T new_value)
{
std::unique_ptr<T> new_data(new T(new_value));
counted_node_ptr new_next;
new_next.ptr=new node;
new_next.external_count=1;
counted_node_ptr old_tail=tail.load();
for(;;)
{
increase_external_count(tail,old_tail);
T* old_data=nullptr;
if(old_tail.ptr->data.compare_exchange_strong(
old_data,new_data.get()))
{
old_tail.ptr->next=new_next;
old_tail=tail.exchange(new_next);
free_external_counter(old_tail);
new_data.release();
break;
}
old_tail.ptr->release_ref();
}
node_counter new_count;
new_count.internal_count = 0;
new_count.external_counters = 2;
count.store(new_count);
next.ptr = nullptr;
next.external_count = 0;
}
};
public:
void push(T new_value)
{
std::unique_ptr<T> new_data(new T(new_value));
counted_node_ptr new_next;
new_next.ptr = new node;
new_next.external_count = 1;
counted_node_ptr old_tail = tail.load();
for (;;) {
increase_external_count(tail, old_tail);
T* old_data = nullptr;
if (old_tail.ptr->data.compare_exchange_strong(old_data,
new_data.get())) {
old_tail.ptr->next = new_next;
old_tail = tail.exchange(new_next);
free_external_counter(old_tail);
new_data.release();
break;
}
old_tail.ptr->release_ref();
}
}
};

View File

@@ -1,31 +1,27 @@
template<typename T>
class lock_free_queue
{
template <typename T>
class lock_free_queue {
private:
struct node
{
void release_ref();
};
struct node {
void release_ref();
};
public:
std::unique_ptr<T> pop()
{
counted_node_ptr old_head=head.load(std::memory_order_relaxed);
for(;;)
{
increase_external_count(head,old_head);
node* const ptr=old_head.ptr;
if(ptr==tail.load().ptr)
{
ptr->release_ref();
return std::unique_ptr<T>();
}
if(head.compare_exchange_strong(old_head,ptr->next))
{
T* const res=ptr->data.exchange(nullptr);
free_external_counter(old_head);
return std::unique_ptr<T>(res);
}
ptr->release_ref();
}
std::unique_ptr<T> pop()
{
counted_node_ptr old_head = head.load(std::memory_order_relaxed);
for (;;) {
increase_external_count(head, old_head);
node* const ptr = old_head.ptr;
if (ptr == tail.load().ptr) {
ptr->release_ref();
return std::unique_ptr<T>();
}
if (head.compare_exchange_strong(old_head, ptr->next)) {
T* const res = ptr->data.exchange(nullptr);
free_external_counter(old_head);
return std::unique_ptr<T>(res);
}
ptr->release_ref();
}
}
};

View File

@@ -1,27 +1,21 @@
template<typename T>
class lock_free_queue
{
template <typename T>
class lock_free_queue {
private:
struct node
struct node {
void release_ref()
{
void release_ref()
{
node_counter old_counter=
count.load(std::memory_order_relaxed);
node_counter new_counter;
do
{
new_counter=old_counter;
--new_counter.internal_count;
}
while(!count.compare_exchange_strong(
old_counter,new_counter,
std::memory_order_acquire,std::memory_order_relaxed));
if(!new_counter.internal_count &&
!new_counter.external_counters)
{
delete this;
}
}
};
node_counter old_counter = count.load(std::memory_order_relaxed);
node_counter new_counter;
do {
new_counter = old_counter;
--new_counter.internal_count;
} while (!count.compare_exchange_strong(old_counter,
new_counter,
std::memory_order_acquire,
std::memory_order_relaxed));
if (!new_counter.internal_count && !new_counter.external_counters) {
delete this;
}
}
};
};

View File

@@ -1,20 +1,17 @@
template<typename T>
class lock_free_queue
{
template <typename T>
class lock_free_queue {
private:
static void increase_external_count(
std::atomic<counted_node_ptr>& counter,
counted_node_ptr& old_counter)
{
counted_node_ptr new_counter;
do
{
new_counter=old_counter;
++new_counter.external_count;
}
while(!counter.compare_exchange_strong(
old_counter,new_counter,
std::memory_order_acquire,std::memory_order_relaxed));
old_counter.external_count=new_counter.external_count;
}
static void increase_external_count(std::atomic<counted_node_ptr>& counter,
counted_node_ptr& old_counter)
{
counted_node_ptr new_counter;
do {
new_counter = old_counter;
++new_counter.external_count;
} while (!counter.compare_exchange_strong(old_counter,
new_counter,
std::memory_order_acquire,
std::memory_order_relaxed));
old_counter.external_count = new_counter.external_count;
}
};

View File

@@ -1,27 +1,22 @@
template<typename T>
class lock_free_queue
{
template <typename T>
class lock_free_queue {
private:
static void free_external_counter(counted_node_ptr &old_node_ptr)
{
node* const ptr=old_node_ptr.ptr;
int const count_increase=old_node_ptr.external_count-2;
node_counter old_counter=
ptr->count.load(std::memory_order_relaxed);
node_counter new_counter;
do
{
new_counter=old_counter;
--new_counter.external_counters;
new_counter.internal_count+=count_increase;
}
while(!ptr->count.compare_exchange_strong(
old_counter,new_counter,
std::memory_order_acquire,std::memory_order_relaxed));
if(!new_counter.internal_count &&
!new_counter.external_counters)
{
delete ptr;
}
static void free_external_counter(counted_node_ptr& old_node_ptr)
{
node* const ptr = old_node_ptr.ptr;
int const count_increase = old_node_ptr.external_count - 2;
node_counter old_counter = ptr->count.load(std::memory_order_relaxed);
node_counter new_counter;
do {
new_counter = old_counter;
--new_counter.external_counters;
new_counter.internal_count += count_increase;
} while (!ptr->count.compare_exchange_strong(old_counter,
new_counter,
std::memory_order_acquire,
std::memory_order_relaxed));
if (!new_counter.internal_count && !new_counter.external_counters) {
delete ptr;
}
}
};

View File

@@ -1,23 +1,21 @@
#include <atomic>
template<typename T>
class lock_free_stack
{
template <typename T>
class lock_free_stack {
private:
struct node
{
T data;
node* next;
node(T const& data_):
data(data_)
{}
};
std::atomic<node*> head;
struct node {
T data;
node* next;
node(T const& data_) : data(data_) {}
};
std::atomic<node*> head;
public:
void push(T const& data)
{
node* const new_node=new node(data);
new_node->next=head.load();
while(!head.compare_exchange_weak(new_node->next,new_node));
}
void push(T const& data)
{
node* const new_node = new node(data);
new_node->next = head.load();
while (!head.compare_exchange_weak(new_node->next, new_node))
;
}
};

View File

@@ -1,33 +1,29 @@
template<typename T>
class lock_free_queue
{
template <typename T>
class lock_free_queue {
private:
struct node
{
std::atomic<T*> data;
std::atomic<node_counter> count;
std::atomic<counted_node_ptr> next;
};
struct node {
std::atomic<T*> data;
std::atomic<node_counter> count;
std::atomic<counted_node_ptr> next;
};
public:
std::unique_ptr<T> pop()
{
counted_node_ptr old_head=head.load(std::memory_order_relaxed);
for(;;)
{
increase_external_count(head,old_head);
node* const ptr=old_head.ptr;
if(ptr==tail.load().ptr)
{
return std::unique_ptr<T>();
}
counted_node_ptr next=ptr->next.load();
if(head.compare_exchange_strong(old_head,next))
{
T* const res=ptr->data.exchange(nullptr);
free_external_counter(old_head);
return std::unique_ptr<T>(res);
}
ptr->release_ref();
}
std::unique_ptr<T> pop()
{
counted_node_ptr old_head = head.load(std::memory_order_relaxed);
for (;;) {
increase_external_count(head, old_head);
node* const ptr = old_head.ptr;
if (ptr == tail.load().ptr) {
return std::unique_ptr<T>();
}
counted_node_ptr next = ptr->next.load();
if (head.compare_exchange_strong(old_head, next)) {
T* const res = ptr->data.exchange(nullptr);
free_external_counter(old_head);
return std::unique_ptr<T>(res);
}
ptr->release_ref();
}
}
};

View File

@@ -1,55 +1,49 @@
template<typename T>
class lock_free_queue
{
template <typename T>
class lock_free_queue {
private:
void set_new_tail(counted_node_ptr &old_tail,
counted_node_ptr const &new_tail)
{
node* const current_tail_ptr=old_tail.ptr;
while(!tail.compare_exchange_weak(old_tail,new_tail) &&
old_tail.ptr==current_tail_ptr);
if(old_tail.ptr==current_tail_ptr)
free_external_counter(old_tail);
else
current_tail_ptr->release_ref();
}
void set_new_tail(counted_node_ptr& old_tail,
counted_node_ptr const& new_tail)
{
node* const current_tail_ptr = old_tail.ptr;
while (!tail.compare_exchange_weak(old_tail, new_tail) &&
old_tail.ptr == current_tail_ptr)
;
if (old_tail.ptr == current_tail_ptr)
free_external_counter(old_tail);
else
current_tail_ptr->release_ref();
}
public:
void push(T new_value)
{
std::unique_ptr<T> new_data(new T(new_value));
counted_node_ptr new_next;
new_next.ptr=new node;
new_next.external_count=1;
counted_node_ptr old_tail=tail.load();
for(;;)
{
increase_external_count(tail,old_tail);
T* old_data=nullptr;
if(old_tail.ptr->data.compare_exchange_strong(
old_data,new_data.get()))
{
counted_node_ptr old_next={0};
if(!old_tail.ptr->next.compare_exchange_strong(
old_next,new_next))
{
delete new_next.ptr;
new_next=old_next;
}
set_new_tail(old_tail, new_next);
new_data.release();
break;
}
else
{
counted_node_ptr old_next={0};
if(old_tail.ptr->next.compare_exchange_strong(
old_next,new_next))
{
old_next=new_next;
new_next.ptr=new node;
}
set_new_tail(old_tail, old_next);
}
void push(T new_value)
{
std::unique_ptr<T> new_data(new T(new_value));
counted_node_ptr new_next;
new_next.ptr = new node;
new_next.external_count = 1;
counted_node_ptr old_tail = tail.load();
for (;;) {
increase_external_count(tail, old_tail);
T* old_data = nullptr;
if (old_tail.ptr->data.compare_exchange_strong(old_data,
new_data.get())) {
counted_node_ptr old_next = {0};
if (!old_tail.ptr->next.compare_exchange_strong(old_next, new_next)) {
delete new_next.ptr;
new_next = old_next;
}
set_new_tail(old_tail, new_next);
new_data.release();
break;
}
else {
counted_node_ptr old_next = {0};
if (old_tail.ptr->next.compare_exchange_strong(old_next, new_next)) {
old_next = new_next;
new_next.ptr = new node;
}
set_new_tail(old_tail, old_next);
}
}
}
};

View File

@@ -1,31 +1,29 @@
#include <atomic>
#include <memory>
template<typename T>
class lock_free_stack
{
template <typename T>
class lock_free_stack {
private:
struct node
{
std::shared_ptr<T> data;
node* next;
node(T const& data_):
data(std::make_shared<T>(data_))
{}
};
std::atomic<node*> head;
struct node {
std::shared_ptr<T> data;
node* next;
node(T const& data_) : data(std::make_shared<T>(data_)) {}
};
std::atomic<node*> head;
public:
void push(T const& data)
{
node* const new_node=new node(data);
new_node->next=head.load();
while(!head.compare_exchange_weak(new_node->next,new_node));
}
std::shared_ptr<T> pop()
{
node* old_head=head.load();
while(old_head &&
!head.compare_exchange_weak(old_head,old_head->next));
return old_head ? old_head->data : std::shared_ptr<T>();
}
void push(T const& data)
{
node* const new_node = new node(data);
new_node->next = head.load();
while (!head.compare_exchange_weak(new_node->next, new_node))
;
}
std::shared_ptr<T> pop()
{
node* old_head = head.load();
while (old_head && !head.compare_exchange_weak(old_head, old_head->next))
;
return old_head ? old_head->data : std::shared_ptr<T>();
}
};

View File

@@ -1,25 +1,24 @@
#include <atomic>
#include <memory>
template<typename T>
class lock_free_stack
{
template <typename T>
class lock_free_stack {
private:
std::atomic<unsigned> threads_in_pop;
void try_reclaim(node* old_head);
std::atomic<unsigned> threads_in_pop;
void try_reclaim(node* old_head);
public:
std::shared_ptr<T> pop()
{
++threads_in_pop;
node* old_head=head.load();
while(old_head &&
!head.compare_exchange_weak(old_head,old_head->next));
std::shared_ptr<T> res;
if(old_head)
{
res.swap(old_head->data);
}
try_reclaim(old_head);
return res;
std::shared_ptr<T> pop()
{
++threads_in_pop;
node* old_head = head.load();
while (old_head && !head.compare_exchange_weak(old_head, old_head->next))
;
std::shared_ptr<T> res;
if (old_head) {
res.swap(old_head->data);
}
try_reclaim(old_head);
return res;
}
};

View File

@@ -1,57 +1,47 @@
#include <atomic>
template<typename T>
class lock_free_stack
{
template <typename T>
class lock_free_stack {
private:
std::atomic<node*> to_be_deleted;
static void delete_nodes(node* nodes)
{
while(nodes)
{
node* next=nodes->next;
delete nodes;
nodes=next;
}
std::atomic<node*> to_be_deleted;
static void delete_nodes(node* nodes)
{
while (nodes) {
node* next = nodes->next;
delete nodes;
nodes = next;
}
void try_reclaim(node* old_head)
{
if(threads_in_pop==1)
{
node* nodes_to_delete=to_be_deleted.exchange(nullptr);
if(!--threads_in_pop)
{
delete_nodes(nodes_to_delete);
}
else if(nodes_to_delete)
{
chain_pending_nodes(nodes_to_delete);
}
delete old_head;
}
else
{
chain_pending_node(old_head);
--threads_in_pop;
}
}
void try_reclaim(node* old_head)
{
if (threads_in_pop == 1) {
node* nodes_to_delete = to_be_deleted.exchange(nullptr);
if (!--threads_in_pop) {
delete_nodes(nodes_to_delete);
}
else if (nodes_to_delete) {
chain_pending_nodes(nodes_to_delete);
}
delete old_head;
}
void chain_pending_nodes(node* nodes)
{
node* last=nodes;
while(node* const next=last->next)
{
last=next;
}
chain_pending_nodes(nodes,last);
else {
chain_pending_node(old_head);
--threads_in_pop;
}
void chain_pending_nodes(node* first,node* last)
{
last->next=to_be_deleted;
while(!to_be_deleted.compare_exchange_weak(
last->next,first));
}
void chain_pending_node(node* n)
{
chain_pending_nodes(n,n);
}
void chain_pending_nodes(node* nodes)
{
node* last = nodes;
while (node* const next = last->next) {
last = next;
}
chain_pending_nodes(nodes, last);
}
void chain_pending_nodes(node* first, node* last)
{
last->next = to_be_deleted;
while (!to_be_deleted.compare_exchange_weak(last->next, first))
;
}
void chain_pending_node(node* n) { chain_pending_nodes(n, n); }
};

View File

@@ -1,36 +1,30 @@
#include <atomic>
#include <memory>
std::shared_ptr<T> pop()
std::shared_ptr<T>
pop()
{
std::atomic<void*>& hp=get_hazard_pointer_for_current_thread();
node* old_head=head.load();
do
{
node* temp;
do
{
temp=old_head;
hp.store(old_head);
old_head=head.load();
} while(old_head!=temp);
std::atomic<void*>& hp = get_hazard_pointer_for_current_thread();
node* old_head = head.load();
do {
node* temp;
do {
temp = old_head;
hp.store(old_head);
old_head = head.load();
} while (old_head != temp);
} while (old_head && !head.compare_exchange_strong(old_head, old_head->next));
hp.store(nullptr);
std::shared_ptr<T> res;
if (old_head) {
res.swap(old_head->data);
if (outstanding_hazard_pointers_for(old_head)) {
reclaim_later(old_head);
}
while(old_head &&
!head.compare_exchange_strong(old_head,old_head->next));
hp.store(nullptr);
std::shared_ptr<T> res;
if(old_head)
{
res.swap(old_head->data);
if(outstanding_hazard_pointers_for(old_head))
{
reclaim_later(old_head);
}
else
{
delete old_head;
}
delete_nodes_with_no_hazards();
else {
delete old_head;
}
return res;
delete_nodes_with_no_hazards();
}
return res;
}

View File

@@ -1,49 +1,42 @@
#include <atomic>
#include <thread>
unsigned const max_hazard_pointers=100;
struct hazard_pointer
{
std::atomic<std::thread::id> id;
std::atomic<void*> pointer;
unsigned const max_hazard_pointers = 100;
struct hazard_pointer {
std::atomic<std::thread::id> id;
std::atomic<void*> pointer;
};
hazard_pointer hazard_pointers[max_hazard_pointers];
class hp_owner
{
hazard_pointer* hp;
class hp_owner {
hazard_pointer* hp;
public:
hp_owner(hp_owner const&)=delete;
hp_owner operator=(hp_owner const&)=delete;
hp_owner():
hp(nullptr)
{
for(unsigned i=0;i<max_hazard_pointers;++i)
{
std::thread::id old_id;
if(hazard_pointers[i].id.compare_exchange_strong(
old_id,std::this_thread::get_id()))
{
hp=&hazard_pointers[i];
break;
}
}
if(!hp)
{
throw std::runtime_error("No hazard pointers available");
}
hp_owner(hp_owner const&) = delete;
hp_owner operator=(hp_owner const&) = delete;
hp_owner() : hp(nullptr)
{
for (unsigned i = 0; i < max_hazard_pointers; ++i) {
std::thread::id old_id;
if (hazard_pointers[i].id.compare_exchange_strong(
old_id, std::this_thread::get_id())) {
hp = &hazard_pointers[i];
break;
}
}
std::atomic<void*>& get_pointer()
{
return hp->pointer;
}
~hp_owner()
{
hp->pointer.store(nullptr);
hp->id.store(std::thread::id());
if (!hp) {
throw std::runtime_error("No hazard pointers available");
}
}
std::atomic<void*>& get_pointer() { return hp->pointer; }
~hp_owner()
{
hp->pointer.store(nullptr);
hp->id.store(std::thread::id());
}
};
std::atomic<void*>& get_hazard_pointer_for_current_thread()
std::atomic<void*>&
get_hazard_pointer_for_current_thread()
{
thread_local static hp_owner hazard;
return hazard.get_pointer();
thread_local static hp_owner hazard;
return hazard.get_pointer();
}

View File

@@ -1,51 +1,47 @@
#include <atomic>
template<typename T>
void do_delete(void* p)
template <typename T>
void
do_delete(void* p)
{
delete static_cast<T*>(p);
delete static_cast<T*>(p);
}
struct data_to_reclaim
{
void* data;
std::function<void(void*)> deleter;
data_to_reclaim* next;
template<typename T>
data_to_reclaim(T* p):
data(p),
deleter(&do_delete<T>),
next(0)
{}
~data_to_reclaim()
{
deleter(data);
}
struct data_to_reclaim {
void* data;
std::function<void(void*)> deleter;
data_to_reclaim* next;
template <typename T>
data_to_reclaim(T* p) : data(p), deleter(&do_delete<T>), next(0)
{
}
~data_to_reclaim() { deleter(data); }
};
std::atomic<data_to_reclaim*> nodes_to_reclaim;
void add_to_reclaim_list(data_to_reclaim* node)
void
add_to_reclaim_list(data_to_reclaim* node)
{
node->next=nodes_to_reclaim.load();
while(!nodes_to_reclaim.compare_exchange_weak(node->next,node));
node->next = nodes_to_reclaim.load();
while (!nodes_to_reclaim.compare_exchange_weak(node->next, node))
;
}
template<typename T>
void reclaim_later(T* data)
template <typename T>
void
reclaim_later(T* data)
{
add_to_reclaim_list(new data_to_reclaim(data));
add_to_reclaim_list(new data_to_reclaim(data));
}
void delete_nodes_with_no_hazards()
void
delete_nodes_with_no_hazards()
{
data_to_reclaim* current=nodes_to_reclaim.exchange(nullptr);
while(current)
{
data_to_reclaim* const next=current->next;
if(!outstanding_hazard_pointers_for(current->data))
{
delete current;
}
else
{
add_to_reclaim_list(current);
}
current=next;
data_to_reclaim* current = nodes_to_reclaim.exchange(nullptr);
while (current) {
data_to_reclaim* const next = current->next;
if (!outstanding_hazard_pointers_for(current->data)) {
delete current;
}
else {
add_to_reclaim_list(current);
}
current = next;
}
}

View File

@@ -1,32 +1,30 @@
#include <atomic>
#include <memory>
template<typename T>
class lock_free_stack
{
template <typename T>
class lock_free_stack {
private:
struct node
{
std::shared_ptr<T> data;
std::shared_ptr<node> next;
node(T const& data_):
data(std::make_shared<T>(data_))
{}
};
std::shared_ptr<node> head;
struct node {
std::shared_ptr<T> data;
std::shared_ptr<node> next;
node(T const& data_) : data(std::make_shared<T>(data_)) {}
};
std::shared_ptr<node> head;
public:
void push(T const& data)
{
std::shared_ptr<node> const new_node=std::make_shared<node>(data);
new_node->next=head.load();
while(!std::atomic_compare_exchange_weak(
&head,&new_node->next,new_node));
}
std::shared_ptr<T> pop()
{
std::shared_ptr<node> old_head=std::atomic_load(&head);
while(old_head && !std::atomic_compare_exchange_weak(
&head,&old_head,old_head->next));
return old_head ? old_head->data : std::shared_ptr<T>();
}
void push(T const& data)
{
std::shared_ptr<node> const new_node = std::make_shared<node>(data);
new_node->next = head.load();
while (!std::atomic_compare_exchange_weak(&head, &new_node->next, new_node))
;
}
std::shared_ptr<T> pop()
{
std::shared_ptr<node> old_head = std::atomic_load(&head);
while (old_head &&
!std::atomic_compare_exchange_weak(&head, &old_head, old_head->next))
;
return old_head ? old_head->data : std::shared_ptr<T>();
}
};

View File

@@ -1,102 +1,96 @@
template<typename T>
struct sorter
{
struct chunk_to_sort
{
std::list<T> data;
std::promise<std::list<T> > promise;
};
template <typename T>
struct sorter {
struct chunk_to_sort {
std::list<T> data;
std::promise<std::list<T>> promise;
};
thread_safe_stack<chunk_to_sort> chunks;
std::vector<std::thread> threads;
unsigned const max_thread_count;
std::atomic<bool> end_of_data;
thread_safe_stack<chunk_to_sort> chunks;
std::vector<std::thread> threads;
unsigned const max_thread_count;
std::atomic<bool> end_of_data;
sorter():
max_thread_count(std::thread::hardware_concurrency()-1),
sorter()
: max_thread_count(std::thread::hardware_concurrency() - 1),
end_of_data(false)
{}
{
}
~sorter()
{
end_of_data=true;
for(unsigned i=0;i<threads.size();++i)
{
threads[i].join();
}
~sorter()
{
end_of_data = true;
for (unsigned i = 0; i < threads.size(); ++i) {
threads[i].join();
}
}
void try_sort_chunk()
{
boost::shared_ptr<chunk_to_sort> chunk = chunks.pop();
if (chunk) {
sort_chunk(chunk);
}
}
std::list<T> do_sort(std::list<T>& chunk_data)
{
if (chunk_data.empty()) {
return chunk_data;
}
void try_sort_chunk()
{
boost::shared_ptr<chunk_to_sort > chunk=chunks.pop();
if(chunk)
{
sort_chunk(chunk);
}
std::list<T> result;
result.splice(result.begin(), chunk_data, chunk_data.begin());
T const& partition_val = *result.begin();
typename std::list<T>::iterator divide_point =
std::partition(chunk_data.begin(), chunk_data.end(), [&](T const& val) {
return val < partition_val;
});
chunk_to_sort new_lower_chunk;
new_lower_chunk.data.splice(new_lower_chunk.data.end(),
chunk_data,
chunk_data.begin(),
divide_point);
std::future<std::list<T>> new_lower = new_lower_chunk.promise.get_future();
chunks.push(std::move(new_lower_chunk));
if (threads.size() < max_thread_count) {
threads.push_back(std::thread(&sorter<T>::sort_thread, this));
}
std::list<T> do_sort(std::list<T>& chunk_data)
{
if(chunk_data.empty())
{
return chunk_data;
}
std::list<T> new_higher(do_sort(chunk_data));
std::list<T> result;
result.splice(result.begin(),chunk_data,chunk_data.begin());
T const& partition_val=*result.begin();
typename std::list<T>::iterator divide_point=
std::partition(chunk_data.begin(),chunk_data.end(),
[&](T const& val){return val<partition_val;});
chunk_to_sort new_lower_chunk;
new_lower_chunk.data.splice(new_lower_chunk.data.end(),
chunk_data,chunk_data.begin(),
divide_point);
std::future<std::list<T> > new_lower=
new_lower_chunk.promise.get_future();
chunks.push(std::move(new_lower_chunk));
if(threads.size()<max_thread_count)
{
threads.push_back(std::thread(&sorter<T>::sort_thread,this));
}
std::list<T> new_higher(do_sort(chunk_data));
result.splice(result.end(),new_higher);
while(new_lower.wait_for(std::chrono::seconds(0)) !=
std::future_status::ready)
{
try_sort_chunk();
}
result.splice(result.begin(),new_lower.get());
return result;
result.splice(result.end(), new_higher);
while (new_lower.wait_for(std::chrono::seconds(0)) !=
std::future_status::ready) {
try_sort_chunk();
}
void sort_chunk(boost::shared_ptr<chunk_to_sort > const& chunk)
{
chunk->promise.set_value(do_sort(chunk->data));
}
result.splice(result.begin(), new_lower.get());
return result;
}
void sort_thread()
{
while(!end_of_data)
{
try_sort_chunk();
std::this_thread::yield();
}
void sort_chunk(boost::shared_ptr<chunk_to_sort> const& chunk)
{
chunk->promise.set_value(do_sort(chunk->data));
}
void sort_thread()
{
while (!end_of_data) {
try_sort_chunk();
std::this_thread::yield();
}
}
};
template<typename T>
std::list<T> parallel_quick_sort(std::list<T> input)
template <typename T>
std::list<T>
parallel_quick_sort(std::list<T> input)
{
if(input.empty())
{
return input;
}
sorter<T> s;
return s.do_sort(input);
if (input.empty()) {
return input;
}
sorter<T> s;
return s.do_sort(input);
}

View File

@@ -1,45 +1,45 @@
template<typename Iterator,typename MatchType>
Iterator parallel_find_impl(Iterator first,Iterator last,MatchType match,
std::atomic<bool>& done)
template <typename Iterator, typename MatchType>
Iterator
parallel_find_impl(Iterator first,
Iterator last,
MatchType match,
std::atomic<bool>& done)
{
try
{
unsigned long const length=std::distance(first,last);
unsigned long const min_per_thread=25;
if(length<(2*min_per_thread))
{
for(;(first!=last) && !done.load();++first)
{
if(*first==match)
{
done=true;
return first;
}
}
return last;
}
else
{
Iterator const mid_point=first+(length/2);
std::future<Iterator> async_result=
std::async(&parallel_find_impl<Iterator,MatchType>,
mid_point,last,match,std::ref(done));
Iterator const direct_result=
parallel_find_impl(first,mid_point,match,done);
return (direct_result==mid_point)?
async_result.get():direct_result;
try {
unsigned long const length = std::distance(first, last);
unsigned long const min_per_thread = 25;
if (length < (2 * min_per_thread)) {
for (; (first != last) && !done.load(); ++first) {
if (*first == match) {
done = true;
return first;
}
}
return last;
}
catch(...)
{
done=true;
throw;
else {
Iterator const mid_point = first + (length / 2);
std::future<Iterator> async_result =
std::async(&parallel_find_impl<Iterator, MatchType>,
mid_point,
last,
match,
std::ref(done));
Iterator const direct_result =
parallel_find_impl(first, mid_point, match, done);
return (direct_result == mid_point) ? async_result.get() : direct_result;
}
}
catch (...) {
done = true;
throw;
}
}
template<typename Iterator,typename MatchType>
Iterator parallel_find(Iterator first,Iterator last,MatchType match)
template <typename Iterator, typename MatchType>
Iterator
parallel_find(Iterator first, Iterator last, MatchType match)
{
std::atomic<bool> done(false);
return parallel_find_impl(first,last,match,done);
std::atomic<bool> done(false);
return parallel_find_impl(first, last, match, done);
}

View File

@@ -1,93 +1,83 @@
template<typename Iterator>
void parallel_partial_sum(Iterator first,Iterator last)
template <typename Iterator>
void
parallel_partial_sum(Iterator first, Iterator last)
{
typedef typename Iterator::value_type value_type;
struct process_chunk
typedef typename Iterator::value_type value_type;
struct process_chunk {
void operator()(Iterator begin,
Iterator last,
std::future<value_type>* previous_end_value,
std::promise<value_type>* end_value)
{
void operator()(Iterator begin,Iterator last,
std::future<value_type>* previous_end_value,
std::promise<value_type>* end_value)
{
try
{
Iterator end=last;
++end;
std::partial_sum(begin,end,begin);
if(previous_end_value)
{
value_type& addend=previous_end_value->get();
*last+=addend;
if(end_value)
{
end_value->set_value(*last);
}
std::for_each(begin,last,[addend](value_type& item)
{
item+=addend;
});
}
else if(end_value)
{
end_value->set_value(*last);
}
}
catch(...)
{
if(end_value)
{
end_value->set_exception(std::current_exception());
}
else
{
throw;
}
}
try {
Iterator end = last;
++end;
std::partial_sum(begin, end, begin);
if (previous_end_value) {
value_type& addend = previous_end_value->get();
*last += addend;
if (end_value) {
end_value->set_value(*last);
}
std::for_each(
begin, last, [addend](value_type& item) { item += addend; });
}
};
unsigned long const length=std::distance(first,last);
if(!length)
return last;
unsigned long const min_per_thread=25;
unsigned long const max_threads=
(length+min_per_thread-1)/min_per_thread;
unsigned long const hardware_threads=
std::thread::hardware_concurrency();
unsigned long const num_threads=
std::min(hardware_threads!=0?hardware_threads:2,max_threads);
unsigned long const block_size=length/num_threads;
typedef typename Iterator::value_type value_type;
std::vector<std::thread> threads(num_threads-1);
std::vector<std::promise<value_type> >
end_values(num_threads-1);
std::vector<std::future<value_type> >
previous_end_values;
previous_end_values.reserve(num_threads-1);
join_threads joiner(threads);
Iterator block_start=first;
for(unsigned long i=0;i<(num_threads-1);++i)
{
Iterator block_last=block_start;
std::advance(block_last,block_size-1);
threads[i]=std::thread(process_chunk(),
block_start,block_last,
(i!=0)?&previous_end_values[i-1]:0,
&end_values[i]);
block_start=block_last;
++block_start;
previous_end_values.push_back(end_values[i].get_future());
else if (end_value) {
end_value->set_value(*last);
}
}
catch (...) {
if (end_value) {
end_value->set_exception(std::current_exception());
}
else {
throw;
}
}
}
Iterator final_element=block_start;
std::advance(final_element,std::distance(block_start,last)-1);
process_chunk()(block_start,final_element,
(num_threads>1)?&previous_end_values.back():0,
0);
};
unsigned long const length = std::distance(first, last);
if (!length)
return last;
unsigned long const min_per_thread = 25;
unsigned long const max_threads =
(length + min_per_thread - 1) / min_per_thread;
unsigned long const hardware_threads = std::thread::hardware_concurrency();
unsigned long const num_threads =
std::min(hardware_threads != 0 ? hardware_threads : 2, max_threads);
unsigned long const block_size = length / num_threads;
typedef typename Iterator::value_type value_type;
std::vector<std::thread> threads(num_threads - 1);
std::vector<std::promise<value_type>> end_values(num_threads - 1);
std::vector<std::future<value_type>> previous_end_values;
previous_end_values.reserve(num_threads - 1);
join_threads joiner(threads);
Iterator block_start = first;
for (unsigned long i = 0; i < (num_threads - 1); ++i) {
Iterator block_last = block_start;
std::advance(block_last, block_size - 1);
threads[i] = std::thread(process_chunk(),
block_start,
block_last,
(i != 0) ? &previous_end_values[i - 1] : 0,
&end_values[i]);
block_start = block_last;
++block_start;
previous_end_values.push_back(end_values[i].get_future());
}
Iterator final_element = block_start;
std::advance(final_element, std::distance(block_start, last) - 1);
process_chunk()(block_start,
final_element,
(num_threads > 1) ? &previous_end_values.back() : 0,
0);
}

View File

@@ -1,24 +1,22 @@
class barrier
{
unsigned const count;
std::atomic<unsigned> spaces;
std::atomic<unsigned> generation;
class barrier {
unsigned const count;
std::atomic<unsigned> spaces;
std::atomic<unsigned> generation;
public:
explicit barrier(unsigned count_):
count(count_),spaces(count),generation(0)
{}
void wait()
{
unsigned const my_generation=generation;
if(!--spaces)
{
spaces=count;
++generation;
}
else
{
while(generation==my_generation)
std::this_thread::yield();
}
explicit barrier(unsigned count_)
: count(count_), spaces(count), generation(0)
{
}
void wait()
{
unsigned const my_generation = generation;
if (!--spaces) {
spaces = count;
++generation;
}
else {
while (generation == my_generation) std::this_thread::yield();
}
}
};

View File

@@ -2,97 +2,84 @@
#include <thread>
#include <vector>
struct join_threads
{
join_threads(std::vector<std::thread>&)
{}
};
struct barrier
{
std::atomic<unsigned> count;
std::atomic<unsigned> spaces;
std::atomic<unsigned> generation;
barrier(unsigned count_):
count(count_),spaces(count_),generation(0)
{}
void wait()
{
unsigned const gen=generation.load();
if(!--spaces)
{
spaces=count.load();
++generation;
}
else
{
while(generation.load()==gen)
{
std::this_thread::yield();
}
}
}
void done_waiting()
{
--count;
if(!--spaces)
{
spaces=count.load();
++generation;
}
}
struct join_threads {
join_threads(std::vector<std::thread>&) {}
};
template<typename Iterator>
void parallel_partial_sum(Iterator first,Iterator last)
{
typedef typename Iterator::value_type value_type;
struct process_element
{
void operator()(Iterator first,Iterator last,
std::vector<value_type>& buffer,
unsigned i,barrier& b)
{
value_type& ith_element=*(first+i);
bool update_source=false;
for(unsigned step=0,stride=1;stride<=i;++step,stride*=2)
{
value_type const& source=(step%2)?
buffer[i]:ith_element;
value_type& dest=(step%2)?
ith_element:buffer[i];
value_type const& addend=(step%2)?
buffer[i-stride]:*(first+i-stride);
dest=source+addend;
update_source=!(step%2);
b.wait();
}
if(update_source)
{
ith_element=buffer[i];
}
b.done_waiting();
}
};
unsigned long const length=std::distance(first,last);
if(length<=1)
return;
std::vector<value_type> buffer(length);
barrier b(length);
std::vector<std::thread> threads(length-1);
join_threads joiner(threads);
Iterator block_start=first;
for(unsigned long i=0;i<(length-1);++i)
{
threads[i]=std::thread(process_element(),first,last,
std::ref(buffer),i,std::ref(b));
struct barrier {
std::atomic<unsigned> count;
std::atomic<unsigned> spaces;
std::atomic<unsigned> generation;
barrier(unsigned count_) : count(count_), spaces(count_), generation(0) {}
void wait()
{
unsigned const gen = generation.load();
if (!--spaces) {
spaces = count.load();
++generation;
}
process_element()(first,last,buffer,length-1,b);
else {
while (generation.load() == gen) {
std::this_thread::yield();
}
}
}
void done_waiting()
{
--count;
if (!--spaces) {
spaces = count.load();
++generation;
}
}
};
template <typename Iterator>
void
parallel_partial_sum(Iterator first, Iterator last)
{
typedef typename Iterator::value_type value_type;
struct process_element {
void operator()(Iterator first,
Iterator last,
std::vector<value_type>& buffer,
unsigned i,
barrier& b)
{
value_type& ith_element = *(first + i);
bool update_source = false;
for (unsigned step = 0, stride = 1; stride <= i; ++step, stride *= 2) {
value_type const& source = (step % 2) ? buffer[i] : ith_element;
value_type& dest = (step % 2) ? ith_element : buffer[i];
value_type const& addend =
(step % 2) ? buffer[i - stride] : *(first + i - stride);
dest = source + addend;
update_source = !(step % 2);
b.wait();
}
if (update_source) {
ith_element = buffer[i];
}
b.done_waiting();
}
};
unsigned long const length = std::distance(first, last);
if (length <= 1)
return;
std::vector<value_type> buffer(length);
barrier b(length);
std::vector<std::thread> threads(length - 1);
join_threads joiner(threads);
Iterator block_start = first;
for (unsigned long i = 0; i < (length - 1); ++i) {
threads[i] = std::thread(
process_element(), first, last, std::ref(buffer), i, std::ref(b));
}
process_element()(first, last, buffer, length - 1, b);
}

View File

@@ -1,49 +1,48 @@
template<typename Iterator,typename T>
struct accumulate_block
{
void operator()(Iterator first,Iterator last,T& result)
{
result=std::accumulate(first,last,result);
}
template <typename Iterator, typename T>
struct accumulate_block {
void operator()(Iterator first, Iterator last, T& result)
{
result = std::accumulate(first, last, result);
}
};
template<typename Iterator,typename T>
T parallel_accumulate(Iterator first,Iterator last,T init)
template <typename Iterator, typename T>
T
parallel_accumulate(Iterator first, Iterator last, T init)
{
unsigned long const length=std::distance(first,last);
unsigned long const length = std::distance(first, last);
if(!length)
return init;
if (!length)
return init;
unsigned long const min_per_thread=25;
unsigned long const max_threads=
(length+min_per_thread-1)/min_per_thread;
unsigned long const min_per_thread = 25;
unsigned long const max_threads =
(length + min_per_thread - 1) / min_per_thread;
unsigned long const hardware_threads=
std::thread::hardware_concurrency();
unsigned long const hardware_threads = std::thread::hardware_concurrency();
unsigned long const num_threads=
std::min(hardware_threads!=0?hardware_threads:2,max_threads);
unsigned long const num_threads =
std::min(hardware_threads != 0 ? hardware_threads : 2, max_threads);
unsigned long const block_size=length/num_threads;
unsigned long const block_size = length / num_threads;
std::vector<T> results(num_threads);
std::vector<std::thread> threads(num_threads-1);
std::vector<T> results(num_threads);
std::vector<std::thread> threads(num_threads - 1);
Iterator block_start=first;
for(unsigned long i=0;i<(num_threads-1);++i)
{
Iterator block_end=block_start;
std::advance(block_end,block_size);
threads[i]=std::thread(
accumulate_block<Iterator,T>(),
block_start,block_end,std::ref(results[i]));
block_start=block_end;
}
accumulate_block()(block_start,last,results[num_threads-1]);
Iterator block_start = first;
for (unsigned long i = 0; i < (num_threads - 1); ++i) {
Iterator block_end = block_start;
std::advance(block_end, block_size);
threads[i] = std::thread(accumulate_block<Iterator, T>(),
block_start,
block_end,
std::ref(results[i]));
block_start = block_end;
}
accumulate_block()(block_start, last, results[num_threads - 1]);
std::for_each(threads.begin(),threads.end(),
std::mem_fn(&std::thread::join));
std::for_each(
threads.begin(), threads.end(), std::mem_fn(&std::thread::join));
return std::accumulate(results.begin(),results.end(),init);
return std::accumulate(results.begin(), results.end(), init);
}

View File

@@ -1,56 +1,53 @@
template<typename Iterator,typename T>
struct accumulate_block
{
T operator()(Iterator first,Iterator last)
{
return std::accumulate(first,last,T());
}
template <typename Iterator, typename T>
struct accumulate_block {
T operator()(Iterator first, Iterator last)
{
return std::accumulate(first, last, T());
}
};
template<typename Iterator,typename T>
T parallel_accumulate(Iterator first,Iterator last,T init)
template <typename Iterator, typename T>
T
parallel_accumulate(Iterator first, Iterator last, T init)
{
unsigned long const length=std::distance(first,last);
unsigned long const length = std::distance(first, last);
if(!length)
return init;
if (!length)
return init;
unsigned long const min_per_thread=25;
unsigned long const max_threads=
(length+min_per_thread-1)/min_per_thread;
unsigned long const min_per_thread = 25;
unsigned long const max_threads =
(length + min_per_thread - 1) / min_per_thread;
unsigned long const hardware_threads=
std::thread::hardware_concurrency();
unsigned long const hardware_threads = std::thread::hardware_concurrency();
unsigned long const num_threads=
std::min(hardware_threads!=0?hardware_threads:2,max_threads);
unsigned long const num_threads =
std::min(hardware_threads != 0 ? hardware_threads : 2, max_threads);
unsigned long const block_size=length/num_threads;
unsigned long const block_size = length / num_threads;
std::vector<std::future<T> > futures(num_threads-1);
std::vector<std::thread> threads(num_threads-1);
std::vector<std::future<T>> futures(num_threads - 1);
std::vector<std::thread> threads(num_threads - 1);
Iterator block_start=first;
for(unsigned long i=0;i<(num_threads-1);++i)
{
Iterator block_end=block_start;
std::advance(block_end,block_size);
std::packaged_task<T(Iterator,Iterator)> task(
accumulate_block<Iterator,T>());
futures[i]=task.get_future();
threads[i]=std::thread(std::move(task),block_start,block_end);
block_start=block_end;
}
T last_result=accumulate_block()(block_start,last);
Iterator block_start = first;
for (unsigned long i = 0; i < (num_threads - 1); ++i) {
Iterator block_end = block_start;
std::advance(block_end, block_size);
std::packaged_task<T(Iterator, Iterator)> task(
accumulate_block<Iterator, T>());
futures[i] = task.get_future();
threads[i] = std::thread(std::move(task), block_start, block_end);
block_start = block_end;
}
T last_result = accumulate_block()(block_start, last);
std::for_each(threads.begin(),threads.end(),
std::mem_fn(&std::thread::join));
std::for_each(
threads.begin(), threads.end(), std::mem_fn(&std::thread::join));
T result=init;
for(unsigned long i=0;i<(num_threads-1);++i)
{
result+=futures[i].get();
}
result += last_result;
return result;
T result = init;
for (unsigned long i = 0; i < (num_threads - 1); ++i) {
result += futures[i].get();
}
result += last_result;
return result;
}

View File

@@ -1,44 +1,42 @@
template<typename Iterator,typename T>
T parallel_accumulate(Iterator first,Iterator last,T init)
template <typename Iterator, typename T>
T
parallel_accumulate(Iterator first, Iterator last, T init)
{
unsigned long const length=std::distance(first,last);
unsigned long const length = std::distance(first, last);
if(!length)
return init;
if (!length)
return init;
unsigned long const min_per_thread=25;
unsigned long const max_threads=
(length+min_per_thread-1)/min_per_thread;
unsigned long const min_per_thread = 25;
unsigned long const max_threads =
(length + min_per_thread - 1) / min_per_thread;
unsigned long const hardware_threads=
std::thread::hardware_concurrency();
unsigned long const hardware_threads = std::thread::hardware_concurrency();
unsigned long const num_threads=
std::min(hardware_threads!=0?hardware_threads:2,max_threads);
unsigned long const num_threads =
std::min(hardware_threads != 0 ? hardware_threads : 2, max_threads);
unsigned long const block_size=length/num_threads;
unsigned long const block_size = length / num_threads;
std::vector<std::future<T> > futures(num_threads-1);
std::vector<std::thread> threads(num_threads-1);
join_threads joiner(threads);
std::vector<std::future<T>> futures(num_threads - 1);
std::vector<std::thread> threads(num_threads - 1);
join_threads joiner(threads);
Iterator block_start=first;
for(unsigned long i=0;i<(num_threads-1);++i)
{
Iterator block_end=block_start;
std::advance(block_end,block_size);
std::packaged_task<T(Iterator,Iterator)> task(
accumulate_block<Iterator,T>());
futures[i]=task.get_future();
threads[i]=std::thread(std::move(task),block_start,block_end);
block_start=block_end;
}
T last_result=accumulate_block()(block_start,last);
T result=init;
for(unsigned long i=0;i<(num_threads-1);++i)
{
result+=futures[i].get();
}
result += last_result;
return result;
Iterator block_start = first;
for (unsigned long i = 0; i < (num_threads - 1); ++i) {
Iterator block_end = block_start;
std::advance(block_end, block_size);
std::packaged_task<T(Iterator, Iterator)> task(
accumulate_block<Iterator, T>());
futures[i] = task.get_future();
threads[i] = std::thread(std::move(task), block_start, block_end);
block_start = block_end;
}
T last_result = accumulate_block()(block_start, last);
T result = init;
for (unsigned long i = 0; i < (num_threads - 1); ++i) {
result += futures[i].get();
}
result += last_result;
return result;
}

View File

@@ -1,20 +1,18 @@
template<typename Iterator,typename T>
T parallel_accumulate(Iterator first,Iterator last,T init)
template <typename Iterator, typename T>
T
parallel_accumulate(Iterator first, Iterator last, T init)
{
unsigned long const length=std::distance(first,last);
unsigned long const max_chunk_size=25;
if(length<=max_chunk_size)
{
return std::accumulate(first,last,init);
}
else
{
Iterator mid_point=first;
std::advance(mid_point,length/2);
std::future<T> first_half_result=
std::async(parallel_accumulate<Iterator,T>,
first,mid_point,init);
T second_half_result=parallel_accumulate(mid_point,last,T());
return first_half_result.get()+second_half_result;
}
unsigned long const length = std::distance(first, last);
unsigned long const max_chunk_size = 25;
if (length <= max_chunk_size) {
return std::accumulate(first, last, init);
}
else {
Iterator mid_point = first;
std::advance(mid_point, length / 2);
std::future<T> first_half_result =
std::async(parallel_accumulate<Iterator, T>, first, mid_point, init);
T second_half_result = parallel_accumulate(mid_point, last, T());
return first_half_result.get() + second_half_result;
}
}

View File

@@ -1,50 +1,48 @@
std::thread task_thread;
std::atomic<bool> task_cancelled(false);
void gui_thread()
void
gui_thread()
{
while(true)
{
event_data event=get_event();
if(event.type==quit)
break;
process(event);
}
while (true) {
event_data event = get_event();
if (event.type == quit)
break;
process(event);
}
}
void task()
void
task()
{
while(!task_complete() && !task_cancelled)
{
do_next_operation();
}
if(task_cancelled)
{
perform_cleanup();
}
else
{
post_gui_event(task_complete);
}
while (!task_complete() && !task_cancelled) {
do_next_operation();
}
if (task_cancelled) {
perform_cleanup();
}
else {
post_gui_event(task_complete);
}
}
void process(event_data const& event)
void
process(event_data const& event)
{
switch(event.type)
{
case start_task:
task_cancelled=false;
task_thread=std::thread(task);
break;
case stop_task:
task_cancelled=true;
task_thread.join();
break;
case task_complete:
task_thread.join();
display_results();
break;
default:
//...
}
switch (event.type) {
case start_task:
task_cancelled = false;
task_thread = std::thread(task);
break;
case stop_task:
task_cancelled = true;
task_thread.join();
break;
case task_complete:
task_thread.join();
display_results();
break;
default:
//...
}
}

View File

@@ -1,44 +1,39 @@
template<typename Iterator,typename Func>
void parallel_for_each(Iterator first,Iterator last,Func f)
template <typename Iterator, typename Func>
void
parallel_for_each(Iterator first, Iterator last, Func f)
{
unsigned long const length=std::distance(first,last);
unsigned long const length = std::distance(first, last);
if(!length)
return;
if (!length)
return;
unsigned long const min_per_thread=25;
unsigned long const max_threads=
(length+min_per_thread-1)/min_per_thread;
unsigned long const min_per_thread = 25;
unsigned long const max_threads =
(length + min_per_thread - 1) / min_per_thread;
unsigned long const hardware_threads=
std::thread::hardware_concurrency();
unsigned long const hardware_threads = std::thread::hardware_concurrency();
unsigned long const num_threads=
std::min(hardware_threads!=0?hardware_threads:2,max_threads);
unsigned long const num_threads =
std::min(hardware_threads != 0 ? hardware_threads : 2, max_threads);
unsigned long const block_size=length/num_threads;
unsigned long const block_size = length / num_threads;
std::vector<std::future<void> > futures(num_threads-1);
std::vector<std::thread> threads(num_threads-1);
join_threads joiner(threads);
std::vector<std::future<void>> futures(num_threads - 1);
std::vector<std::thread> threads(num_threads - 1);
join_threads joiner(threads);
Iterator block_start=first;
for(unsigned long i=0;i<(num_threads-1);++i)
{
Iterator block_end=block_start;
std::advance(block_end,block_size);
std::packaged_task<void(void)> task(
[=]()
{
std::for_each(block_start,block_end,f);
});
futures[i]=task.get_future();
threads[i]=std::thread(std::move(task));
block_start=block_end;
}
std::for_each(block_start,last,f);
for(unsigned long i=0;i<(num_threads-1);++i)
{
futures[i].get();
}
Iterator block_start = first;
for (unsigned long i = 0; i < (num_threads - 1); ++i) {
Iterator block_end = block_start;
std::advance(block_end, block_size);
std::packaged_task<void(void)> task(
[=]() { std::for_each(block_start, block_end, f); });
futures[i] = task.get_future();
threads[i] = std::thread(std::move(task));
block_start = block_end;
}
std::for_each(block_start, last, f);
for (unsigned long i = 0; i < (num_threads - 1); ++i) {
futures[i].get();
}
}

View File

@@ -1,24 +1,22 @@
template<typename Iterator,typename Func>
void parallel_for_each(Iterator first,Iterator last,Func f)
template <typename Iterator, typename Func>
void
parallel_for_each(Iterator first, Iterator last, Func f)
{
unsigned long const length=std::distance(first,last);
unsigned long const length = std::distance(first, last);
if(!length)
return;
if (!length)
return;
unsigned long const min_per_thread=25;
unsigned long const min_per_thread = 25;
if(length<(2*min_per_thread))
{
std::for_each(first,last,f);
}
else
{
Iterator const mid_point=first+length/2;
std::future<void> first_half=
std::async(&parallel_for_each<Iterator,Func>,
first,mid_point,f);
parallel_for_each(mid_point,last,f);
first_half.get();
}
if (length < (2 * min_per_thread)) {
std::for_each(first, last, f);
}
else {
Iterator const mid_point = first + length / 2;
std::future<void> first_half =
std::async(&parallel_for_each<Iterator, Func>, first, mid_point, f);
parallel_for_each(mid_point, last, f);
first_half.get();
}
}

View File

@@ -1,76 +1,68 @@
template<typename Iterator,typename MatchType>
Iterator parallel_find(Iterator first,Iterator last,MatchType match)
template <typename Iterator, typename MatchType>
Iterator
parallel_find(Iterator first, Iterator last, MatchType match)
{
struct find_element
struct find_element {
void operator()(Iterator begin,
Iterator end,
MatchType match,
std::promise<Iterator>* result,
std::atomic<bool>* done_flag)
{
void operator()(Iterator begin,Iterator end,
MatchType match,
std::promise<Iterator>* result,
std::atomic<bool>* done_flag)
{
try
{
for(;(begin!=end) && !done_flag->load();++begin)
{
if(*begin==match)
{
result->set_value(begin);
done_flag->store(true);
return;
}
}
}
catch(...)
{
try
{
result->set_exception(std::current_exception());
done_flag->store(true);
}
catch(...)
{}
}
try {
for (; (begin != end) && !done_flag->load(); ++begin) {
if (*begin == match) {
result->set_value(begin);
done_flag->store(true);
return;
}
}
};
unsigned long const length=std::distance(first,last);
if(!length)
return last;
unsigned long const min_per_thread=25;
unsigned long const max_threads=
(length+min_per_thread-1)/min_per_thread;
unsigned long const hardware_threads=
std::thread::hardware_concurrency();
unsigned long const num_threads=
std::min(hardware_threads!=0?hardware_threads:2,max_threads);
unsigned long const block_size=length/num_threads;
std::promise<Iterator> result;
std::atomic<bool> done_flag(false);
std::vector<std::thread> threads(num_threads-1);
{
join_threads joiner(threads);
Iterator block_start=first;
for(unsigned long i=0;i<(num_threads-1);++i)
{
Iterator block_end=block_start;
std::advance(block_end,block_size);
threads[i]=std::thread(find_element(),
block_start,block_end,match,
&result,&done_flag);
block_start=block_end;
}
catch (...) {
try {
result->set_exception(std::current_exception());
done_flag->store(true);
}
find_element()(block_start,last,match,&result,&done_flag);
catch (...) {
}
}
}
if(!done_flag.load())
{
return last;
};
unsigned long const length = std::distance(first, last);
if (!length)
return last;
unsigned long const min_per_thread = 25;
unsigned long const max_threads =
(length + min_per_thread - 1) / min_per_thread;
unsigned long const hardware_threads = std::thread::hardware_concurrency();
unsigned long const num_threads =
std::min(hardware_threads != 0 ? hardware_threads : 2, max_threads);
unsigned long const block_size = length / num_threads;
std::promise<Iterator> result;
std::atomic<bool> done_flag(false);
std::vector<std::thread> threads(num_threads - 1);
{
join_threads joiner(threads);
Iterator block_start = first;
for (unsigned long i = 0; i < (num_threads - 1); ++i) {
Iterator block_end = block_start;
std::advance(block_end, block_size);
threads[i] = std::thread(
find_element(), block_start, block_end, match, &result, &done_flag);
block_start = block_end;
}
return result.get_future().get();
find_element()(block_start, last, match, &result, &done_flag);
}
if (!done_flag.load()) {
return last;
}
return result.get_future().get();
}

View File

@@ -1,53 +1,42 @@
class thread_pool
{
std::atomic_bool done;
thread_safe_queue<std::function<void()> > work_queue;
std::vector<std::thread> threads;
join_threads joiner;
class thread_pool {
std::atomic_bool done;
thread_safe_queue<std::function<void()>> work_queue;
std::vector<std::thread> threads;
join_threads joiner;
void worker_thread()
{
while(!done)
{
std::function<void()> task;
if(work_queue.try_pop(task))
{
task();
}
else
{
std::this_thread::yield();
}
}
void worker_thread()
{
while (!done) {
std::function<void()> task;
if (work_queue.try_pop(task)) {
task();
}
else {
std::this_thread::yield();
}
}
}
public:
thread_pool():
done(false),joiner(threads)
{
unsigned const thread_count=std::thread::hardware_concurrency();
try
{
for(unsigned i=0;i<thread_count;++i)
{
threads.push_back(
std::thread(&thread_pool::worker_thread,this));
}
}
catch(...)
{
done=true;
throw;
}
thread_pool() : done(false), joiner(threads)
{
unsigned const thread_count = std::thread::hardware_concurrency();
try {
for (unsigned i = 0; i < thread_count; ++i) {
threads.push_back(std::thread(&thread_pool::worker_thread, this));
}
}
catch (...) {
done = true;
throw;
}
}
~thread_pool()
{
done=true;
}
~thread_pool() { done = true; }
template<typename FunctionType>
void submit(FunctionType f)
{
work_queue.push(std::function<void()>(f));
}
template <typename FunctionType>
void submit(FunctionType f)
{
work_queue.push(std::function<void()>(f));
}
};

Some files were not shown because too many files have changed in this diff Show More