Skip to content

Commit 853550b

Browse files
committed
Merge pull request #590 from glynos/thread_group
Thread group
2 parents 6bff172 + a7d48af commit 853550b

File tree

9 files changed

+208
-132
lines changed

9 files changed

+208
-132
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@
77
[submodule "libs/network/doc/_ext/breathe"]
88
path = libs/network/doc/_ext/breathe
99
url = https://github.com/michaeljones/breathe.git
10+
[submodule "deps/cxxopts"]
11+
path = deps/cxxopts
12+
url = https://github.com/jarro2783/cxxopts.git

CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ add_definitions(-DBOOST_TEST_DYN_LINK)
4646
# Always use multi-threaded Boost libraries.
4747
set(Boost_USE_MULTI_THREADED ON)
4848

49-
find_package(Boost 1.57.0
50-
REQUIRED system thread filesystem program_options)
49+
find_package(Boost 1.57.0 REQUIRED system filesystem)
5150

5251
if (CPP-NETLIB_ENABLE_HTTPS)
5352
find_package( OpenSSL )

boost/network/utils/thread_group.hpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright (c) Glyn Matthews 2016.
2+
// (C) Copyright 2007-9 Anthony Williams
3+
// Distributed under the Boost Software License, Version 1.0.
4+
// (See accompanying file LICENSE_1_0.txt or copy at
5+
// http://www.boost.org/LICENSE_1_0.txt)
6+
7+
#ifndef BOOST_NETWORK_UTILS_THREAD_GROUP_INC
8+
#define BOOST_NETWORK_UTILS_THREAD_GROUP_INC
9+
10+
#include <thread>
11+
#include <mutex>
12+
#include <memory>
13+
#include <list>
14+
#include <algorithm>
15+
16+
namespace boost {
17+
namespace network {
18+
namespace utils {
19+
class thread_group {
20+
private:
21+
thread_group(thread_group const&);
22+
thread_group& operator=(thread_group const&);
23+
24+
public:
25+
thread_group() {}
26+
~thread_group() {}
27+
28+
template <typename F>
29+
std::thread* create_thread(F threadfunc) {
30+
std::lock_guard<std::mutex> guard(m);
31+
std::unique_ptr<std::thread> new_thread(new std::thread(threadfunc));
32+
threads.push_back(std::move(new_thread));
33+
return threads.back().get();
34+
}
35+
36+
void add_thread(std::thread* thrd) {
37+
if (thrd) {
38+
std::lock_guard<std::mutex> guard(m);
39+
threads.push_back(std::unique_ptr<std::thread>(thrd));
40+
}
41+
}
42+
43+
void remove_thread(std::thread* thrd) {
44+
std::lock_guard<std::mutex> guard(m);
45+
auto const it = std::find_if(threads.begin(), threads.end(),
46+
[&thrd] (std::unique_ptr<std::thread> &arg) {
47+
return arg.get() == thrd;
48+
});
49+
if (it != threads.end()) {
50+
threads.erase(it);
51+
}
52+
}
53+
54+
void join_all() {
55+
std::unique_lock<std::mutex> guard(m);
56+
57+
for (auto &thread : threads) {
58+
if (thread->joinable()) {
59+
thread->join();
60+
}
61+
}
62+
}
63+
64+
size_t size() const {
65+
std::unique_lock<std::mutex> guard(m);
66+
return threads.size();
67+
}
68+
69+
private:
70+
std::list<std::unique_ptr<std::thread>> threads;
71+
mutable std::mutex m;
72+
};
73+
74+
} // namespace utils
75+
} // namespace network
76+
} // namespace boost
77+
78+
#endif // BOOST_NETWORK_UTILS_THREAD_GROUP_INC

boost/network/utils/thread_pool.hpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,22 @@
66
// (See accompanying file LICENSE_1_0.txt or copy at
77
// http://www.boost.org/LICENSE_1_0.txt)
88

9+
#include <cstddef>
910
#include <memory>
1011
#include <functional>
1112
#include <boost/asio/io_service.hpp>
1213
#include <boost/function.hpp>
1314
#include <boost/network/tags.hpp>
1415
#include <boost/scope_exit.hpp>
15-
#include <boost/thread/thread.hpp>
16-
#include <cstddef>
16+
//#include <boost/thread/thread.hpp>
17+
#include <boost/network/utils/thread_group.hpp>
1718

1819
namespace boost {
1920
namespace network {
2021
namespace utils {
2122

2223
typedef std::shared_ptr<boost::asio::io_service> io_service_ptr;
23-
typedef std::shared_ptr<boost::thread_group> worker_threads_ptr;
24+
typedef std::shared_ptr<utils::thread_group> worker_threads_ptr;
2425
typedef std::shared_ptr<boost::asio::io_service::work> sentinel_ptr;
2526

2627
template <class Tag>
@@ -46,7 +47,7 @@ struct basic_thread_pool {
4647
sentinel_.reset();
4748
io_service_.reset();
4849
if (worker_threads_.get()) {
49-
worker_threads_->interrupt_all();
50+
// worker_threads_->interrupt_all();
5051
worker_threads_->join_all();
5152
}
5253
worker_threads_.reset();
@@ -59,7 +60,7 @@ struct basic_thread_pool {
5960
}
6061

6162
if (!worker_threads_.get()) {
62-
worker_threads_.reset(new boost::thread_group);
63+
worker_threads_.reset(new utils::thread_group);
6364
}
6465

6566
if (!sentinel_.get()) {

deps/cxxopts

Submodule cxxopts added at aec97a6

libs/network/example/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# http://www.boost.org/LICENSE_1_0.txt)
55

66
include_directories(${CPP-NETLIB_SOURCE_DIR})
7+
include_directories(${CPP-NETLIB_SOURCE_DIR}/deps/cxxopts/src)
78
if (OPENSSL_FOUND)
89
include_directories(${OPENSSL_INCLUDE_DIR})
910
endif (OPENSSL_FOUND)

libs/network/example/http/fileserver.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
// http://www.boost.org/LICENSE_1_0.txt)
55

66
#include <memory>
7+
#include <thread>
78
#include <boost/network/include/http/server.hpp>
8-
#include <boost/thread.hpp>
99
#include <sys/mman.h>
1010
#include <sys/types.h>
1111
#include <sys/stat.h>
@@ -28,7 +28,7 @@ struct file_cache {
2828
std::string doc_root_;
2929
region_map regions;
3030
meta_map file_headers;
31-
boost::shared_mutex cache_mutex;
31+
std::mutex cache_mutex;
3232

3333
explicit file_cache(std::string doc_root) : doc_root_(std::move(doc_root)) {}
3434

@@ -39,12 +39,12 @@ struct file_cache {
3939
}
4040

4141
bool has(std::string const &path) {
42-
boost::shared_lock<boost::shared_mutex> lock(cache_mutex);
42+
std::unique_lock<std::mutex> lock(cache_mutex);
4343
return regions.find(doc_root_ + path) != regions.end();
4444
}
4545

4646
bool add(std::string const &path) {
47-
boost::upgrade_lock<boost::shared_mutex> lock(cache_mutex);
47+
std::unique_lock<std::mutex> lock(cache_mutex);
4848
std::string real_filename = doc_root_ + path;
4949
if (regions.find(real_filename) != regions.end()) return true;
5050
#ifdef O_NOATIME
@@ -60,7 +60,6 @@ struct file_cache {
6060
return false;
6161
}
6262

63-
boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock);
6463
regions.insert(std::make_pair(real_filename, std::make_pair(region, size)));
6564
static server::response_header common_headers[] = {
6665
{"Connection", "close"}, {"Content-Type", "x-application/octet-stream"},
@@ -73,7 +72,7 @@ struct file_cache {
7372
}
7473

7574
std::pair<void *, std::size_t> get(std::string const &path) {
76-
boost::shared_lock<boost::shared_mutex> lock(cache_mutex);
75+
std::unique_lock<std::mutex> lock(cache_mutex);
7776
region_map::const_iterator region = regions.find(doc_root_ + path);
7877
if (region != regions.end())
7978
return region->second;
@@ -83,14 +82,12 @@ struct file_cache {
8382

8483
boost::iterator_range<std::vector<server::response_header>::iterator> meta(
8584
std::string const &path) {
86-
boost::shared_lock<boost::shared_mutex> lock(cache_mutex);
85+
std::unique_lock<std::mutex> lock(cache_mutex);
8786
static std::vector<server::response_header> empty_vector;
8887
auto headers = file_headers.find(doc_root_ + path);
8988
if (headers != file_headers.end()) {
90-
auto begin = headers->second
91-
.begin(),
92-
end =
93-
headers->second.end();
89+
auto begin = headers->second.begin(),
90+
end = headers->second.end();
9491
return boost::make_iterator_range(begin, end);
9592
} else
9693
return boost::make_iterator_range(empty_vector);

0 commit comments

Comments
 (0)