Skip to content

Commit 91e115f

Browse files
committed
Deprecating stream buffer putn function, adding putn_nocopy. This is really is the best choice to completely remove the unnecessary copy in file streams.
1 parent f04dee9 commit 91e115f

20 files changed

+215
-142
lines changed

Release/include/cpprest/astreambuf.h

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,19 @@ namespace streams
197197
/// <returns>A <c>task</c> that holds the number of characters actually written, either 'count' or 0.</returns>
198198
virtual pplx::task<size_t> putn(const _CharType *ptr, size_t count) = 0;
199199

200+
/// <summary>
201+
/// Writes a number of characters to the stream. Note: callers must make sure the data to be written is valid until
202+
/// the returned task completes.
203+
/// </summary>
204+
/// <param name="ptr">A pointer to the block of data to be written.</param>
205+
/// <param name="count">The number of characters to write.</param>
206+
/// <returns>A <c>task</c> that holds the number of characters actually written, either 'count' or 0.</returns>
207+
virtual pplx::task<size_t> putn_nocopy(const _CharType *ptr, size_t count) = 0;
208+
200209
/// <summary>
201210
/// Reads a single character from the stream and advances the read position.
202211
/// </summary>
203-
/// <returns>A <c>task</c> that holds the value of the character. This value is EOF if the read fails.</returns>
212+
/// <returns>A <c>task</c> that holds the value of the character. This value is EOF if the read fails.</returns>
204213
virtual pplx::task<int_type> bumpc() = 0;
205214

206215
/// <summary>
@@ -226,7 +235,7 @@ namespace streams
226235
/// <summary>
227236
/// Advances the read position, then returns the next character without advancing again.
228237
/// </summary>
229-
/// <returns>A <c>task</c> that holds the value of the character. This value is EOF if the read fails.</returns>
238+
/// <returns>A <c>task</c> that holds the value of the character. This value is EOF if the read fails.</returns>
230239
virtual pplx::task<int_type> nextc() = 0;
231240

232241
/// <summary>
@@ -450,7 +459,27 @@ namespace streams
450459
/// <param name="ptr">A pointer to the block of data to be written.</param>
451460
/// <param name="count">The number of characters to write.</param>
452461
/// <returns>The number of characters actually written, either 'count' or 0.</returns>
462+
CASABLANCA_DEPRECATED("This API in some cases performs a copy. It is deprecated and will be removed in a future release. Use putn_nocopy instead.")
453463
virtual pplx::task<size_t> putn(const _CharType *ptr, size_t count)
464+
{
465+
if (!can_write())
466+
return create_exception_checked_value_task<size_t>(0);
467+
if (count == 0)
468+
return pplx::task_from_result<size_t>(0);
469+
470+
return create_exception_checked_task<size_t>(_putn(ptr, count, true), [](size_t) {
471+
return false; // no EOF for write
472+
});
473+
}
474+
475+
/// <summary>
476+
/// Writes a number of characters to the stream. Note: callers must make sure the data to be written is valid until
477+
/// the returned task completes.
478+
/// </summary>
479+
/// <param name="ptr">A pointer to the block of data to be written.</param>
480+
/// <param name="count">The number of characters to write.</param>
481+
/// <returns>A <c>task</c> that holds the number of characters actually written, either 'count' or 0.</returns>
482+
virtual pplx::task<size_t> putn_nocopy(const _CharType *ptr, size_t count)
454483
{
455484
if (!can_write())
456485
return create_exception_checked_value_task<size_t>(0);
@@ -655,7 +684,15 @@ namespace streams
655684
virtual void release(_Out_writes_(count) _CharType *ptr, _In_ size_t count) = 0;
656685
protected:
657686
virtual pplx::task<int_type> _putc(_CharType ch) = 0;
687+
688+
// This API is only needed for file streams and until we remove the deprecated stream buffer putn overload.
689+
virtual pplx::task<size_t> _putn(const _CharType *ptr, size_t count, bool)
690+
{
691+
// Default to no copy, only the file streams API overloads and performs a copy.
692+
return _putn(ptr, count);
693+
}
658694
virtual pplx::task<size_t> _putn(const _CharType *ptr, size_t count) = 0;
695+
659696
virtual pplx::task<int_type> _bumpc() = 0;
660697
virtual int_type _sbumpc() = 0;
661698
virtual pplx::task<int_type> _getc() = 0;
@@ -866,7 +903,7 @@ namespace streams
866903
/// </summary>
867904
virtual ~streambuf() { }
868905

869-
std::shared_ptr<details::basic_streambuf<_CharType>> get_base() const
906+
const std::shared_ptr<details::basic_streambuf<_CharType>> & get_base() const
870907
{
871908
if (!m_buffer)
872909
{
@@ -1031,11 +1068,24 @@ namespace streams
10311068
/// <param name="ptr">A pointer to the block of data to be written.</param>
10321069
/// <param name="count">The number of characters to write.</param>
10331070
/// <returns>The number of characters actually written, either 'count' or 0.</returns>
1071+
CASABLANCA_DEPRECATED("This API in some cases performs a copy. It is deprecated and will be removed in a future release. Use putn_nocopy instead.")
10341072
virtual pplx::task<size_t> putn(const _CharType *ptr, size_t count)
10351073
{
10361074
return get_base()->putn(ptr, count);
10371075
}
10381076

1077+
/// <summary>
1078+
/// Writes a number of characters to the stream. Note: callers must make sure the data to be written is valid until
1079+
/// the returned task completes.
1080+
/// </summary>
1081+
/// <param name="ptr">A pointer to the block of data to be written.</param>
1082+
/// <param name="count">The number of characters to write.</param>
1083+
/// <returns>The number of characters actually written, either 'count' or 0.</returns>
1084+
virtual pplx::task<size_t> putn_nocopy(const _CharType *ptr, size_t count)
1085+
{
1086+
return get_base()->putn_nocopy(ptr, count);
1087+
}
1088+
10391089
/// <summary>
10401090
/// Reads a single character from the stream and advances the read position.
10411091
/// </summary>

Release/include/cpprest/filestream.h

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,24 @@ namespace details {
368368
return pplx::create_task(result_tce);
369369
}
370370

371+
// Temporarily needed until the deprecated putn is removed.
372+
virtual pplx::task<size_t> _putn(const _CharType *ptr, size_t count, bool copy)
373+
{
374+
if (copy)
375+
{
376+
auto sharedData = std::shared_ptr<_CharType>(new _CharType[count], std::default_delete<_CharType []>());
377+
memcpy(sharedData.get(), ptr, count * sizeof(_CharType));
378+
return _putn(ptr, count).then([sharedData](size_t size)
379+
{
380+
return size;
381+
});
382+
}
383+
else
384+
{
385+
return _putn(ptr, count);
386+
}
387+
}
388+
371389
/// <summary>
372390
/// Reads a single byte from the stream and advance the read position.
373391
/// </summary>
@@ -741,7 +759,7 @@ namespace details {
741759
class _filestream_callback_open : public details::_filestream_callback
742760
{
743761
public:
744-
_filestream_callback_open(pplx::task_completion_event<std::shared_ptr<basic_streambuf<_CharType>>> op) : m_op(op) { }
762+
_filestream_callback_open(const pplx::task_completion_event<std::shared_ptr<basic_streambuf<_CharType>>> &op) : m_op(op) { }
745763

746764
virtual void on_opened(_In_ _file_info *info)
747765
{
@@ -762,7 +780,7 @@ namespace details {
762780
class _filestream_callback_close : public details::_filestream_callback
763781
{
764782
public:
765-
_filestream_callback_close(pplx::task_completion_event<void> op) : m_op(op) { }
783+
_filestream_callback_close(const pplx::task_completion_event<void> &op) : m_op(op) { }
766784

767785
virtual void on_closed()
768786
{
@@ -784,7 +802,7 @@ namespace details {
784802
class _filestream_callback_write : public details::_filestream_callback
785803
{
786804
public:
787-
_filestream_callback_write(_In_ _file_info *info, pplx::task_completion_event<ResultType> op) : m_info(info), m_op(op) { }
805+
_filestream_callback_write(_In_ _file_info *info, const pplx::task_completion_event<ResultType> &op) : m_info(info), m_op(op) { }
788806

789807
virtual void on_completed(size_t result)
790808
{
@@ -806,7 +824,7 @@ namespace details {
806824
class _filestream_callback_write_b : public details::_filestream_callback
807825
{
808826
public:
809-
_filestream_callback_write_b(_In_ _file_info *info, pplx::task_completion_event<void> op) : m_info(info), m_op(op) { }
827+
_filestream_callback_write_b(_In_ _file_info *info, const pplx::task_completion_event<void> &op) : m_info(info), m_op(op) { }
810828

811829
virtual void on_completed(size_t)
812830
{
@@ -829,7 +847,7 @@ namespace details {
829847
class _filestream_callback_read : public details::_filestream_callback
830848
{
831849
public:
832-
_filestream_callback_read(_In_ _file_info *info, pplx::task_completion_event<size_t> op) : m_info(info), m_op(op) { }
850+
_filestream_callback_read(_In_ _file_info *info, const pplx::task_completion_event<size_t> &op) : m_info(info), m_op(op) { }
833851

834852
virtual void on_completed(size_t result)
835853
{
@@ -853,7 +871,7 @@ namespace details {
853871
class _filestream_callback_bumpc : public details::_filestream_callback
854872
{
855873
public:
856-
_filestream_callback_bumpc(_In_ _file_info *info, pplx::task_completion_event<int_type> op) : m_ch(0), m_info(info), m_op(op) { }
874+
_filestream_callback_bumpc(_In_ _file_info *info, const pplx::task_completion_event<int_type> &op) : m_ch(0), m_info(info), m_op(op) { }
857875

858876
virtual void on_completed(size_t result)
859877
{
@@ -885,7 +903,7 @@ namespace details {
885903
class _filestream_callback_getc : public details::_filestream_callback
886904
{
887905
public:
888-
_filestream_callback_getc(_In_ _file_info *info, pplx::task_completion_event<int_type> op) : m_ch(0), m_info(info), m_op(op) { }
906+
_filestream_callback_getc(_In_ _file_info *info, const pplx::task_completion_event<int_type> &op) : m_ch(0), m_info(info), m_op(op) { }
889907

890908
virtual void on_completed(size_t result)
891909
{

Release/include/cpprest/interopstream.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,8 @@ namespace Concurrency { namespace streams {
309309
{
310310
try
311311
{
312-
return m_buffer.putn(ptr, (size_t)count).get();
313-
}
312+
return m_buffer.putn_nocopy(ptr, static_cast<size_t>(count)).get();
313+
}
314314
catch(...)
315315
{
316316
return 0;

Release/include/cpprest/streams.h

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ namespace Concurrency { namespace streams
196196
if ( !_verify_and_return_task(details::_out_stream_msg, result) ) return result;
197197

198198
auto copy = std::make_shared<T>(std::move(value));
199-
return helper()->m_buffer.putn((CharType*)copy.get(), sizeof(T)).then([copy](pplx::task<size_t> op) -> size_t { return op.get(); });
199+
return helper()->m_buffer.putn_nocopy((CharType*)copy.get(), sizeof(T)).then([copy](pplx::task<size_t> op) -> size_t { return op.get(); });
200200
}
201201

202202
/// <summary>
@@ -242,7 +242,7 @@ namespace Concurrency { namespace streams
242242
s.release(data,op.get());
243243
return op;
244244
};
245-
return buffer.putn(data, count).then(post_write);
245+
return buffer.putn_nocopy(data, count).then(post_write);
246246
}
247247
else
248248
{
@@ -263,7 +263,7 @@ namespace Concurrency { namespace streams
263263
[buf,post_write,buffer](pplx::task<size_t> op) -> pplx::task<size_t>
264264
{
265265
auto b = buffer;
266-
return b.putn(buf.get(), op.get()).then(post_write);
266+
return b.putn_nocopy(buf.get(), op.get()).then(post_write);
267267
};
268268

269269
return source.getn(buf.get(), count).then(post_read);
@@ -279,9 +279,16 @@ namespace Concurrency { namespace streams
279279
{
280280
pplx::task<size_t> result;
281281
if ( !_verify_and_return_task(details::_out_stream_msg, result) ) return result;
282-
return (str.size() == 0)
283-
? pplx::task_from_result<size_t>((0))
284-
: helper()->m_buffer.putn(str.c_str(), str.size());
282+
283+
if (str.empty())
284+
{
285+
return pplx::task_from_result<size_t>(0);
286+
}
287+
else
288+
{
289+
auto sharedStr = std::make_shared<std::basic_string<CharType>>(str);
290+
return helper()->m_buffer.putn_nocopy(sharedStr->c_str(), sharedStr->size()).then([sharedStr](size_t size) { return size; });
291+
}
285292
}
286293

287294
/// <summary>
@@ -713,7 +720,7 @@ namespace Concurrency { namespace streams
713720
b.release(data, op.get());
714721
return op;
715722
};
716-
return target.putn(data, count).then(post_write);
723+
return target.putn_nocopy(data, count).then(post_write);
717724
}
718725
else
719726
{
@@ -734,7 +741,7 @@ namespace Concurrency { namespace streams
734741
[buf,target,post_write](pplx::task<size_t> op) -> pplx::task<size_t>
735742
{
736743
auto trg = target;
737-
return trg.putn(buf.get(), op.get()).then(post_write);
744+
return trg.putn_nocopy(buf.get(), op.get()).then(post_write);
738745
};
739746

740747
return helper()->m_buffer.getn(buf.get(), count).then(post_read);
@@ -776,7 +783,7 @@ namespace Concurrency { namespace streams
776783

777784
auto flush = [=]() mutable
778785
{
779-
return target.putn(_locals->outbuf, _locals->write_pos).then([=](size_t wrote) mutable
786+
return target.putn_nocopy(_locals->outbuf, _locals->write_pos).then([=](size_t wrote) mutable
780787
{
781788
_locals->total += wrote;
782789
_locals->write_pos = 0;
@@ -848,7 +855,7 @@ namespace Concurrency { namespace streams
848855

849856
auto flush = [=]() mutable
850857
{
851-
return target.putn(_locals->outbuf, _locals->write_pos).then([=](size_t wrote) mutable
858+
return target.putn_nocopy(_locals->outbuf, _locals->write_pos).then([=](size_t wrote) mutable
852859
{
853860
_locals->total += wrote;
854861
_locals->write_pos = 0;
@@ -963,7 +970,7 @@ namespace Concurrency { namespace streams
963970
return pplx::task_from_result(false);
964971

965972
// Must be nested to capture rd
966-
return target.putn(l_locals->outbuf, rd).then([target, l_locals, rd](size_t wr) mutable -> pplx::task<bool>
973+
return target.putn_nocopy(l_locals->outbuf, rd).then([target, l_locals, rd](size_t wr) mutable -> pplx::task<bool>
967974
{
968975
l_locals->total += wr;
969976

@@ -1728,7 +1735,7 @@ class type_parser<char,std::basic_string<wchar_t>> : public _type_parser_base<ch
17281735
}
17291736

17301737
private:
1731-
static bool _accept_char(std::shared_ptr<std::basic_string<char>> state, int_type ch)
1738+
static bool _accept_char(const std::shared_ptr<std::basic_string<char>> &state, int_type ch)
17321739
{
17331740
if ( ch == concurrency::streams::char_traits<char>::eof() || isspace(ch)) return false;
17341741
state->push_back(char(ch));
@@ -1750,7 +1757,7 @@ class type_parser<signed char,std::basic_string<wchar_t>> : public _type_parser_
17501757
}
17511758

17521759
private:
1753-
static bool _accept_char(std::shared_ptr<std::basic_string<char>> state, int_type ch)
1760+
static bool _accept_char(const std::shared_ptr<std::basic_string<char>> &state, int_type ch)
17541761
{
17551762
if ( ch == concurrency::streams::char_traits<char>::eof() || isspace(ch)) return false;
17561763
state->push_back(char(ch));
@@ -1772,7 +1779,7 @@ class type_parser<unsigned char,std::basic_string<wchar_t>> : public _type_parse
17721779
}
17731780

17741781
private:
1775-
static bool _accept_char(std::shared_ptr<std::basic_string<char>> state, int_type ch)
1782+
static bool _accept_char(const std::shared_ptr<std::basic_string<char>> &state, int_type ch)
17761783
{
17771784
if ( ch == concurrency::streams::char_traits<char>::eof() || isspace(ch)) return false;
17781785
state->push_back(char(ch));

Release/src/http/client/http_client_asio.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,7 @@ class asio_context : public request_context, public std::enable_shared_from_this
968968
{
969969
auto writeBuffer = _get_writebuffer();
970970
const auto this_request = shared_from_this();
971-
writeBuffer.putn(boost::asio::buffer_cast<const uint8_t *>(m_body_buf.data()), to_read).then([this_request, to_read](pplx::task<size_t> op)
971+
writeBuffer.putn_nocopy(boost::asio::buffer_cast<const uint8_t *>(m_body_buf.data()), to_read).then([this_request, to_read](pplx::task<size_t> op)
972972
{
973973
try
974974
{
@@ -1026,7 +1026,7 @@ class asio_context : public request_context, public std::enable_shared_from_this
10261026
{
10271027
// more data need to be read
10281028
const auto this_request = shared_from_this();
1029-
writeBuffer.putn(boost::asio::buffer_cast<const uint8_t *>(m_body_buf.data()),
1029+
writeBuffer.putn_nocopy(boost::asio::buffer_cast<const uint8_t *>(m_body_buf.data()),
10301030
static_cast<size_t>(std::min(static_cast<uint64_t>(m_body_buf.size()), m_content_length - m_downloaded)))
10311031
.then([this_request](pplx::task<size_t> op)
10321032
{

Release/src/http/client/http_client_winhttp.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,7 @@ class winhttp_client : public _http_client_communicator
739739
{
740740
// We have raw memory here writing to a memory stream so it is safe to wait
741741
// since it will always be non-blocking.
742-
p_request_context->m_readBufferCopy->putn(&p_request_context->m_body_data.get()[http::details::chunked_encoding::data_offset], bytes_read).wait();
742+
p_request_context->m_readBufferCopy->putn_nocopy(&p_request_context->m_body_data.get()[http::details::chunked_encoding::data_offset], bytes_read).wait();
743743
}
744744
}
745745
catch (...)
@@ -1230,7 +1230,7 @@ class winhttp_client : public _http_client_communicator
12301230
}
12311231
else
12321232
{
1233-
writebuf.putn(p_request_context->m_body_data.get(), bytesRead).then(
1233+
writebuf.putn_nocopy(p_request_context->m_body_data.get(), bytesRead).then(
12341234
[hRequestHandle, p_request_context, bytesRead] (pplx::task<size_t> op)
12351235
{
12361236
size_t written = 0;

Release/src/http/client/http_client_winrt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ class IResponseStream
307307
try
308308
{
309309
auto buffer = context->_get_writebuffer();
310-
const size_t count = buffer.putn(reinterpret_cast<const uint8_t *>(pv), static_cast<size_t>(cb)).get();
310+
const size_t count = buffer.putn_nocopy(reinterpret_cast<const uint8_t *>(pv), static_cast<size_t>(cb)).get();
311311

312312
_ASSERTE(count != static_cast<size_t>(-1));
313313
_ASSERTE(count <= static_cast<size_t>(ULONG_MAX));

0 commit comments

Comments
 (0)