19#ifndef FILEHANDLER_IMPL
20#error "This file should not be included directly! Use FileHandler.h instead"
26template <
typename TFD>
28 auto manager = m_file_manager.lock();
31 UniqueLock unique_lock(m_file_mutex, boost::defer_lock);
32 if (try_lock && !unique_lock.try_lock()) {
38 std::unique_ptr<FdWrapper> fd_ptr;
40 std::unique_lock<std::mutex> this_lock(m_handler_mutex);
44 for (
auto& fd : m_available_fd) {
47 m_available_fd.clear();
48 m_is_readonly =
false;
51 assert(m_available_fd.size() <= 1);
54 if (!m_available_fd.empty()) {
55 auto typed_ptr =
dynamic_cast<TypedFdWrapper<TFD>*
>(m_available_fd.begin()->
second.get());
57 m_available_fd.clear();
62 if (m_available_fd.empty()) {
64 auto fd = manager->open<TFD>(m_path,
true, [
this](
FileManager::FileId id) {
return this->close(
id); });
66 m_available_fd[fd.first].reset(
new TypedFdWrapper<TFD>(fd.first,
std::move(fd.second), manager.get()));
69 assert(m_available_fd.size() == 1);
72 fd_ptr =
std::move(m_available_fd.begin()->second);
73 m_available_fd.clear();
76 auto typed_ptr =
dynamic_cast<TypedFdWrapper<TFD>*
>(fd_ptr.
get());
77 if (typed_ptr ==
nullptr) {
78 throw std::logic_error(
"Failed to cast type-erased file descriptor wrapper");
81 auto id = typed_ptr->m_id;
83 auto return_callback = [
this, id, manager](TFD&& returned_fd) {
84 std::lock_guard<std::mutex> lambda_this_lock(m_handler_mutex);
86 std::unique_ptr<TypedFdWrapper<TFD>>(
new TypedFdWrapper<TFD>(
id,
std::move(returned_fd), manager.get()));
89 manager->notifyUsed(
id);
90 return std::unique_ptr<FileWriteAccessor<TFD>>(
94template <
typename TFD>
96 auto manager = m_file_manager.lock();
99 SharedLock shared_lock(m_file_mutex, boost::defer_lock);
100 if (try_lock && !shared_lock.try_lock()) {
106 std::unique_ptr<FdWrapper> fd_ptr =
nullptr;
108 std::unique_lock<std::mutex> this_lock(m_handler_mutex);
111 if (!m_is_readonly) {
112 for (
auto& fd : m_available_fd) {
115 m_available_fd.clear();
116 m_is_readonly =
true;
120 auto avail_i = m_available_fd.begin();
121 TypedFdWrapper<TFD>* typed_ptr =
nullptr;
122 while (typed_ptr ==
nullptr && avail_i != m_available_fd.end()) {
123 if ((typed_ptr =
dynamic_cast<TypedFdWrapper<TFD>*
>(avail_i->second.get())) ==
nullptr)
130 auto fd = manager->open<TFD>(m_path,
false, [
this](
FileManager::FileId id) {
return this->close(
id); });
131 typed_ptr =
new TypedFdWrapper<TFD>(fd.first,
std::move(fd.second), manager.get());
133 avail_i = m_available_fd.emplace(fd.first, std::unique_ptr<TypedFdWrapper<TFD>>(typed_ptr)).first;
136 assert(typed_ptr && avail_i != m_available_fd.end());
139 m_available_fd.erase(avail_i);
143 TypedFdWrapper<TFD>* typed_ptr =
dynamic_cast<TypedFdWrapper<TFD>*
>(fd_ptr.
get());
144 if (typed_ptr ==
nullptr) {
145 throw std::logic_error(
"Failed to cast type-erased file descriptor wrapper");
148 auto id = typed_ptr->m_id;
150 auto return_callback = [
this, id, manager](TFD&& returned_fd) {
151 std::lock_guard<std::mutex> lambda_this_lock(m_handler_mutex);
153 std::unique_ptr<TypedFdWrapper<TFD>>(
new TypedFdWrapper<TFD>(
id,
std::move(returned_fd), manager.get()));
156 manager->notifyUsed(
id);
157 return std::unique_ptr<FileReadAccessor<TFD>>(
161template <
typename TFD>
163 bool write_bool = mode & kWrite;
164 bool try_bool = mode & kTry;
167 return getWriteAccessor<TFD>(try_bool);
169 return getReadAccessor<TFD>(try_bool);
std::unique_ptr< FileAccessor< TFD > > getAccessor(Mode mode=kRead)
std::unique_ptr< FileAccessor< TFD > > getReadAccessor(bool try_lock)
std::unique_ptr< FileAccessor< TFD > > getWriteAccessor(bool try_lock)
intptr_t FileId
Opaque FileId, its concrete type should only be assumed to be copyable and hashable.