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 @@
#include "net/third_party/spdy/core/hpack/hpack_constants.h"
#include <cstddef>
#include <memory>
#include <vector>
#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_static_table.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 {
// SharedHpackHuffmanTable is a Singleton wrapping a HpackHuffmanTable
// 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.
// 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
// HpackHuffmanSymbol entries are initialized as {code, length, id}.
// Codes are specified in the |length| most-significant bits of |code|.
std::vector<HpackHuffmanSymbol> HpackHuffmanCode() {
static const HpackHuffmanSymbol kHpackHuffmanCode[] = {
const std::vector<HpackHuffmanSymbol>& HpackHuffmanCodeVector() {
static const auto* kHpackHuffmanCode = new std::vector<HpackHuffmanSymbol>{
{0xffc00000ul, 13, 0}, // 11111111|11000
{0xffffb000ul, 23, 1}, // 11111111|11111111|1011000
{0xfffffe20ul, 28, 2}, // 11111111|11111111|11111110|0010
......@@ -327,8 +284,7 @@ std::vector<HpackHuffmanSymbol> HpackHuffmanCode() {
{0xfffffb80ul, 26, 255}, // 11111111|11111111|11111011|10
{0xfffffffcul, 30, 256}, // EOS 11111111|11111111|11111111|111111
};
return std::vector<HpackHuffmanSymbol>(
kHpackHuffmanCode, kHpackHuffmanCode + SPDY_ARRAYSIZE(kHpackHuffmanCode));
return *kHpackHuffmanCode;
}
// The "constructor" for a HpackStaticEntry that computes the lengths at
......@@ -336,8 +292,8 @@ std::vector<HpackHuffmanSymbol> HpackHuffmanCode() {
#define STATIC_ENTRY(name, value) \
{ name, SPDY_ARRAYSIZE(name) - 1, value, SPDY_ARRAYSIZE(value) - 1 }
std::vector<HpackStaticEntry> HpackStaticTableVector() {
static const HpackStaticEntry kHpackStaticTable[] = {
const std::vector<HpackStaticEntry>& HpackStaticTableVector() {
static const auto* kHpackStaticTable = new std::vector<HpackStaticEntry>{
STATIC_ENTRY(":authority", ""), // 1
STATIC_ENTRY(":method", "GET"), // 2
STATIC_ENTRY(":method", "POST"), // 3
......@@ -400,18 +356,31 @@ std::vector<HpackStaticEntry> HpackStaticTableVector() {
STATIC_ENTRY("via", ""), // 60
STATIC_ENTRY("www-authenticate", ""), // 61
};
return std::vector<HpackStaticEntry>(
kHpackStaticTable, kHpackStaticTable + SPDY_ARRAYSIZE(kHpackStaticTable));
return *kHpackStaticTable;
}
#undef STATIC_ENTRY
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() {
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
......@@ -70,11 +70,13 @@ const HpackPrefix kLiteralNoIndexOpcode = {0b0000, 4};
// varint-encoded table size with a 5-bit prefix.
const HpackPrefix kHeaderTableSizeUpdateOpcode = {0b001, 3};
// Returns symbol code table from RFC 7541, "Appendix C. Huffman Code".
SPDY_EXPORT_PRIVATE std::vector<HpackHuffmanSymbol> HpackHuffmanCode();
// Symbol code table from RFC 7541, "Appendix C. Huffman Code".
SPDY_EXPORT_PRIVATE const std::vector<HpackHuffmanSymbol>&
HpackHuffmanCodeVector();
// Returns static table from RFC 7541, "Appendix B. Static Table Definition".
SPDY_EXPORT_PRIVATE std::vector<HpackStaticEntry> HpackStaticTableVector();
// Static table from RFC 7541, "Appendix B. Static Table Definition".
SPDY_EXPORT_PRIVATE const std::vector<HpackStaticEntry>&
HpackStaticTableVector();
// Returns a HpackHuffmanTable instance initialized with |kHpackHuffmanCode|.
// The instance is read-only, has static lifetime, and is safe to share amoung
......
......@@ -202,8 +202,8 @@ TEST_F(GenericHuffmanTableTest, ValidateInternalsWithSmallCode) {
class HpackHuffmanTableTest : public GenericHuffmanTableTest {
protected:
void SetUp() override {
std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode();
EXPECT_TRUE(table_.Initialize(&code[0], code.size()));
EXPECT_TRUE(table_.Initialize(HpackHuffmanCodeVector().data(),
HpackHuffmanCodeVector().size()));
EXPECT_TRUE(table_.IsInitialized());
}
......
......@@ -27,15 +27,15 @@ class HpackStaticTableTest : public ::testing::Test {
// Check that an initialized instance has the right number of entries.
TEST_F(HpackStaticTableTest, Initialize) {
EXPECT_FALSE(table_.IsInitialized());
std::vector<HpackStaticEntry> static_table = HpackStaticTableVector();
table_.Initialize(&static_table[0], static_table.size());
table_.Initialize(HpackStaticTableVector().data(),
HpackStaticTableVector().size());
EXPECT_TRUE(table_.IsInitialized());
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();
EXPECT_EQ(static_table.size(), static_index.size());
EXPECT_EQ(HpackStaticTableVector().size(), static_index.size());
HpackHeaderTable::NameToEntryMap static_name_index =
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