Skip to content

Commit 5f789eb

Browse files
taku910hiroyuki-komatsu
authored andcommitted
Stop using raw pointer to share composer::Table.
Background: composer::Table is shared across different components. Though we would like to avoid shared object, Table is not copyable so there is no other way to share them at this moment. The internal data of the Table is managed by std::unique_ptr, which makes simple copying impossible. Furthermore, copying the table every time would result in a significant performance degradation. Style guide says that we prefer to use std::shared_ptr for shared memory object. PiperOrigin-RevId: 730072127
1 parent 73d25e3 commit 5f789eb

33 files changed

+557
-529
lines changed

src/composer/BUILD.bazel

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ mozc_cc_library(
111111
"//composer/internal:special_key",
112112
"//protocol:commands_cc_proto",
113113
"//protocol:config_cc_proto",
114+
"@com_google_absl//absl/base:no_destructor",
114115
"@com_google_absl//absl/container:flat_hash_map",
115116
"@com_google_absl//absl/container:flat_hash_set",
116117
"@com_google_absl//absl/hash",

src/composer/composer.cc

+14-9
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
#include <cstddef>
3535
#include <cstdint>
36+
#include <memory>
3637
#include <string>
3738
#include <tuple>
3839
#include <unordered_map>
@@ -569,14 +570,16 @@ void ComposerData::GetSubTransliterations(
569570
// Composer
570571

571572
Composer::Composer()
572-
: Composer(Table::GetDefaultTable(), commands::Request::default_instance(),
573+
: Composer(Table::GetSharedDefaultTable(),
574+
commands::Request::default_instance(),
573575
config::ConfigHandler::DefaultConfig()) {}
574576

575577
Composer::Composer(const commands::Request &request,
576578
const config::Config &config)
577-
: Composer(Table::GetDefaultTable(), request, config) {}
579+
: Composer(Table::GetSharedDefaultTable(), request, config) {}
578580

579-
Composer::Composer(const Table &table, const commands::Request &request,
581+
Composer::Composer(std::shared_ptr<const Table> table,
582+
const commands::Request &request,
580583
const config::Config &config)
581584
: position_(0),
582585
input_mode_(transliteration::HIRAGANA),
@@ -588,16 +591,17 @@ Composer::Composer(const Table &table, const commands::Request &request,
588591
max_length_(kMaxPreeditLength),
589592
request_(&request),
590593
config_(&config),
591-
table_(&table),
594+
table_(table),
592595
is_new_input_(true) {
593596
SetInputMode(transliteration::HIRAGANA);
597+
DCHECK(table_);
594598
Reset();
595599
}
596600

597601
// static
598602
ComposerData Composer::CreateEmptyComposerData() {
599-
static const absl::NoDestructor<Table> table;
600-
static const absl::NoDestructor<Composition> composition(*table);
603+
static const absl::NoDestructor<Composition> composition(
604+
Table::GetSharedDefaultTable());
601605
return ComposerData(*composition, 0, transliteration::HIRAGANA,
602606
commands::Context::NORMAL, "", {});
603607
}
@@ -624,9 +628,10 @@ void Composer::ReloadConfig() {
624628

625629
bool Composer::Empty() const { return (GetLength() == 0); }
626630

627-
void Composer::SetTable(const Table &table) {
628-
table_ = &table;
629-
composition_.SetTable(*table_);
631+
void Composer::SetTable(std::shared_ptr<const Table> table) {
632+
table_ = table;
633+
DCHECK(table_);
634+
composition_.SetTable(table_);
630635
}
631636

632637
void Composer::SetRequest(const commands::Request &request) {

src/composer/composer.h

+17-8
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,12 @@ namespace mozc {
5555
namespace composer {
5656

5757
// ComposerData is a data structure that represents the current state of the
58-
// composer. It is used by Converter, Predictor and Rewriters as a const object.
58+
// composer. It is used by Converter, Predictor and Rewriters as a const
59+
// object.
5960
class ComposerData {
6061
public:
61-
// This constructor is temporary and should be removed, when ConverterRequest
62-
// is updated to use a const ComposerData.
62+
// This constructor is temporary and should be removed, when
63+
// ConverterRequest is updated to use a const ComposerData.
6364
ABSL_DEPRECATED("Do not use this constructor except in converter_request.h")
6465
ComposerData() = default;
6566

@@ -144,8 +145,8 @@ class ComposerData {
144145
};
145146

146147
// Composer is a class that manages the composing text. It provides methods to
147-
// edit the text by users. Composer creates ComposerData as the snapshot of the
148-
// current state of the composer.
148+
// edit the text by users. Composer creates ComposerData as the snapshot of
149+
// the current state of the composer.
149150
class Composer final {
150151
public:
151152
// Pseudo commands in composer.
@@ -155,7 +156,7 @@ class Composer final {
155156
};
156157

157158
Composer();
158-
Composer(const Table &table, const commands::Request &request,
159+
Composer(std::shared_ptr<const Table> table, const commands::Request &request,
159160
const config::Config &config);
160161
// This constructor is for testing.
161162
ABSL_DEPRECATED("Use the constructor with Table")
@@ -188,7 +189,7 @@ class Composer final {
188189
// Check the preedit string is empty or not.
189190
bool Empty() const;
190191

191-
void SetTable(const Table &table);
192+
void SetTable(std::shared_ptr<const Table> table);
192193

193194
void SetRequest(const commands::Request &request);
194195
void SetConfig(const config::Config &config);
@@ -390,9 +391,17 @@ class Composer final {
390391

391392
size_t max_length_;
392393

394+
// TODO(all): Stop using raw pointer to achieve shared ownership.
393395
const commands::Request *request_ = nullptr;
394396
const config::Config *config_ = nullptr;
395-
const Table *table_ = nullptr;
397+
398+
// Though we would like to avoid shared object, Table is not copyable so
399+
// there is no other way to share them at this moment. The internal data
400+
// of the Table is managed by std::unique_ptr, which makes simple copying
401+
// impossible. Furthermore, copying the table every time would result in
402+
// a significant performance degradation. Style guide says that we prefer
403+
// to use std::shared_ptr for shared object.
404+
std::shared_ptr<const Table> table_;
396405

397406
// Timestamp of last modified.
398407
int64_t timestamp_msec_ = 0;

src/composer/composer_main.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ using ::mozc::config::Config;
5050
int main(int argc, char **argv) {
5151
mozc::InitMozc(argv[0], &argc, &argv);
5252

53-
mozc::composer::Table table;
54-
table.LoadFromFile(absl::GetFlag(FLAGS_table).c_str());
53+
auto table = std::make_shared<mozc::composer::Table>();
54+
table->LoadFromFile(absl::GetFlag(FLAGS_table).c_str());
5555
auto composer = std::make_unique<mozc::composer::Composer>(
5656
table, Request::default_instance(), Config::default_instance());
5757

src/composer/composer_test.cc

+6-6
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ class ComposerTest : public ::testing::Test {
107107
~ComposerTest() override = default;
108108

109109
void SetUp() override {
110-
table_ = std::make_unique<Table>();
110+
table_ = std::make_shared<Table>();
111111
config_ = std::make_unique<Config>();
112112
request_ = std::make_unique<Request>();
113-
composer_ = std::make_unique<Composer>(*table_, *request_, *config_);
113+
composer_ = std::make_unique<Composer>(table_, *request_, *config_);
114114
CharacterFormManager::GetCharacterFormManager()->SetDefaultRule();
115115
}
116116

@@ -123,7 +123,7 @@ class ComposerTest : public ::testing::Test {
123123
}
124124

125125
std::unique_ptr<Composer> composer_;
126-
std::unique_ptr<Table> table_;
126+
std::shared_ptr<Table> table_;
127127
std::unique_ptr<Request> request_;
128128
std::unique_ptr<Config> config_;
129129
};
@@ -854,7 +854,7 @@ TEST_F(ComposerTest, InsertCharacterKeyEventWithInputMode) {
854854
EXPECT_EQ(composer_->GetInputMode(), transliteration::HIRAGANA);
855855
}
856856

857-
composer_ = std::make_unique<Composer>(*table_, *request_, *config_);
857+
composer_ = std::make_unique<Composer>(table_, *request_, *config_);
858858

859859
{
860860
// "a" → "あ" (Hiragana)
@@ -1256,7 +1256,7 @@ TEST_F(ComposerTest, AutoIMETurnOffEnabled) {
12561256
EXPECT_EQ(composer_->GetInputMode(), transliteration::HIRAGANA);
12571257
}
12581258

1259-
composer_ = std::make_unique<Composer>(*table_, *request_, *config_);
1259+
composer_ = std::make_unique<Composer>(table_, *request_, *config_);
12601260

12611261
{ // google
12621262
InsertKey("g", composer_.get());
@@ -1321,7 +1321,7 @@ TEST_F(ComposerTest, AutoIMETurnOffEnabled) {
13211321
}
13221322

13231323
config_->set_shift_key_mode_switch(Config::OFF);
1324-
composer_ = std::make_unique<Composer>(*table_, *request_, *config_);
1324+
composer_ = std::make_unique<Composer>(table_, *request_, *config_);
13251325

13261326
{ // Google
13271327
InsertKey("G", composer_.get());

src/composer/internal/char_chunk.cc

+8-6
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "composer/internal/char_chunk.h"
3131

3232
#include <cstddef>
33+
#include <memory>
3334
#include <string>
3435
#include <tuple>
3536
#include <utility>
@@ -111,13 +112,14 @@ bool GetFromPending(const Table *table, const absl::string_view key,
111112
} // namespace
112113

113114
CharChunk::CharChunk(Transliterators::Transliterator transliterator,
114-
const Table &table)
115-
: table_(&table), transliterator_(transliterator) {
115+
std::shared_ptr<const Table> table)
116+
: table_(table), transliterator_(transliterator) {
117+
DCHECK(table_);
116118
DCHECK_NE(transliterator, Transliterators::LOCAL);
117119
}
118120

119121
CharChunk::CharChunk(Transliterators::Transliterator transliterator)
120-
: transliterator_(transliterator) {
122+
: table_(Table::GetSharedDefaultTable()), transliterator_(transliterator) {
121123
DCHECK_NE(transliterator, Transliterators::LOCAL);
122124
}
123125

@@ -244,7 +246,7 @@ absl::btree_set<std::string> CharChunk::GetExpandedResults() const {
244246
continue;
245247
}
246248
absl::btree_set<std::string> loop_result;
247-
if (!GetFromPending(table_, entry->pending(), kMaxRecursion,
249+
if (!GetFromPending(table_.get(), entry->pending(), kMaxRecursion,
248250
&loop_result)) {
249251
continue;
250252
}
@@ -261,7 +263,7 @@ bool CharChunk::IsAppendable(Transliterators::Transliterator t12r,
261263
const Table &table) const {
262264
return !pending_.empty() &&
263265
(t12r == Transliterators::LOCAL || t12r == transliterator_) &&
264-
&table == table_;
266+
&table == table_.get();
265267
}
266268

267269
bool CharChunk::IsConvertible(Transliterators::Transliterator t12r,
@@ -565,7 +567,7 @@ absl::StatusOr<CharChunk> CharChunk::SplitChunk(
565567
DeleteSpecialKeys(conversion_ + pending_), &raw_lhs, &raw_rhs,
566568
&converted_lhs, &converted_rhs);
567569

568-
CharChunk left_new_chunk(transliterator_, *table_);
570+
CharChunk left_new_chunk(transliterator_, table_);
569571
left_new_chunk.set_raw(raw_lhs);
570572
set_raw(std::move(raw_rhs));
571573

src/composer/internal/char_chunk.h

+8-6
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
#include <tuple>
3636
#include <utility>
3737

38-
#include "absl/container/btree_set.h"
3938
#include "absl/base/attributes.h"
39+
#include "absl/container/btree_set.h"
4040
#include "absl/status/statusor.h"
4141
#include "absl/strings/str_format.h"
4242
#include "absl/strings/string_view.h"
@@ -56,7 +56,8 @@ namespace composer {
5656
class CharChunk final {
5757
public:
5858
// LOCAL transliterator is not accepted.
59-
CharChunk(Transliterators::Transliterator transliterator, const Table &table);
59+
CharChunk(Transliterators::Transliterator transliterator,
60+
std::shared_ptr<const Table> table);
6061
// This constructor is for testing.
6162
ABSL_DEPRECATED("Use the constructor with Table")
6263
explicit CharChunk(Transliterators::Transliterator transliterator);
@@ -142,7 +143,7 @@ class CharChunk final {
142143
Transliterators::Transliterator transliterator() const {
143144
return transliterator_;
144145
}
145-
const Table *table() const { return table_; }
146+
std::shared_ptr<const Table> table_for_testing() const { return table_; }
146147

147148
const std::string &raw() const { return raw_; }
148149
template <typename String>
@@ -191,8 +192,9 @@ class CharChunk final {
191192
absl::Format(&sink,
192193
"table = %p, raw = %s, conversion = %s, pending = %s, "
193194
"ambiguous = %s, transliterator = %v, attributes = %v",
194-
chunk.table_, chunk.raw_, chunk.conversion_, chunk.pending_,
195-
chunk.ambiguous_, chunk.transliterator_, chunk.attributes_);
195+
chunk.table_.get(), chunk.raw_, chunk.conversion_,
196+
chunk.pending_, chunk.ambiguous_, chunk.transliterator_,
197+
chunk.attributes_);
196198
}
197199

198200
// bool = should loop
@@ -202,7 +204,7 @@ class CharChunk final {
202204
private:
203205
void AddInputAndConvertedChar(CompositionInput *composition_input);
204206

205-
const Table *table_ = nullptr;
207+
std::shared_ptr<const Table> table_;
206208

207209
// There are four variables to represent a composing text:
208210
// `raw_`, `conversion_`, `pending_`, and `ambiguous_`.

0 commit comments

Comments
 (0)