int DiscoveryClient::Register(const DiscoveryRegisterParam& req) { if (!req.IsValid()) { return -1; } if (_registered.load(butil::memory_order_relaxed) || _registered.exchange(true, butil::memory_order_release)) { return 0; } pthread_once(&s_init_channel_once, InitChannel); _appid = req.appid; _hostname = req.hostname; _addrs = req.addrs; _env = req.env; _region = req.region; _zone = req.zone; _status = req.status; _version = req.version; _metadata = req.metadata; if (DoRegister() != 0) { return -1; } if (bthread_start_background(&_th, NULL, PeriodicRenew, this) != 0) { LOG(ERROR) << "Fail to start background PeriodicRenew"; return -1; } return 0; }
int EventDispatcher::Start(const bthread_attr_t* consumer_thread_attr) { if (_epfd < 0) { LOG(FATAL) << "epoll was not created"; return -1; } if (_tid != 0) { LOG(FATAL) << "Already started this dispatcher(" << this << ") in bthread=" << _tid; return -1; } // Set _consumer_thread_attr before creating epoll thread to make sure // everyting seems sane to the thread. _consumer_thread_attr = (consumer_thread_attr ? *consumer_thread_attr : BTHREAD_ATTR_NORMAL); // Polling thread uses the same attr for consumer threads (NORMAL right // now). Previously, we used small stack (32KB) which may be overflowed // when the older comlog (e.g. 3.1.85) calls com_openlog_r(). Since this // is also a potential issue for consumer threads, using the same attr // should be a reasonable solution. int rc = bthread_start_background( &_tid, &_consumer_thread_attr, RunThis, this); if (rc) { LOG(FATAL) << "Fail to create epoll thread: " << berror(rc); return -1; } return 0; }
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"; }
void RemoteFileCopier::Session::on_timer(void* arg) { bthread_t tid; if (bthread_start_background( &tid, NULL, send_next_rpc_on_timedout, arg) != 0) { PLOG(ERROR) << "Fail to start bthread"; send_next_rpc_on_timedout(arg); } }
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)); }
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; }
void RepeatedTimerTask::on_timedout(void* arg) { // Start a bthread to invoke run() so we won't block the timer thread. // as run() might access the disk so the time it takes is probably beyond // expection bthread_t tid; if (bthread_start_background( &tid, NULL, run_on_timedout_in_new_thread, arg) != 0) { PLOG(ERROR) << "Fail to start bthread"; run_on_timedout_in_new_thread(arg); } }
void BthreadPool<Parameter,TASKNUM>::Init(int T_num) { pool.resize(T_num); for (auto& val : pool) { //normal func is two parameter if (bthread_start_background(&val,NULL,&Run,(void*)this)!= 0) { Csz::ErrQuit("Bthrad Pool create bthread failed"); } } }
int start(int epoll_size) { if (started()) { return -1; } _epfd = epoll_create(epoll_size); if (_epfd < 0) { PLOG(FATAL) << "Fail to epoll_create"; return -1; } if (bthread_start_background( &_tid, NULL, EpollThread::run_this, this) != 0) { close(_epfd); _epfd = -1; LOG(FATAL) << "Fail to create epoll bthread"; return -1; } return 0; }
int Stream::TriggerOnWritable(bthread_id_t id, void *data, int error_code) { WritableMeta *wm = (WritableMeta*)data; if (wm->has_timer) { bthread_timer_del(wm->timer); } wm->error_code = error_code; if (wm->new_thread) { const bthread_attr_t* attr = FLAGS_usercode_in_pthread ? &BTHREAD_ATTR_PTHREAD : &BTHREAD_ATTR_NORMAL; bthread_t tid; if (bthread_start_background(&tid, attr, RunOnWritable, wm) != 0) { LOG(FATAL) << "Fail to start bthread" << berror(); RunOnWritable(wm); } } else { RunOnWritable(wm); } return bthread_id_unlock_and_destroy(id); }
void StreamWait(StreamId stream_id, const timespec *due_time, void (*on_writable)(StreamId, void*, int), void *arg) { SocketUniquePtr ptr; if (Socket::Address(stream_id, &ptr) != 0) { Stream::WritableMeta* wm = new Stream::WritableMeta; wm->id = stream_id; wm->arg= arg; wm->has_timer = false; wm->on_writable = on_writable; wm->error_code = EINVAL; const bthread_attr_t* attr = FLAGS_usercode_in_pthread ? &BTHREAD_ATTR_PTHREAD : &BTHREAD_ATTR_NORMAL; bthread_t tid; if (bthread_start_background(&tid, attr, Stream::RunOnWritable, wm) != 0) { PLOG(FATAL) << "Fail to start bthread"; Stream::RunOnWritable(wm); } return; } Stream* s = (Stream*)ptr->conn(); return s->Wait(on_writable, arg, due_time); }
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 = 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; }
void Echo(google::protobuf::RpcController* cntl_base, const example::EchoRequest* request, example::EchoResponse* response, google::protobuf::Closure* done) { brpc::ClosureGuard done_guard(done); brpc::Controller* cntl = static_cast<brpc::Controller*>(cntl_base); // Get the session-local data which is created by ServerOptions.session_local_data_factory // and reused between different RPC. All session-local data are // destroyed upon server destruction. MySessionLocalData* sd = static_cast<MySessionLocalData*>(cntl->session_local_data()); if (sd == NULL) { cntl->SetFailed("Require ServerOptions.session_local_data_factory to be" " set with a correctly implemented instance"); LOG(ERROR) << cntl->ErrorText(); return; } const int expected_value = sd->x + (((uintptr_t)cntl) & 0xFFFFFFFF); sd->x = expected_value; // Get the thread-local data which is created by ServerOptions.thread_local_data_factory // and reused between different threads. All thread-local data are // destroyed upon server destruction. // "tls" is short for "thread local storage". MyThreadLocalData* tls = static_cast<MyThreadLocalData*>(brpc::thread_local_data()); if (tls == NULL) { cntl->SetFailed("Require ServerOptions.thread_local_data_factory " "to be set with a correctly implemented instance"); LOG(ERROR) << cntl->ErrorText(); return; } tls->y = expected_value; // You can create bthread-local data for your own. // The interfaces are similar with pthread equivalence: // pthread_key_create -> bthread_key_create // pthread_key_delete -> bthread_key_delete // pthread_getspecific -> bthread_getspecific // pthread_setspecific -> bthread_setspecific MyThreadLocalData* tls2 = static_cast<MyThreadLocalData*>(bthread_getspecific(_tls2_key)); if (tls2 == NULL) { tls2 = new MyThreadLocalData; CHECK_EQ(0, bthread_setspecific(_tls2_key, tls2)); } tls2->y = expected_value + 1; // sleep awhile to force context switching. bthread_usleep(10000); // tls is unchanged after context switching. CHECK_EQ(tls, brpc::thread_local_data()); CHECK_EQ(expected_value, tls->y); CHECK_EQ(tls2, bthread_getspecific(_tls2_key)); CHECK_EQ(expected_value + 1, tls2->y); // Process the request asynchronously. AsyncJob* job = new AsyncJob; job->expected_session_local_data = sd; job->expected_session_value = expected_value; job->cntl = cntl; job->request = request; job->response = response; job->done = done; bthread_t th; CHECK_EQ(0, bthread_start_background(&th, NULL, process_thread, job)); // We don't want to call done->Run() here, release the guard. done_guard.release(); LOG_EVERY_SECOND(INFO) << "ntls=" << ntls.load(butil::memory_order_relaxed) << " nsd=" << nsd.load(butil::memory_order_relaxed); }
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; }