| 70 | }; |
| 71 | |
| 72 | port::Status MultiPlatformManagerImpl::RegisterPlatform( |
| 73 | std::unique_ptr<Platform> platform) { |
| 74 | CHECK(platform != nullptr); |
| 75 | string key = absl::AsciiStrToLower(platform->Name()); |
| 76 | absl::MutexLock lock(&mu_); |
| 77 | if (name_map_.find(key) != name_map_.end()) { |
| 78 | return port::Status(port::error::INTERNAL, |
| 79 | "platform is already registered with name: \"" + |
| 80 | platform->Name() + "\""); |
| 81 | } |
| 82 | Platform* platform_ptr = platform.get(); |
| 83 | CHECK(id_map_.emplace(platform->id(), platform_ptr).second); |
| 84 | // Release ownership/uniqueness to prevent destruction on program exit. |
| 85 | // This avoids Platforms "cleaning up" on program exit, because otherwise, |
| 86 | // there are _very_ tricky races between StreamExecutor and underlying |
| 87 | // platforms (CUDA, OpenCL) during exit. Since these are fixed-size and 1x per |
| 88 | // program, these are deemed acceptable. |
| 89 | name_map_[key] = platform.release(); |
| 90 | for (const auto& listener : listeners_) { |
| 91 | listener->PlatformRegistered(platform_ptr); |
| 92 | } |
| 93 | return port::Status::OK(); |
| 94 | } |
| 95 | |
| 96 | port::StatusOr<Platform*> MultiPlatformManagerImpl::PlatformWithName( |
| 97 | absl::string_view target) { |