Skip to content

Commit ddf1765

Browse files
committed
Value Semantics for request_storage_base.
Here we make sure that copies of types deriving from request_storage_base will properly copy the data (not copy-on-write) that is in the buffers of the original object.
1 parent 43f56f3 commit ddf1765

File tree

5 files changed

+53
-12
lines changed

5 files changed

+53
-12
lines changed

boost/network/protocol/http/request/request.hpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,6 @@ inline void swap(request &l, request &r) {
8888

8989
} // namespace boost
9090

91-
#ifdef BOOST_NETWORK_NO_LIB
92-
#include <boost/network/protocol/http/request/request.ipp>
93-
#endif
94-
9591
#include <boost/network/message/modifiers.hpp>
9692
#include <boost/network/message/wrappers.hpp>
9793
#include <boost/network/message/directives.hpp>

boost/network/protocol/http/request/request_base.hpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ struct request_storage_base_pimpl;
2626
struct request_storage_base {
2727
protected:
2828
request_storage_base(size_t chunk_size = BOOST_NETWORK_BUFFER_CHUNK);
29+
request_storage_base(request_storage_base const &other);
2930
virtual void append(char const *data, size_t size);
3031
virtual size_t read(char *destination, size_t offset, size_t size) const;
3132
virtual void flatten(std::string &destination) const;
@@ -62,8 +63,4 @@ struct request_base : message_base, request_storage_base {
6263

6364
} /* boost */
6465

65-
#ifdef BOOST_NETWORK_NO_LIB
66-
#include <boost/network/protocol/http/request/request_base.ipp>
67-
#endif
68-
6966
#endif /* BOOST_NETWORK_PROTOCOL_HTTP_REQUEST_BASE_HPP_20111008 */

boost/network/protocol/http/request/request_base.ipp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,31 @@ request_base::~request_base() {
1818
}
1919

2020
struct request_storage_base_pimpl {
21-
request_storage_base_pimpl(size_t chunk_size);
21+
explicit request_storage_base_pimpl(size_t chunk_size);
22+
request_storage_base_pimpl *clone() const;
2223
void append(char const *data, size_t size);
2324
size_t read(char *destination, size_t offset, size_t size) const;
2425
void flatten(std::string &destination) const;
2526
void clear();
26-
request_storage_base_pimpl clone() const;
2727
~request_storage_base_pimpl();
2828

2929
private:
3030
size_t chunk_size_;
3131
typedef std::vector<std::pair<char *, size_t> > chunks_vector;
3232
chunks_vector chunks_;
3333
mutex chunk_mutex;
34+
35+
request_storage_base_pimpl(request_storage_base_pimpl const &other);
3436
};
3537

3638
request_storage_base::request_storage_base(size_t chunk_size)
3739
: pimpl_(new (std::nothrow) request_storage_base_pimpl(chunk_size))
3840
{}
3941

42+
request_storage_base::request_storage_base(request_storage_base const &other)
43+
: pimpl_(other.pimpl_->clone())
44+
{}
45+
4046
request_storage_base::~request_storage_base() {
4147
delete pimpl_;
4248
}
@@ -64,6 +70,25 @@ request_storage_base_pimpl::request_storage_base_pimpl(size_t chunk_size)
6470
// do nothing here.
6571
}
6672

73+
request_storage_base_pimpl::request_storage_base_pimpl(request_storage_base_pimpl const &other)
74+
: chunk_size_(other.chunk_size_)
75+
, chunks_(0) {
76+
chunks_.reserve(other.chunks_.size());
77+
chunks_vector::const_iterator it = other.chunks_.begin();
78+
for (; it != other.chunks_.end(); ++it) {
79+
chunks_vector::value_type pair =
80+
std::make_pair(
81+
new (std::nothrow) char[other.chunk_size_],
82+
it->second);
83+
std::memcpy(pair.first, it->first, it->second);
84+
chunks_.push_back(pair);
85+
}
86+
}
87+
88+
request_storage_base_pimpl * request_storage_base_pimpl::clone() const {
89+
return new(std::nothrow) request_storage_base_pimpl(*this);
90+
}
91+
6792
void request_storage_base_pimpl::append(char const *data, size_t size) {
6893
if (chunks_.empty()) {
6994
chunks_.push_back(std::make_pair(
@@ -133,6 +158,7 @@ request_storage_base_pimpl::~request_storage_base_pimpl() {
133158
clear();
134159
}
135160

161+
136162
} /* http */
137163

138164
} /* network */

libs/network/test/http/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ if (Boost_FOUND)
7878
PROPERTIES COMPILE_FLAGS "-Wall")
7979
endif()
8080
add_executable(cpp-netlib-http-${test} ${test}.cpp)
81-
add_dependencies(cpp-netlib-http-${test} cppnetlib-server-parsers)
8281
target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers)
8382
set_target_properties(cpp-netlib-http-${test}
8483
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests)

libs/network/test/http/request_base_test.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,14 @@ struct request_test : http::request_storage_base {
2323
using base_type::flatten;
2424
using base_type::clear;
2525

26-
request_test(size_t chunk_size)
26+
explicit request_test(size_t chunk_size)
2727
: base_type(chunk_size)
2828
{}
2929

30+
request_test(request_test const &other)
31+
: base_type(other)
32+
{}
33+
3034
~request_test() {
3135
// do nothing here.
3236
}
@@ -47,3 +51,22 @@ BOOST_AUTO_TEST_CASE(request_storage_flow) {
4751
BOOST_CHECK_EQUAL(std::string(data, sizeof(data)), std::string(output, sizeof(data)));
4852
simple.clear();
4953
}
54+
55+
BOOST_AUTO_TEST_CASE(request_storage_copy) {
56+
// Use a few byt chunks just to make it manageable.
57+
request_test original(64);
58+
static char quick_brown[] = "The quick brown fox jumps over the lazy dog.";
59+
original.append(quick_brown, sizeof(quick_brown));
60+
char output[sizeof(quick_brown)];
61+
request_test copy(original);
62+
size_t bytes_read = copy.read(output, 0, sizeof(quick_brown));
63+
BOOST_CHECK_EQUAL(bytes_read, sizeof(quick_brown));
64+
std::string flattened;
65+
copy.flatten(flattened);
66+
BOOST_CHECK_EQUAL(flattened, std::string(output, sizeof(quick_brown)));
67+
BOOST_CHECK_EQUAL(std::string(quick_brown, sizeof(quick_brown)), std::string(output, sizeof(quick_brown)));
68+
copy.clear();
69+
flattened.clear();
70+
original.flatten(flattened);
71+
BOOST_CHECK_EQUAL(flattened, std::string(quick_brown, sizeof(quick_brown)));
72+
}

0 commit comments

Comments
 (0)