| 413 | } |
| 414 | |
| 415 | int GetNamingServiceThread( |
| 416 | butil::intrusive_ptr<NamingServiceThread>* nsthread_out, |
| 417 | const char* url, |
| 418 | const GetNamingServiceThreadOptions* options) { |
| 419 | char protocol[MAX_PROTOCOL_LEN + 1]; |
| 420 | const char* const service_name = ParseNamingServiceUrl(url, protocol); |
| 421 | if (service_name == NULL) { |
| 422 | LOG(ERROR) << "Invalid naming service url=" << url; |
| 423 | return -1; |
| 424 | } |
| 425 | const NamingService* source_ns = NamingServiceExtension()->Find(protocol); |
| 426 | if (source_ns == NULL) { |
| 427 | LOG(ERROR) << "Unknown protocol=" << protocol; |
| 428 | return -1; |
| 429 | } |
| 430 | const NSKey key(protocol, service_name, |
| 431 | (options ? options->channel_signature : ChannelSignature())); |
| 432 | bool new_thread = false; |
| 433 | butil::intrusive_ptr<NamingServiceThread> nsthread; |
| 434 | { |
| 435 | std::unique_lock<pthread_mutex_t> mu(g_nsthread_map_mutex); |
| 436 | if (g_nsthread_map == NULL) { |
| 437 | g_nsthread_map = new (std::nothrow) NamingServiceMap; |
| 438 | if (NULL == g_nsthread_map) { |
| 439 | mu.unlock(); |
| 440 | LOG(ERROR) << "Fail to new g_nsthread_map"; |
| 441 | return -1; |
| 442 | } |
| 443 | if (g_nsthread_map->init(64) != 0) { |
| 444 | LOG(WARNING) << "Fail to init g_nsthread_map"; |
| 445 | } |
| 446 | } |
| 447 | NamingServiceThread*& ptr = (*g_nsthread_map)[key]; |
| 448 | if (ptr != NULL) { |
| 449 | if (ptr->AddRefManually() == 0) { |
| 450 | // The ns thread's last intrusive_ptr was just destructed and |
| 451 | // the removal-from-global-map-code in ptr->~NamingServiceThread() |
| 452 | // is about to run or already running, need to create another ns |
| 453 | // thread. |
| 454 | // Notice that we don't need to remove the reference because |
| 455 | // the object is already destructing. |
| 456 | ptr = NULL; |
| 457 | } else { |
| 458 | nsthread.reset(ptr, false); |
| 459 | } |
| 460 | } |
| 461 | if (ptr == NULL) { |
| 462 | NamingServiceThread* thr = new (std::nothrow) NamingServiceThread; |
| 463 | if (thr == NULL) { |
| 464 | mu.unlock(); |
| 465 | LOG(ERROR) << "Fail to new NamingServiceThread"; |
| 466 | return -1; |
| 467 | } |
| 468 | ptr = thr; |
| 469 | nsthread.reset(ptr); |
| 470 | new_thread = true; |
| 471 | } |
| 472 | } |
no test coverage detected