TEST_F(BthreadTest, start_latency_when_high_idle) { bool warmup = true; long elp1 = 0; long elp2 = 0; int REP = 0; for (int i = 0; i < 10000; ++i) { butil::Timer tm; tm.start(); bthread_t th; bthread_start_urgent(&th, NULL, log_start_latency, &tm); bthread_join(th, NULL); bthread_t th2; butil::Timer tm2; tm2.start(); bthread_start_background(&th2, NULL, log_start_latency, &tm2); bthread_join(th2, NULL); if (!warmup) { ++REP; elp1 += tm.n_elapsed(); elp2 += tm2.n_elapsed(); } else if (i == 100) { warmup = false; } } LOG(INFO) << "start_urgent=" << elp1 / REP << "ns start_background=" << elp2 / REP << "ns"; }
TEST_F(BthreadTest, bthread_equal) { bthread_t th1; ASSERT_EQ(0, bthread_start_urgent(&th1, NULL, do_nothing, NULL)); bthread_t th2; ASSERT_EQ(0, bthread_start_urgent(&th2, NULL, do_nothing, NULL)); ASSERT_EQ(0, bthread_equal(th1, th2)); bthread_t th3 = th2; ASSERT_EQ(1, bthread_equal(th3, th2)); ASSERT_EQ(0, bthread_join(th1, NULL)); ASSERT_EQ(0, bthread_join(th2, NULL)); }
TEST_F(BthreadTest, bthread_usleep) { // NOTE: May fail because worker threads may still be stealing tasks // after previous cases. usleep(10000); bthread_t th1; ASSERT_EQ(0, bthread_start_urgent(&th1, &BTHREAD_ATTR_PTHREAD, check_sleep, (void*)1)); ASSERT_EQ(0, bthread_join(th1, NULL)); bthread_t th2; ASSERT_EQ(0, bthread_start_urgent(&th2, NULL, check_sleep, (void*)0)); ASSERT_EQ(0, bthread_join(th2, NULL)); }
void* check_sleep(void* pthread_task) { EXPECT_TRUE(bthread_self() != 0); // Create a no-signal task that other worker will not steal. The task will be // run if current bthread does context switch. bthread_attr_t attr = BTHREAD_ATTR_NORMAL | BTHREAD_NOSIGNAL; bthread_t th1; pthread_t run = 0; const pthread_t pid = pthread_self(); EXPECT_EQ(0, bthread_start_urgent(&th1, &attr, mark_run, &run)); if (pthread_task) { bthread_usleep(100000L); // due to NOSIGNAL, mark_run did not run. // FIXME: actually runs. someone is still stealing. // EXPECT_EQ((pthread_t)0, run); // bthread_usleep = usleep for BTHREAD_ATTR_PTHREAD EXPECT_EQ(pid, pthread_self()); // schedule mark_run bthread_flush(); } else { // start_urgent should jump to the new thread first, then back to // current thread. EXPECT_EQ(pid, run); // should run in the same pthread } EXPECT_EQ(0, bthread_join(th1, NULL)); if (pthread_task) { EXPECT_EQ(pid, pthread_self()); EXPECT_NE((pthread_t)0, run); // the mark_run should run. } return NULL; }
DiscoveryClient::~DiscoveryClient() { if (_registered.load(butil::memory_order_acquire)) { bthread_stop(_th); bthread_join(_th, NULL); DoCancel(); } }
int main(int argc, char* argv[]) { GFLAGS_NS::ParseCommandLineFlags(&argc, &argv, true); // Register configuration of target group to RouteTable if (braft::rtb::update_configuration(FLAGS_group, FLAGS_conf) != 0) { LOG(ERROR) << "Fail to register configuration " << FLAGS_conf << " of group " << FLAGS_group; return -1; } std::vector<bthread_t> tids; std::vector<SendArg> args; for (int i = 1; i <= FLAGS_thread_num; ++i) { SendArg arg = { i }; args.push_back(arg); } tids.resize(FLAGS_thread_num); if (!FLAGS_use_bthread) { for (int i = 0; i < FLAGS_thread_num; ++i) { if (pthread_create( &tids[i], NULL, sender, &args[i]) != 0) { LOG(ERROR) << "Fail to create pthread"; return -1; } } } else { for (int i = 0; i < FLAGS_thread_num; ++i) { if (bthread_start_background( &tids[i], NULL, sender, &args[i]) != 0) { LOG(ERROR) << "Fail to create bthread"; return -1; } } } while (!brpc::IsAskedToQuit()) { sleep(1); LOG_IF(INFO, !FLAGS_log_each_request) << "Sending Request to " << FLAGS_group << " (" << FLAGS_conf << ')' << " at qps=" << g_latency_recorder.qps(1) << " latency=" << g_latency_recorder.latency(1); } LOG(INFO) << "Counter client is going to quit"; for (int i = 0; i < FLAGS_thread_num; ++i) { if (!FLAGS_use_bthread) { pthread_join(tids[i], NULL); } else { bthread_join(tids[i], NULL); } } return 0; }
TEST_F(BthreadTest, bthread_exit) { bthread_t th1; bthread_t th2; pthread_t th3; bthread_t th4; bthread_t th5; const bthread_attr_t attr = BTHREAD_ATTR_PTHREAD; ASSERT_EQ(0, bthread_start_urgent(&th1, NULL, just_exit, NULL)); ASSERT_EQ(0, bthread_start_background(&th2, NULL, just_exit, NULL)); ASSERT_EQ(0, pthread_create(&th3, NULL, just_exit, NULL)); EXPECT_EQ(0, bthread_start_urgent(&th4, &attr, just_exit, NULL)); EXPECT_EQ(0, bthread_start_background(&th5, &attr, just_exit, NULL)); ASSERT_EQ(0, bthread_join(th1, NULL)); ASSERT_EQ(0, bthread_join(th2, NULL)); ASSERT_EQ(0, pthread_join(th3, NULL)); ASSERT_EQ(0, bthread_join(th4, NULL)); ASSERT_EQ(0, bthread_join(th5, NULL)); }
TEST_F(BthreadTest, stop_sleep) { bthread_t th; ASSERT_EQ(0, bthread_start_urgent( &th, NULL, sleep_for_awhile_with_sleep, (void*)1000000L)); butil::Timer tm; tm.start(); bthread_usleep(10000); ASSERT_EQ(0, bthread_stop(th)); ASSERT_EQ(0, bthread_join(th, NULL)); tm.stop(); ASSERT_LE(labs(tm.m_elapsed() - 10), 5); }
void BthreadPool<Parameter,TASKNUM>::Stop() { Csz::LI("[%s->%d]bthread join",__func__,__LINE__); task_list.Stop(); for (const auto& val : pool) { bthread_join(val,nullptr); } if (!pool.empty()) { pool.clear(); } return ; }
// Note: This function does not wake up suspended fd_wait. This is fine // since stop_and_join is only called on program's termination // (g_task_control.stop()), suspended bthreads do not block quit of // worker pthreads and completion of g_task_control.stop(). int stop_and_join() { if (!started()) { return 0; } // No matter what this function returns, _epfd will be set to -1 // (making started() false) to avoid latter stop_and_join() to // enter again. const int saved_epfd = _epfd; _epfd = -1; // epoll_wait cannot be woken up by closing _epfd. We wake up // epoll_wait by inserting a fd continuously triggering EPOLLOUT. // Visibility of _stop: constant EPOLLOUT forces epoll_wait to see // _stop (to be true) finally. _stop = true; int closing_epoll_pipe[2]; if (pipe(closing_epoll_pipe)) { PLOG(FATAL) << "Fail to create closing_epoll_pipe"; return -1; } epoll_event evt = { EPOLLOUT, { NULL } }; if (epoll_ctl(saved_epfd, EPOLL_CTL_ADD, closing_epoll_pipe[1], &evt) < 0) { PLOG(FATAL) << "Fail to add closing_epoll_pipe into epfd=" << saved_epfd; return -1; } const int rc = bthread_join(_tid, NULL); if (rc) { LOG(FATAL) << "Fail to join EpollThread, " << berror(rc); return -1; } close(closing_epoll_pipe[0]); close(closing_epoll_pipe[1]); close(saved_epfd); return 0; }
NamingServiceThread::~NamingServiceThread() { RPC_VLOG << "~NamingServiceThread(" << *this << ')'; // Remove from g_nsthread_map first if (_source_ns != NULL) { const NSKey key = { _source_ns, _service_name }; std::unique_lock<pthread_mutex_t> mu(g_nsthread_map_mutex); if (g_nsthread_map != NULL) { NamingServiceThread** ptr = g_nsthread_map->seek(key); if (ptr != NULL && *ptr == this) { g_nsthread_map->erase(key); } } } if (_tid) { bthread_stop(_tid); bthread_join(_tid, NULL); _tid = 0; } { BAIDU_SCOPED_LOCK(_mutex); std::vector<ServerId> to_be_removed; ServerNodeWithId2ServerId(_last_sockets, &to_be_removed, NULL); if (!_last_sockets.empty()) { for (std::map<NamingServiceWatcher*, const NamingServiceFilter*>::iterator it = _watchers.begin(); it != _watchers.end(); ++it) { it->first->OnRemovedServers(to_be_removed); } } _watchers.clear(); } if (_ns) { _ns->Destroy(); _ns = NULL; } }
TEST_F(BthreadTest, start_bthreads_frequently) { sleep_in_adding_func = 0; char prof_name[32]; snprintf(prof_name, sizeof(prof_name), "start_bthreads_frequently.prof"); const int con = bthread_getconcurrency(); ASSERT_GT(con, 0); AlignedCounter* counters = new AlignedCounter[con]; bthread_t th[con]; std::cout << "Perf with different parameters..." << std::endl; //ProfilerStart(prof_name); for (int cur_con = 1; cur_con <= con; ++cur_con) { stop = false; for (int i = 0; i < cur_con; ++i) { counters[i].value = 0; ASSERT_EQ(0, bthread_start_urgent( &th[i], NULL, bthread_starter, &counters[i].value)); } butil::Timer tm; tm.start(); bthread_usleep(200000L); stop = true; for (int i = 0; i < cur_con; ++i) { bthread_join(th[i], NULL); } tm.stop(); size_t sum = 0; for (int i = 0; i < cur_con; ++i) { sum += counters[i].value * 1000 / tm.m_elapsed(); } std::cout << sum << ","; } std::cout << std::endl; //ProfilerStop(); delete [] counters; }
void EventDispatcher::Join() { if (_tid) { bthread_join(_tid, NULL); _tid = 0; } }
int main(int argc, char* argv[]) { // Parse gflags. We recommend you to use gflags as well. GFLAGS_NS::ParseCommandLineFlags(&argc, &argv, true); // A Channel represents a communication line to a Server. Notice that // Channel is thread-safe and can be shared by all threads in your program. brpc::Channel channel; // Initialize the channel, NULL means using default options. brpc::ChannelOptions options; options.protocol = FLAGS_protocol; options.connection_type = FLAGS_connection_type; options.timeout_ms = FLAGS_timeout_ms/*milliseconds*/; options.max_retry = FLAGS_max_retry; if (channel.Init(FLAGS_server.c_str(), FLAGS_load_balancer.c_str(), &options) != 0) { LOG(ERROR) << "Fail to initialize channel"; return -1; } if (FLAGS_attachment_size > 0) { g_attachment.resize(FLAGS_attachment_size, 'a'); } if (FLAGS_request_size <= 0) { LOG(ERROR) << "Bad request_size=" << FLAGS_request_size; return -1; } g_request.resize(FLAGS_request_size, 'r'); std::vector<bthread_t> bids; std::vector<pthread_t> pids; if (!FLAGS_use_bthread) { pids.resize(FLAGS_thread_num); for (int i = 0; i < FLAGS_thread_num; ++i) { if (pthread_create(&pids[i], NULL, sender, &channel) != 0) { LOG(ERROR) << "Fail to create pthread"; return -1; } } } else { bids.resize(FLAGS_thread_num); for (int i = 0; i < FLAGS_thread_num; ++i) { if (bthread_start_background( &bids[i], NULL, sender, &channel) != 0) { LOG(ERROR) << "Fail to create bthread"; return -1; } } } while (!brpc::IsAskedToQuit()) { sleep(1); LOG(INFO) << "Sending EchoRequest at qps=" << g_latency_recorder.qps(1) << " latency=" << g_latency_recorder.latency(1); } LOG(INFO) << "EchoClient is going to quit"; for (int i = 0; i < FLAGS_thread_num; ++i) { if (!FLAGS_use_bthread) { pthread_join(pids[i], NULL); } else { bthread_join(bids[i], NULL); } } return 0; }
TEST_F(BthreadTest, yield_single_thread) { bthread_t tid; ASSERT_EQ(0, bthread_start_background(&tid, NULL, yield_thread, NULL)); ASSERT_EQ(0, bthread_join(tid, NULL)); }
int main(int argc, char* argv[]) { // Parse gflags. We recommend you to use gflags as well. GFLAGS_NS::ParseCommandLineFlags(&argc, &argv, true); // A Channel represents a communication line to a Server. Notice that // Channel is thread-safe and can be shared by all threads in your program. brpc::Channel channel; brpc::ChannelOptions options; options.protocol = FLAGS_protocol; options.connection_type = FLAGS_connection_type; // Initialize the channel, NULL means using default options. // options, see `brpc/channel.h'. if (channel.Init(FLAGS_url.c_str(), FLAGS_load_balancer.c_str(), &options) != 0) { LOG(ERROR) << "Fail to initialize channel"; return -1; } std::vector<bthread_t> bids; std::vector<pthread_t> pids; if (!FLAGS_use_bthread) { pids.resize(FLAGS_thread_num); for (int i = 0; i < FLAGS_thread_num; ++i) { if (pthread_create(&pids[i], NULL, sender, &channel) != 0) { LOG(ERROR) << "Fail to create pthread"; return -1; } } } else { bids.resize(FLAGS_thread_num); for (int i = 0; i < FLAGS_thread_num; ++i) { if (bthread_start_background( &bids[i], NULL, sender, &channel) != 0) { LOG(ERROR) << "Fail to create bthread"; return -1; } } } if (FLAGS_dummy_port >= 0) { brpc::StartDummyServerAt(FLAGS_dummy_port); } while (!brpc::IsAskedToQuit()) { sleep(1); LOG(INFO) << "Sending " << FLAGS_protocol << " requests at qps=" << g_latency_recorder.qps(1) << " latency=" << g_latency_recorder.latency(1); } LOG(INFO) << "benchmark_http is going to quit"; for (int i = 0; i < FLAGS_thread_num; ++i) { if (!FLAGS_use_bthread) { pthread_join(pids[i], NULL); } else { bthread_join(bids[i], NULL); } } return 0; }
int main(int argc, char* argv[]) { // Parse gflags. We recommend you to use gflags as well. GFLAGS_NS::ParseCommandLineFlags(&argc, &argv, true); // A Channel represents a communication line to a Server. Notice that // Channel is thread-safe and can be shared by all threads in your program. brpc::DynamicPartitionChannel channel; brpc::PartitionChannelOptions options; options.protocol = FLAGS_protocol; options.connection_type = FLAGS_connection_type; options.succeed_without_server = true; options.fail_limit = 1; options.timeout_ms = FLAGS_timeout_ms/*milliseconds*/; options.max_retry = FLAGS_max_retry; if (channel.Init(new MyPartitionParser(), FLAGS_server.c_str(), FLAGS_load_balancer.c_str(), &options) != 0) { LOG(ERROR) << "Fail to init channel"; return -1; } if (FLAGS_attachment_size > 0) { g_attachment.resize(FLAGS_attachment_size, 'a'); } if (FLAGS_request_size <= 0) { LOG(ERROR) << "Bad request_size=" << FLAGS_request_size; return -1; } g_request.resize(FLAGS_request_size, 'r'); std::vector<bthread_t> tids; tids.resize(FLAGS_thread_num); if (!FLAGS_use_bthread) { for (int i = 0; i < FLAGS_thread_num; ++i) { if (pthread_create(&tids[i], NULL, sender, &channel) != 0) { LOG(ERROR) << "Fail to create pthread"; return -1; } } } else { for (int i = 0; i < FLAGS_thread_num; ++i) { if (bthread_start_background( &tids[i], NULL, sender, &channel) != 0) { LOG(ERROR) << "Fail to create bthread"; return -1; } } } int64_t last_counter = 0; int64_t last_latency_sum = 0; std::vector<size_t> last_nsuccess(FLAGS_thread_num); while (!brpc::IsAskedToQuit()) { sleep(1); int64_t latency_sum = 0; int64_t nsuccess = 0; pthread_mutex_lock(&g_latency_mutex); CHECK_EQ(g_sender_info.size(), (size_t)FLAGS_thread_num); for (size_t i = 0; i < g_sender_info.size(); ++i) { const SenderInfo& info = g_sender_info[i]; latency_sum += info.latency_sum; nsuccess += info.nsuccess; if (FLAGS_dont_fail) { CHECK(info.nsuccess > last_nsuccess[i]) << "i=" << i; } last_nsuccess[i] = info.nsuccess; } pthread_mutex_unlock(&g_latency_mutex); const int64_t avg_latency = (latency_sum - last_latency_sum) / std::max(nsuccess - last_counter, 1L); LOG(INFO) << "Sending EchoRequest at qps=" << nsuccess - last_counter << " latency=" << avg_latency; last_counter = nsuccess; last_latency_sum = latency_sum; } LOG(INFO) << "EchoClient is going to quit"; for (int i = 0; i < FLAGS_thread_num; ++i) { if (!FLAGS_use_bthread) { pthread_join(tids[i], NULL); } else { bthread_join(tids[i], NULL); } } return 0; }
int main(int argc, char* argv[]) { // Parse gflags. We recommend you to use gflags as well. GFLAGS_NS::ParseCommandLineFlags(&argc, &argv, true); // A Channel represents a communication line to a Server. Notice that // Channel is thread-safe and can be shared by all threads in your program. brpc::Channel channel; // Initialize the channel, NULL means using default options. brpc::ChannelOptions options; options.protocol = brpc::PROTOCOL_REDIS; options.connection_type = FLAGS_connection_type; options.timeout_ms = FLAGS_timeout_ms/*milliseconds*/; options.max_retry = FLAGS_max_retry; options.backup_request_ms = FLAGS_backup_request_ms; if (channel.Init(FLAGS_server.c_str(), &options) != 0) { LOG(ERROR) << "Fail to initialize channel"; return -1; } // Pipeline #batch * #thread_num SET requests into redis so that we // have keys to get. brpc::RedisRequest request; brpc::RedisResponse response; brpc::Controller cntl; for (int i = 0; i < FLAGS_batch * FLAGS_thread_num; ++i) { if (!request.AddCommand("SET %s_%04d %s_%04d", FLAGS_key.c_str(), i, FLAGS_value.c_str(), i)) { LOG(ERROR) << "Fail to SET " << i << "th request"; return -1; } } channel.CallMethod(NULL, &cntl, &request, &response, NULL); if (cntl.Failed()) { LOG(ERROR) << "Fail to access redis, " << cntl.ErrorText(); return -1; } if (FLAGS_batch * FLAGS_thread_num != response.reply_size()) { LOG(ERROR) << "Fail to set"; return -1; } for (int i = 0; i < FLAGS_batch * FLAGS_thread_num; ++i) { CHECK_EQ("OK", response.reply(i).data()); } LOG(INFO) << "Set " << FLAGS_batch * FLAGS_thread_num << " values"; if (FLAGS_dummy_port >= 0) { brpc::StartDummyServerAt(FLAGS_dummy_port); } std::vector<bthread_t> tids; std::vector<SenderArgs> args; tids.resize(FLAGS_thread_num); args.resize(FLAGS_thread_num); for (int i = 0; i < FLAGS_thread_num; ++i) { args[i].base_index = i * FLAGS_batch; args[i].redis_channel = &channel; if (!FLAGS_use_bthread) { if (pthread_create(&tids[i], NULL, sender, &args[i]) != 0) { LOG(ERROR) << "Fail to create pthread"; return -1; } } else { if (bthread_start_background( &tids[i], NULL, sender, &args[i]) != 0) { LOG(ERROR) << "Fail to create bthread"; return -1; } } } while (!brpc::IsAskedToQuit()) { sleep(1); LOG(INFO) << "Accessing redis-server at qps=" << g_latency_recorder.qps(1) << " latency=" << g_latency_recorder.latency(1); } LOG(INFO) << "redis_client is going to quit"; for (int i = 0; i < FLAGS_thread_num; ++i) { if (!FLAGS_use_bthread) { pthread_join(tids[i], NULL); } else { bthread_join(tids[i], NULL); } } return 0; }
int main(int argc, char* argv[]) { // Parse gflags. We recommend you to use gflags as well. GFLAGS_NS::ParseCommandLineFlags(&argc, &argv, true); if (FLAGS_dir.empty() || !butil::DirectoryExists(butil::FilePath(FLAGS_dir))) { LOG(ERROR) << "--dir=<dir-of-dumped-files> is required"; return -1; } if (FLAGS_dummy_port >= 0) { brpc::StartDummyServerAt(FLAGS_dummy_port); } ChannelGroup chan_group; if (chan_group.Init() != 0) { LOG(ERROR) << "Fail to init ChannelGroup"; return -1; } if (FLAGS_thread_num <= 0) { if (FLAGS_qps <= 0) { // unlimited qps FLAGS_thread_num = 50; } else { FLAGS_thread_num = FLAGS_qps / 10000; if (FLAGS_thread_num < 1) { FLAGS_thread_num = 1; } if (FLAGS_thread_num > 50) { FLAGS_thread_num = 50; } } } std::vector<bthread_t> tids; tids.resize(FLAGS_thread_num); if (!FLAGS_use_bthread) { for (int i = 0; i < FLAGS_thread_num; ++i) { if (pthread_create(&tids[i], NULL, replay_thread, &chan_group) != 0) { LOG(ERROR) << "Fail to create pthread"; return -1; } } } else { for (int i = 0; i < FLAGS_thread_num; ++i) { if (bthread_start_background( &tids[i], NULL, replay_thread, &chan_group) != 0) { LOG(ERROR) << "Fail to create bthread"; return -1; } } } brpc::InfoThread info_thr; brpc::InfoThreadOptions info_thr_opt; info_thr_opt.latency_recorder = &g_latency_recorder; info_thr_opt.error_count = &g_error_count; info_thr_opt.sent_count = &g_sent_count; if (!info_thr.start(info_thr_opt)) { LOG(ERROR) << "Fail to create info_thread"; return -1; } for (int i = 0; i < FLAGS_thread_num; ++i) { if (!FLAGS_use_bthread) { pthread_join(tids[i], NULL); } else { bthread_join(tids[i], NULL); } } info_thr.stop(); return 0; }