Skip to content

Commit 99fc614

Browse files
authored
Feat:Runtime state management to avoid duplicate calls (#112)
1 parent 2f5fc31 commit 99fc614

File tree

9 files changed

+230
-65
lines changed

9 files changed

+230
-65
lines changed

trpc/common/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ cc_library(
7575
"//trpc/naming:trpc_naming_registry",
7676
"//trpc/runtime",
7777
"//trpc/runtime:fiber_runtime",
78+
"//trpc/runtime:runtime_state",
7879
"//trpc/runtime:separate_runtime",
7980
"//trpc/runtime/common:periphery_task_scheduler",
8081
"//trpc/serialization:trpc_serialization",
@@ -178,6 +179,7 @@ cc_test(
178179
deps = [
179180
":runtime_manager",
180181
"//trpc/common/config:trpc_config",
182+
"//trpc/util:latch",
181183
"@com_google_googletest//:gtest",
182184
"@com_google_googletest//:gtest_main",
183185
],

trpc/common/runtime_manager.cc

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "trpc/runtime/common/periphery_task_scheduler.h"
2525
#include "trpc/runtime/fiber_runtime.h"
2626
#include "trpc/runtime/runtime.h"
27+
#include "trpc/runtime/runtime_state.h"
2728
#include "trpc/runtime/separate_runtime.h"
2829
#include "trpc/serialization/trpc_serialization.h"
2930
#include "trpc/telemetry/telemetry_factory.h"
@@ -40,6 +41,9 @@
4041

4142
namespace trpc {
4243

44+
// FrameworkRuntime state manager
45+
RuntimeState framework_runtime_state{RuntimeState::kUnknown};
46+
4347
int RunInTrpcRuntime(std::function<int()>&& func) {
4448
const GlobalConfig& global_config = TrpcConfig::GetInstance()->GetGlobalConfig();
4549
const ThreadModelConfig& threadmodel_config = global_config.threadmodel_config;
@@ -121,37 +125,49 @@ int RunInThreadRuntime(std::function<int()>&& func) {
121125
}
122126

123127
int InitFrameworkRuntime() {
124-
const GlobalConfig& global_config = TrpcConfig::GetInstance()->GetGlobalConfig();
125-
const ThreadModelConfig& threadmodel_config = global_config.threadmodel_config;
126-
if (threadmodel_config.use_fiber_flag) {
127-
runtime::SetRuntimeType(runtime::kFiberRuntime);
128-
} else {
129-
TRPC_FMT_ERROR("not running in fiber runtime, please check the framework config.");
130-
return -1;
131-
}
128+
// It can be restarted if it has not been started before or has already been destroyed
129+
if (framework_runtime_state == RuntimeState::kUnknown || framework_runtime_state == RuntimeState::kDestroyed) {
130+
const GlobalConfig& global_config = TrpcConfig::GetInstance()->GetGlobalConfig();
131+
const ThreadModelConfig& threadmodel_config = global_config.threadmodel_config;
132+
if (threadmodel_config.use_fiber_flag) {
133+
runtime::SetRuntimeType(runtime::kFiberRuntime);
134+
} else {
135+
TRPC_FMT_ERROR("not running in fiber runtime, please check the framework config.");
136+
return -1;
137+
}
132138

133-
util::IgnorePipe();
139+
util::IgnorePipe();
134140

135-
// set object pool option
136-
const BufferPoolConfig& buffer_pool_config = global_config.buffer_pool_config;
137-
memory_pool::SetMemBlockSize(buffer_pool_config.block_size);
138-
memory_pool::SetMemPoolThreshold(buffer_pool_config.mem_pool_threshold);
141+
// set object pool option
142+
const BufferPoolConfig& buffer_pool_config = global_config.buffer_pool_config;
143+
memory_pool::SetMemBlockSize(buffer_pool_config.block_size);
144+
memory_pool::SetMemPoolThreshold(buffer_pool_config.mem_pool_threshold);
139145

140-
internal::TimeKeeper::Instance()->Start();
146+
internal::TimeKeeper::Instance()->Start();
141147

142-
if (IsInFiberRuntime()) {
143-
fiber::StartRuntime();
144-
runtime::InitFiberReactorConfig();
148+
if (IsInFiberRuntime()) {
149+
fiber::StartRuntime();
150+
// need to StartAdminRuntime
151+
separate::StartAdminRuntime();
152+
runtime::InitFiberReactorConfig();
153+
}
154+
155+
framework_runtime_state = RuntimeState::kStarted;
156+
return 0;
145157
}
146158

147-
return 0;
159+
return -1;
148160
}
149161

150162
bool IsInFiberRuntime() {
151163
return runtime::IsInFiberRuntime();
152164
}
153165

154-
void DestroyFrameworkRuntime() {
166+
int DestroyFrameworkRuntime() {
167+
if (framework_runtime_state != RuntimeState::kStarted) {
168+
return -1;
169+
}
170+
155171
if (IsInFiberRuntime()) {
156172
separate::TerminateAdminRuntime();
157173

@@ -162,6 +178,10 @@ void DestroyFrameworkRuntime() {
162178
internal::TimeKeeper::Instance()->Join();
163179

164180
TrpcPlugin::GetInstance()->DestroyResource();
181+
182+
framework_runtime_state = RuntimeState::kDestroyed;
183+
184+
return 0;
165185
}
166186

167187
} // namespace trpc

trpc/common/runtime_manager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,6 @@ int InitFrameworkRuntime();
4141
/// @brief Destroy the runtime environment of the framework.
4242
/// @note for compatible, please not use it.
4343
/// @private For internal use purpose only.
44-
void DestroyFrameworkRuntime();
44+
int DestroyFrameworkRuntime();
4545

4646
} // namespace trpc

trpc/common/runtime_manager_fiber_test.cc

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "trpc/common/runtime_manager.h"
1818
#include "trpc/coroutine/fiber.h"
1919
#include "trpc/coroutine/fiber_latch.h"
20+
#include "trpc/util/latch.h"
2021

2122
namespace trpc::testing {
2223

@@ -34,6 +35,50 @@ TEST(RuntimeManager, Run) {
3435
ASSERT_TRUE(running_flag);
3536
}
3637

38+
TEST(RuntimeManager, RunInTrpcRuntimeInTrpcRuntime) {
39+
// Test calling RunInTrpcRuntime again within RunInTrpcRuntime
40+
int ret = ::trpc::RunInTrpcRuntime([]() { return 0; });
41+
assert(ret != 0);
42+
}
43+
44+
// Testing scenarios where InitFrameworkRuntime and DestroyFrameworkRuntime appear in pairs
45+
int TestInitAndDestroyFrameworkRuntime() {
46+
int ret = ::trpc::InitFrameworkRuntime();
47+
assert(ret == 0);
48+
49+
::trpc::Latch l(1);
50+
int count = 0;
51+
bool start_fiber = trpc::StartFiberDetached([&] {
52+
count++;
53+
l.count_down();
54+
});
55+
56+
if (start_fiber) {
57+
l.wait();
58+
assert(count == 1);
59+
}
60+
61+
ret = ::trpc::DestroyFrameworkRuntime();
62+
assert(ret == 0);
63+
64+
return 0;
65+
}
66+
67+
// Test calling twice before and after RunInTrpc
68+
int TestRunInTrpcRuntimeDouble() {
69+
bool running_flag{false};
70+
int ret = ::trpc::RunInTrpcRuntime([&running_flag]() {
71+
running_flag = true;
72+
73+
return 0;
74+
});
75+
76+
assert(ret == 0);
77+
assert(running_flag);
78+
79+
return 0;
80+
}
81+
3782
} // namespace trpc::testing
3883

3984
int InitAndRunAllTests(int argc, char** argv) {
@@ -42,6 +87,12 @@ int InitAndRunAllTests(int argc, char** argv) {
4287
int ret = ::trpc::TrpcConfig::GetInstance()->Init("./trpc/common/testing/fiber_testing.yaml");
4388
assert(ret == 0);
4489

90+
ret = ::trpc::testing::TestInitAndDestroyFrameworkRuntime();
91+
assert(ret == 0);
92+
93+
ret = ::trpc::testing::TestRunInTrpcRuntimeDouble();
94+
assert(ret == 0);
95+
4596
return ::trpc::RunInTrpcRuntime([]() { return ::RUN_ALL_TESTS(); });
4697
}
4798

trpc/runtime/BUILD

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,17 @@ licenses(["notice"])
22

33
package(default_visibility = ["//visibility:public"])
44

5+
cc_library(
6+
name = "runtime_state",
7+
hdrs = ["runtime_state.h"],
8+
)
9+
510
cc_library(
611
name = "fiber_runtime",
712
srcs = ["fiber_runtime.cc"],
813
hdrs = ["fiber_runtime.h"],
914
deps = [
15+
":runtime_state",
1016
"//trpc/common/config:trpc_config",
1117
"//trpc/runtime/threadmodel:thread_model",
1218
"//trpc/runtime/threadmodel:thread_model_manager",
@@ -22,6 +28,7 @@ cc_library(
2228
srcs = ["merge_runtime.cc"],
2329
hdrs = ["merge_runtime.h"],
2430
deps = [
31+
":runtime_state",
2532
"//trpc/common/config:trpc_config",
2633
"//trpc/runtime/iomodel/reactor",
2734
"//trpc/runtime/threadmodel:thread_model",
@@ -40,6 +47,7 @@ cc_library(
4047
srcs = ["separate_runtime.cc"],
4148
hdrs = ["separate_runtime.h"],
4249
deps = [
50+
":runtime_state",
4351
"//trpc/common/config:trpc_config",
4452
"//trpc/runtime/iomodel/reactor",
4553
"//trpc/runtime/threadmodel:thread_model",

trpc/runtime/fiber_runtime.cc

Lines changed: 52 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "trpc/runtime/fiber_runtime.h"
1515

1616
#include "trpc/common/config/trpc_config.h"
17+
#include "trpc/runtime/runtime_state.h"
1718
#include "trpc/runtime/threadmodel/fiber/fiber_thread_model.h"
1819
#include "trpc/runtime/threadmodel/thread_model_manager.h"
1920
#include "trpc/util/likely.h"
@@ -23,6 +24,9 @@
2324

2425
namespace trpc::fiber {
2526

27+
// fiber_threadmodel state manager
28+
RuntimeState fiber_runtime_state{RuntimeState::kUnknown};
29+
2630
// fiber_threadmodel has not owned threadmodel's ownership, it managered by ThreadModelManager
2731
static FiberThreadModel* fiber_threadmodel = nullptr;
2832

@@ -75,56 +79,67 @@ std::ptrdiff_t NearestSchedulingGroupIndex() {
7579
} // namespace detail
7680

7781
void StartRuntime() {
78-
trpc::fiber::FiberThreadModel::Options options;
79-
options.group_id = ThreadModelManager::GetInstance()->GenGroupId();
80-
options.group_name = "";
81-
options.scheduling_name = "v1";
82-
83-
const GlobalConfig& global_config = TrpcConfig::GetInstance()->GetGlobalConfig();
84-
85-
// only support one fiber threadmodel instance
86-
if (global_config.threadmodel_config.fiber_model.size() == 1) {
87-
const auto& conf = global_config.threadmodel_config.fiber_model[0];
88-
if (!conf.fiber_scheduling_name.empty()) {
89-
options.scheduling_name = conf.fiber_scheduling_name;
90-
}
91-
options.group_name = conf.instance_name;
92-
options.concurrency_hint = conf.concurrency_hint;
93-
options.scheduling_group_size = conf.scheduling_group_size;
94-
options.numa_aware = conf.numa_aware;
95-
96-
if (!conf.fiber_worker_accessible_cpus.empty() &&
97-
ParseBindCoreConfig(conf.fiber_worker_accessible_cpus, options.worker_accessible_cpus)) {
98-
// Only when configuring the core binding related settings, strict core binding will take effect.
99-
options.worker_disallow_cpu_migration = conf.fiber_worker_disallow_cpu_migration;
82+
// It can be restarted if it has not been started before or has already been destroyed
83+
if (fiber_runtime_state == RuntimeState::kUnknown || fiber_runtime_state == RuntimeState::kDestroyed) {
84+
trpc::fiber::FiberThreadModel::Options options;
85+
options.group_id = ThreadModelManager::GetInstance()->GenGroupId();
86+
options.group_name = "";
87+
options.scheduling_name = "v1";
88+
89+
const GlobalConfig& global_config = TrpcConfig::GetInstance()->GetGlobalConfig();
90+
91+
// only support one fiber threadmodel instance
92+
if (global_config.threadmodel_config.fiber_model.size() == 1) {
93+
const auto& conf = global_config.threadmodel_config.fiber_model[0];
94+
if (!conf.fiber_scheduling_name.empty()) {
95+
options.scheduling_name = conf.fiber_scheduling_name;
96+
}
97+
options.group_name = conf.instance_name;
98+
options.concurrency_hint = conf.concurrency_hint;
99+
options.scheduling_group_size = conf.scheduling_group_size;
100+
options.numa_aware = conf.numa_aware;
101+
102+
if (!conf.fiber_worker_accessible_cpus.empty() &&
103+
ParseBindCoreConfig(conf.fiber_worker_accessible_cpus, options.worker_accessible_cpus)) {
104+
// Only when configuring the core binding related settings, strict core binding will take effect.
105+
options.worker_disallow_cpu_migration = conf.fiber_worker_disallow_cpu_migration;
106+
}
107+
options.work_stealing_ratio = conf.work_stealing_ratio;
108+
options.cross_numa_work_stealing_ratio = conf.cross_numa_work_stealing_ratio;
109+
options.run_queue_size = conf.fiber_run_queue_size;
110+
options.stack_size = conf.fiber_stack_size;
111+
options.pool_num_by_mmap = conf.fiber_pool_num_by_mmap;
112+
options.stack_enable_guard_page = conf.fiber_stack_enable_guard_page;
113+
options.disable_process_name = global_config.thread_disable_process_name;
114+
options.enable_gdb_debug = conf.enable_gdb_debug;
115+
} else {
116+
options.group_name = "fiber_instance";
100117
}
101-
options.work_stealing_ratio = conf.work_stealing_ratio;
102-
options.cross_numa_work_stealing_ratio = conf.cross_numa_work_stealing_ratio;
103-
options.run_queue_size = conf.fiber_run_queue_size;
104-
options.stack_size = conf.fiber_stack_size;
105-
options.pool_num_by_mmap = conf.fiber_pool_num_by_mmap;
106-
options.stack_enable_guard_page = conf.fiber_stack_enable_guard_page;
107-
options.disable_process_name = global_config.thread_disable_process_name;
108-
options.enable_gdb_debug = conf.enable_gdb_debug;
109-
} else {
110-
options.group_name = "fiber_instance";
111-
}
112118

113-
std::shared_ptr<ThreadModel> fiber_model = std::make_shared<FiberThreadModel>(std::move(options));
119+
std::shared_ptr<ThreadModel> fiber_model = std::make_shared<FiberThreadModel>(std::move(options));
120+
121+
fiber_threadmodel = static_cast<FiberThreadModel*>(fiber_model.get());
114122

115-
fiber_threadmodel = static_cast<FiberThreadModel*>(fiber_model.get());
123+
TRPC_ASSERT(ThreadModelManager::GetInstance()->Register(fiber_model) == true);
116124

117-
TRPC_ASSERT(ThreadModelManager::GetInstance()->Register(fiber_model) == true);
125+
fiber_threadmodel->Start();
118126

119-
fiber_threadmodel->Start();
127+
fiber_runtime_state = RuntimeState::kStarted;
128+
}
120129
}
121130

122131
void TerminateRuntime() {
132+
if (fiber_runtime_state != RuntimeState::kStarted) {
133+
return;
134+
}
135+
123136
fiber_threadmodel->Terminate();
124137

125138
ThreadModelManager::GetInstance()->Del(fiber_threadmodel->GroupName());
126139

127140
fiber_threadmodel = nullptr;
141+
142+
fiber_runtime_state = RuntimeState::kDestroyed;
128143
}
129144

130145
ThreadModel* GetFiberThreadModel() { return fiber_threadmodel; }

0 commit comments

Comments
 (0)