-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Avoid excessive reply buffer copy in WinHTTP
- Loading branch information
1 parent
97fb759
commit 3b1f7a8
Showing
9 changed files
with
224 additions
and
37 deletions.
There are no files selected for viewing
126 changes: 126 additions & 0 deletions
126
src/aws-cpp-sdk-core/include/aws/core/utils/stream/StreamBufProtectedWriter.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
|
||
/** | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <aws/core/Core_EXPORTS.h> | ||
#include <aws/core/utils/Array.h> | ||
#include <streambuf> | ||
#include <functional> | ||
|
||
namespace Aws | ||
{ | ||
namespace Utils | ||
{ | ||
namespace Stream | ||
{ | ||
/** | ||
* This is a wrapper to perform a hack to write directly to the put area of the underlying streambuf | ||
*/ | ||
class AWS_CORE_API StreamBufProtectedWriter : public std::streambuf | ||
{ | ||
public: | ||
StreamBufProtectedWriter() = delete; | ||
|
||
using WriterFunc = std::function<bool(char* dst, uint64_t dstSz, uint64_t& read)>; | ||
|
||
static uint64_t WriteToBuffer(std::streambuf* pBuffer, const WriterFunc& writerFunc) | ||
{ | ||
StreamBufProtectedWriter* pBufferCasted = static_cast<StreamBufProtectedWriter*>(pBuffer); | ||
uint64_t totalRead = 0; | ||
|
||
while (true) | ||
{ | ||
bool bufferPresent = pBufferCasted->pptr() && (pBufferCasted->pptr() < pBufferCasted->epptr()); | ||
uint64_t read = 0; | ||
if (bufferPresent) | ||
{ | ||
// have access to underlying put ptr. | ||
read = WriteDirectlyToPtr(pBufferCasted, writerFunc); | ||
} | ||
else | ||
{ | ||
// can't access underlying buffer, stream buffer maybe be customized to not use put ptr. | ||
// or underlying put buffer is simply not initialized yet. | ||
read = WriteWithHelperBuffer(pBufferCasted, writerFunc); | ||
} | ||
if (!read) | ||
{ | ||
return totalRead; | ||
} | ||
totalRead += read; | ||
|
||
if (pBufferCasted->pptr() && (pBufferCasted->pptr() >= pBufferCasted->epptr())) | ||
{ | ||
if(!ForceOverflow(pBufferCasted, writerFunc)) | ||
{ | ||
return totalRead; | ||
} else { | ||
totalRead++; | ||
} | ||
} | ||
} | ||
return totalRead; | ||
} | ||
protected: | ||
static size_t ForceOverflow(StreamBufProtectedWriter* pBuffer, const WriterFunc& writerFunc) | ||
{ | ||
char dstChar; | ||
uint64_t read = 0; | ||
if (writerFunc(&dstChar, 1, read) && read > 0) | ||
{ | ||
pBuffer->overflow(dstChar); | ||
return 1; | ||
} | ||
return 0; | ||
} | ||
|
||
static uint64_t WriteWithHelperBuffer(StreamBufProtectedWriter* pBuffer, const WriterFunc& writerFunc) | ||
{ | ||
uint64_t read = 0; | ||
char tmpBuf[1024]; | ||
uint64_t tmpBufSz = sizeof(tmpBuf); | ||
|
||
if(writerFunc(tmpBuf, tmpBufSz, read) && read > 0) | ||
{ | ||
auto dstPptrBefore = pBuffer->pptr(); | ||
auto dstEptrBefore = pBuffer->epptr(); | ||
auto dstSzBefore = pBuffer->epptr() - pBuffer->pptr(); | ||
auto actuallyWritten = pBuffer->sputn(tmpBuf, read); | ||
if ((uint64_t) actuallyWritten != read) | ||
{ | ||
std::cout << "Failed to write " << read << "\n"; | ||
std::cout << "Only wrote " << actuallyWritten << "\n"; | ||
std::cout << "pptr() = " << pBuffer->pptr() << "\n"; | ||
std::cout << "epptr() = " << pBuffer->epptr() << "\n"; | ||
std::cout << "dst size = " << pBuffer->epptr() - pBuffer->pptr() << "\n"; | ||
std::cout << "pptr() before = " << dstPptrBefore << "\n"; | ||
std::cout << "epptr() before = " << dstEptrBefore << "\n"; | ||
std::cout << "dst size before = " << dstSzBefore << "\n"; | ||
} | ||
assert((uint64_t) actuallyWritten == read); | ||
} | ||
|
||
return read; | ||
} | ||
|
||
static uint64_t WriteDirectlyToPtr(StreamBufProtectedWriter* pBuffer, const WriterFunc& writerFunc) | ||
{ | ||
auto dstBegin = pBuffer->pptr(); | ||
uint64_t dstSz = pBuffer->epptr() - dstBegin; | ||
uint64_t read = 0; | ||
if(writerFunc(dstBegin, dstSz, read) && read > 0) | ||
{ | ||
assert(read <= dstSz); | ||
pBuffer->pbump((int) read); | ||
} | ||
|
||
return read; | ||
} | ||
}; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.