bkietz commented on code in PR #39067:
URL: https://github.com/apache/arrow/pull/39067#discussion_r1516127274


##########
cpp/src/arrow/filesystem/filesystem.cc:
##########
@@ -674,6 +685,141 @@ Status CopyFiles(const std::shared_ptr<FileSystem>& 
source_fs,
   return CopyFiles(sources, destinations, io_context, chunk_size, use_threads);
 }
 
+class FileSystemFactoryRegistry {
+ public:
+  static FileSystemFactoryRegistry* GetInstance() {
+    static FileSystemFactoryRegistry registry;
+    return &registry;
+  }
+
+  Result<FileSystemFactory*> FactoryForScheme(const std::string& scheme) {
+    std::shared_lock lock{mutex_};
+    if (finalized_) return AlreadyFinalized();
+
+    auto it = scheme_to_factory_.find(scheme);
+    if (it == scheme_to_factory_.end()) return nullptr;
+
+    return it->second.Map([](const auto& r) { return r.factory; });
+  }
+
+  Status MergeInto(FileSystemFactoryRegistry* main_registry) {
+    std::unique_lock lock{mutex_};
+    if (finalized_) return AlreadyFinalized();
+
+    auto& [main_mutex, main_scheme_to_factory, _] = *main_registry;
+    std::unique_lock main_lock{main_mutex};
+
+    std::vector<std::string_view> duplicated_schemes;
+    for (auto& [scheme, registered] : scheme_to_factory_) {
+      if (!registered.ok()) {
+        duplicated_schemes.emplace_back(scheme);
+        continue;
+      }
+
+      auto [it, success] = main_scheme_to_factory.emplace(std::move(scheme), 
registered);
+      if (success) continue;
+
+      duplicated_schemes.emplace_back(it->first);
+    }
+    scheme_to_factory_.clear();
+
+    if (duplicated_schemes.empty()) return Status::OK();
+    return Status::KeyError("Attempted to register ", 
duplicated_schemes.size(),
+                            " factories for schemes ['",
+                            arrow::internal::JoinStrings(duplicated_schemes, 
"', '"),
+                            "'] but those schemes were already registered.");
+  }
+
+  void EnsureFinalized() {
+    std::unique_lock lock{mutex_};
+    if (finalized_) return;
+
+    for (const auto& [_, registered_or_error] : scheme_to_factory_) {
+      if (!registered_or_error.ok()) continue;
+      registered_or_error->finalizer();
+    }
+    finalized_ = true;
+  }
+
+  Status RegisterFactory(std::string scheme, FileSystemFactory factory,
+                         std::function<void()> finalizer, bool defer_error) {
+    std::unique_lock lock{mutex_};
+    if (finalized_) return AlreadyFinalized();
+
+    auto [it, success] = scheme_to_factory_.emplace(
+        std::move(scheme), Registered{factory, std::move(finalizer)});
+    if (success) {
+      return Status::OK();
+    }
+
+    auto st = Status::KeyError(
+        "Attempted to register factory for "
+        "scheme '",
+        it->first,
+        "' but that scheme is already "
+        "registered.");
+    if (!defer_error) return st;
+
+    it->second = std::move(st);
+    return Status::OK();
+  }
+
+ private:
+  struct Registered {
+    FileSystemFactory* factory;
+    std::function<void()> finalizer;
+  };
+
+  static Status AlreadyFinalized() {
+    return Status::Invalid(
+        "FileSystem factories were already "
+        "finalized!");
+  }
+
+  std::shared_mutex mutex_;
+  std::unordered_map<std::string, Result<Registered>> scheme_to_factory_;
+  bool finalized_ = false;
+};
+
+Status RegisterFileSystemFactory(std::string scheme, FileSystemFactory factory,
+                                 std::function<void()> finalizer) {
+  return FileSystemFactoryRegistry::GetInstance()->RegisterFactory(
+      std::move(scheme), factory, std::move(finalizer),

Review Comment:
   I have changed factory to [also be a 
std::function](https://github.com/apache/arrow/pull/39067/files#diff-82a2d9a8424dfb436344c0802dc36275cd0fb87e2e9eb6399745fba43799f7e5R355-R356)
 for consistency with finalizer, so the std::move is warranted



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to