Commit f9f5d150 authored by Victor Vasiliev's avatar Victor Vasiliev Committed by Commit Bot

Use C++11 lazy static initialization for HPACK tables

Merge internal change: 217957275

R=rch@chromium.org

Change-Id: I07eef67fd54b96f37d6ee234c5cfb247a9472c74
Reviewed-on: https://chromium-review.googlesource.com/c/1292443Reviewed-by: default avatarRyan Hamilton <rch@chromium.org>
Commit-Queue: Ryan Hamilton <rch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#601420}
parent 00d6281c
...@@ -4,71 +4,28 @@ ...@@ -4,71 +4,28 @@
#include "net/third_party/spdy/core/hpack/hpack_constants.h" #include "net/third_party/spdy/core/hpack/hpack_constants.h"
#include <cstddef>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/singleton.h"
#include "net/third_party/spdy/core/hpack/hpack_huffman_table.h" #include "net/third_party/spdy/core/hpack/hpack_huffman_table.h"
#include "net/third_party/spdy/core/hpack/hpack_static_table.h" #include "net/third_party/spdy/core/hpack/hpack_static_table.h"
#include "net/third_party/spdy/platform/api/spdy_arraysize.h" #include "net/third_party/spdy/platform/api/spdy_arraysize.h"
#include "net/third_party/spdy/platform/api/spdy_ptr_util.h"
namespace spdy { namespace spdy {
namespace { // Produced by applying the python program [1] with tables provided by [2]
// (inserted into the source of the python program) and copy-paste them into
// SharedHpackHuffmanTable is a Singleton wrapping a HpackHuffmanTable // this file.
// instance initialized with |kHpackHuffmanCode|.
struct SharedHpackHuffmanTable {
public:
SharedHpackHuffmanTable() {
std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode();
auto mutable_table = SpdyMakeUnique<HpackHuffmanTable>();
CHECK(mutable_table->Initialize(&code[0], code.size()));
CHECK(mutable_table->IsInitialized());
table = std::move(mutable_table);
}
static SharedHpackHuffmanTable* GetInstance() {
return base::Singleton<SharedHpackHuffmanTable>::get();
}
std::unique_ptr<const HpackHuffmanTable> table;
};
// SharedHpackStaticTable is a Singleton wrapping a HpackStaticTable
// instance initialized with |kHpackStaticTable|.
struct SharedHpackStaticTable {
public:
SharedHpackStaticTable() {
std::vector<HpackStaticEntry> static_table = HpackStaticTableVector();
auto mutable_table = SpdyMakeUnique<HpackStaticTable>();
mutable_table->Initialize(&static_table[0], static_table.size());
CHECK(mutable_table->IsInitialized());
table = std::move(mutable_table);
}
static SharedHpackStaticTable* GetInstance() {
return base::Singleton<SharedHpackStaticTable>::get();
}
std::unique_ptr<const HpackStaticTable> table;
};
} // namespace
// Produced by applying the python program [1] with tables
// provided by [2] (inserted into the source of the python program)
// and copy-paste them into this file.
// //
// [1] net/tools/build_hpack_constants.py // [1] net/tools/build_hpack_constants.py in Chromium
// [2] http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08 // [2] http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-08
// HpackHuffmanSymbol entries are initialized as {code, length, id}. // HpackHuffmanSymbol entries are initialized as {code, length, id}.
// Codes are specified in the |length| most-significant bits of |code|. // Codes are specified in the |length| most-significant bits of |code|.
std::vector<HpackHuffmanSymbol> HpackHuffmanCode() { const std::vector<HpackHuffmanSymbol>& HpackHuffmanCodeVector() {
static const HpackHuffmanSymbol kHpackHuffmanCode[] = { static const auto* kHpackHuffmanCode = new std::vector<HpackHuffmanSymbol>{
{0xffc00000ul, 13, 0}, // 11111111|11000 {0xffc00000ul, 13, 0}, // 11111111|11000
{0xffffb000ul, 23, 1}, // 11111111|11111111|1011000 {0xffffb000ul, 23, 1}, // 11111111|11111111|1011000
{0xfffffe20ul, 28, 2}, // 11111111|11111111|11111110|0010 {0xfffffe20ul, 28, 2}, // 11111111|11111111|11111110|0010
...@@ -327,8 +284,7 @@ std::vector<HpackHuffmanSymbol> HpackHuffmanCode() { ...@@ -327,8 +284,7 @@ std::vector<HpackHuffmanSymbol> HpackHuffmanCode() {
{0xfffffb80ul, 26, 255}, // 11111111|11111111|11111011|10 {0xfffffb80ul, 26, 255}, // 11111111|11111111|11111011|10
{0xfffffffcul, 30, 256}, // EOS 11111111|11111111|11111111|111111 {0xfffffffcul, 30, 256}, // EOS 11111111|11111111|11111111|111111
}; };
return std::vector<HpackHuffmanSymbol>( return *kHpackHuffmanCode;
kHpackHuffmanCode, kHpackHuffmanCode + SPDY_ARRAYSIZE(kHpackHuffmanCode));
} }
// The "constructor" for a HpackStaticEntry that computes the lengths at // The "constructor" for a HpackStaticEntry that computes the lengths at
...@@ -336,8 +292,8 @@ std::vector<HpackHuffmanSymbol> HpackHuffmanCode() { ...@@ -336,8 +292,8 @@ std::vector<HpackHuffmanSymbol> HpackHuffmanCode() {
#define STATIC_ENTRY(name, value) \ #define STATIC_ENTRY(name, value) \
{ name, SPDY_ARRAYSIZE(name) - 1, value, SPDY_ARRAYSIZE(value) - 1 } { name, SPDY_ARRAYSIZE(name) - 1, value, SPDY_ARRAYSIZE(value) - 1 }
std::vector<HpackStaticEntry> HpackStaticTableVector() { const std::vector<HpackStaticEntry>& HpackStaticTableVector() {
static const HpackStaticEntry kHpackStaticTable[] = { static const auto* kHpackStaticTable = new std::vector<HpackStaticEntry>{
STATIC_ENTRY(":authority", ""), // 1 STATIC_ENTRY(":authority", ""), // 1
STATIC_ENTRY(":method", "GET"), // 2 STATIC_ENTRY(":method", "GET"), // 2
STATIC_ENTRY(":method", "POST"), // 3 STATIC_ENTRY(":method", "POST"), // 3
...@@ -400,18 +356,31 @@ std::vector<HpackStaticEntry> HpackStaticTableVector() { ...@@ -400,18 +356,31 @@ std::vector<HpackStaticEntry> HpackStaticTableVector() {
STATIC_ENTRY("via", ""), // 60 STATIC_ENTRY("via", ""), // 60
STATIC_ENTRY("www-authenticate", ""), // 61 STATIC_ENTRY("www-authenticate", ""), // 61
}; };
return std::vector<HpackStaticEntry>( return *kHpackStaticTable;
kHpackStaticTable, kHpackStaticTable + SPDY_ARRAYSIZE(kHpackStaticTable));
} }
#undef STATIC_ENTRY #undef STATIC_ENTRY
const HpackHuffmanTable& ObtainHpackHuffmanTable() { const HpackHuffmanTable& ObtainHpackHuffmanTable() {
return *SharedHpackHuffmanTable::GetInstance()->table; static const HpackHuffmanTable* const shared_huffman_table = []() {
auto* table = new HpackHuffmanTable();
CHECK(table->Initialize(HpackHuffmanCodeVector().data(),
HpackHuffmanCodeVector().size()));
CHECK(table->IsInitialized());
return table;
}();
return *shared_huffman_table;
} }
const HpackStaticTable& ObtainHpackStaticTable() { const HpackStaticTable& ObtainHpackStaticTable() {
return *SharedHpackStaticTable::GetInstance()->table; static const HpackStaticTable* const shared_static_table = []() {
auto* table = new HpackStaticTable();
table->Initialize(HpackStaticTableVector().data(),
HpackStaticTableVector().size());
CHECK(table->IsInitialized());
return table;
}();
return *shared_static_table;
} }
} // namespace spdy } // namespace spdy
...@@ -70,11 +70,13 @@ const HpackPrefix kLiteralNoIndexOpcode = {0b0000, 4}; ...@@ -70,11 +70,13 @@ const HpackPrefix kLiteralNoIndexOpcode = {0b0000, 4};
// varint-encoded table size with a 5-bit prefix. // varint-encoded table size with a 5-bit prefix.
const HpackPrefix kHeaderTableSizeUpdateOpcode = {0b001, 3}; const HpackPrefix kHeaderTableSizeUpdateOpcode = {0b001, 3};
// Returns symbol code table from RFC 7541, "Appendix C. Huffman Code". // Symbol code table from RFC 7541, "Appendix C. Huffman Code".
SPDY_EXPORT_PRIVATE std::vector<HpackHuffmanSymbol> HpackHuffmanCode(); SPDY_EXPORT_PRIVATE const std::vector<HpackHuffmanSymbol>&
HpackHuffmanCodeVector();
// Returns static table from RFC 7541, "Appendix B. Static Table Definition". // Static table from RFC 7541, "Appendix B. Static Table Definition".
SPDY_EXPORT_PRIVATE std::vector<HpackStaticEntry> HpackStaticTableVector(); SPDY_EXPORT_PRIVATE const std::vector<HpackStaticEntry>&
HpackStaticTableVector();
// Returns a HpackHuffmanTable instance initialized with |kHpackHuffmanCode|. // Returns a HpackHuffmanTable instance initialized with |kHpackHuffmanCode|.
// The instance is read-only, has static lifetime, and is safe to share amoung // The instance is read-only, has static lifetime, and is safe to share amoung
......
...@@ -202,8 +202,8 @@ TEST_F(GenericHuffmanTableTest, ValidateInternalsWithSmallCode) { ...@@ -202,8 +202,8 @@ TEST_F(GenericHuffmanTableTest, ValidateInternalsWithSmallCode) {
class HpackHuffmanTableTest : public GenericHuffmanTableTest { class HpackHuffmanTableTest : public GenericHuffmanTableTest {
protected: protected:
void SetUp() override { void SetUp() override {
std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode(); EXPECT_TRUE(table_.Initialize(HpackHuffmanCodeVector().data(),
EXPECT_TRUE(table_.Initialize(&code[0], code.size())); HpackHuffmanCodeVector().size()));
EXPECT_TRUE(table_.IsInitialized()); EXPECT_TRUE(table_.IsInitialized());
} }
......
...@@ -27,15 +27,15 @@ class HpackStaticTableTest : public ::testing::Test { ...@@ -27,15 +27,15 @@ class HpackStaticTableTest : public ::testing::Test {
// Check that an initialized instance has the right number of entries. // Check that an initialized instance has the right number of entries.
TEST_F(HpackStaticTableTest, Initialize) { TEST_F(HpackStaticTableTest, Initialize) {
EXPECT_FALSE(table_.IsInitialized()); EXPECT_FALSE(table_.IsInitialized());
std::vector<HpackStaticEntry> static_table = HpackStaticTableVector(); table_.Initialize(HpackStaticTableVector().data(),
table_.Initialize(&static_table[0], static_table.size()); HpackStaticTableVector().size());
EXPECT_TRUE(table_.IsInitialized()); EXPECT_TRUE(table_.IsInitialized());
HpackHeaderTable::EntryTable static_entries = table_.GetStaticEntries(); HpackHeaderTable::EntryTable static_entries = table_.GetStaticEntries();
EXPECT_EQ(static_table.size(), static_entries.size()); EXPECT_EQ(HpackStaticTableVector().size(), static_entries.size());
HpackHeaderTable::UnorderedEntrySet static_index = table_.GetStaticIndex(); HpackHeaderTable::UnorderedEntrySet static_index = table_.GetStaticIndex();
EXPECT_EQ(static_table.size(), static_index.size()); EXPECT_EQ(HpackStaticTableVector().size(), static_index.size());
HpackHeaderTable::NameToEntryMap static_name_index = HpackHeaderTable::NameToEntryMap static_name_index =
table_.GetStaticNameIndex(); table_.GetStaticNameIndex();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment