* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#ifndef OMNISTREAM_CLOSEABLEREGISTRY_H
#define OMNISTREAM_CLOSEABLEREGISTRY_H
#include <list>
#include <map>
#include <memory>
#include <utility>
#include <algorithm>
#include <stdexcept>
class Closeable {
public:
virtual void close() = 0;
virtual ~Closeable() = default;
};
template <typename T, typename M, typename L>
class AbstractAutoCloseableRegistry {
public:
virtual ~AbstractAutoCloseableRegistry() = default;
void registerCloseable(T closeable)
{
if (closed) {
closeable->close();
throw std::runtime_error("Cannot register to closed registry");
}
doRegister(closeable, closeableMap);
}
bool unregisterCloseable(T closeable)
{
if (closed) {
return false;
}
return doUnRegister(closeable, closeableMap);
}
void close()
{
if (!closed) {
closed = true;
std::list<T> toClose;
for (const auto& entry : closeableMap) {
toClose.push_back(entry.first);
}
doClose(toClose);
}
}
protected:
explicit AbstractAutoCloseableRegistry(M map) : closeableMap(std::move(map)) {}
virtual void doRegister(T closeable, M& map) = 0;
virtual bool doUnRegister(T closeable, M& map) = 0;
virtual void doClose(std::list<T>& toClose) = 0;
M closeableMap;
bool closed = false;
};
class CloseableRegistry : public AbstractAutoCloseableRegistry<std::shared_ptr<Closeable>,
std::map<std::shared_ptr<Closeable>, void*>, void> {
public:
CloseableRegistry() : AbstractAutoCloseableRegistry(std::map<std::shared_ptr<Closeable>, void*>()) {}
protected:
void doRegister(std::shared_ptr<Closeable> closeable,
std::map<std::shared_ptr<Closeable>,
void*>& closeableMap) override
{
closeableMap[closeable] = DUMMY;
}
bool doUnRegister(std::shared_ptr<Closeable> closeable,
std::map<std::shared_ptr<Closeable>,
void*>& closeableMap) override
{
return closeableMap.erase(closeable) > 0;
}
void doClose(std::list<std::shared_ptr<Closeable>>& toClose) override
{
std::reverse(toClose.begin(), toClose.end());
for (const auto& closeable : toClose) {
try {
closeable->close();
} catch (const std::exception& e) {
throw std::runtime_error("doClose failed: " + std::string(e.what()));
}
}
}
private:
static inline void* DUMMY = nullptr;
};
#endif