void add(T v) const { std::unique_lock<std::mutex> guard(lock); if (!count.empty()) { if (values.size() == count.get()) remove_oldest(); } if (!period.empty()) { auto now = coordination.now(); while (!time_points.empty() && (now - time_points.front() > period.get())) remove_oldest(); time_points.push_back(now); } values.push_back(std::move(v)); }
void bin_index_t::file_node::add_page(const page_ptr& p) { pages[p->page_offset]=p; insert_into_list(p,first_page.lock()); remove_oldest(); }
file_view file_view_pool::open_file(storage_index_t st, std::string const& p , file_index_t const file_index, file_storage const& fs , open_mode_t const m) { // potentially used to hold a reference to a file object that's // about to be destructed. If we have such object we assign it to // this member to be destructed after we release the std::mutex. On some // operating systems (such as OSX) closing a file may take a long // time. We don't want to hold the std::mutex for that. std::shared_ptr<file_mapping> defer_destruction; std::unique_lock<std::mutex> l(m_mutex); TORRENT_ASSERT(is_complete(p)); auto& key_view = m_files.get<0>(); auto const i = key_view.find(file_id{st, file_index}); if (i != key_view.end()) { key_view.modify(i, [&](file_entry& e) { e.last_use = aux::time_now(); // make sure the write bit is set if we asked for it // it's OK to use a read-write file if we just asked for read. But if // we asked for write, the file we serve back must be opened in write // mode if (!(e.mode & open_mode::write) && (m & open_mode::write)) { defer_destruction = std::move(e.mapping); e.mapping = std::make_shared<file_mapping>( file_handle(fs.file_path(file_index, p) , fs.file_size(file_index), m), m , fs.file_size(file_index)); e.mode = m; } }); auto& lru_view = m_files.get<1>(); lru_view.relocate(m_files.project<1>(i), lru_view.begin()); return i->mapping->view(); } if (int(m_files.size()) >= m_size - 1) { // the file cache is at its maximum size, close // the least recently used file remove_oldest(l); } l.unlock(); file_entry e({st, file_index}, fs.file_path(file_index, p), m , fs.file_size(file_index)); auto ret = e.mapping->view(); l.lock(); auto& key_view2 = m_files.get<0>(); key_view2.insert(std::move(e)); return ret; }
void file_pool::resize(int size) { TORRENT_ASSERT(size > 0); if (size == m_size) return; mutex::scoped_lock l(m_mutex); m_size = size; if (int(m_files.size()) <= m_size) return; // close the least recently used files while (int(m_files.size()) > m_size) remove_oldest(); }
void file_pool::resize(int size) { std::unique_lock<std::mutex> l(m_mutex); TORRENT_ASSERT(size > 0); if (size == m_size) return; m_size = size; if (int(m_files.size()) <= m_size) return; // close the least recently used files while (int(m_files.size()) > m_size) remove_oldest(l); }
// ---------------------------------------------------------------------------- // -- Function : private add(val) // -- // -- Takes : val = the value to add to the array // -- // -- Purpose : Adds a value to the array, making sure the array never // becomes larger than m_maxValueCount void ValueHistoryTable::add(double val) { // Make sure the array size is 1 less than the max count if (int(m_values->size()) >= m_maxValuesCount) { // We need to prune the array by removing the oldest value remove_oldest(); } // Add the value to the end of the array m_values->push_back(val); // Update the bounds update_bounds(val); }
file_handle file_pool::open_file(void* st, std::string const& p , int file_index, file_storage const& fs, int m, error_code& ec) { // potentially used to hold a reference to a file object that's // about to be destructed. If we have such object we assign it to // this member to be destructed after we release the mutex. On some // operating systems (such as OSX) closing a file may take a long // time. We don't want to hold the mutex for that. file_handle defer_destruction; mutex::scoped_lock l(m_mutex); #if TORRENT_USE_ASSERTS // we're not allowed to open a file // from a deleted storage! TORRENT_ASSERT(std::find(m_deleted_storages.begin(), m_deleted_storages.end(), std::make_pair(fs.name(), (void const*)&fs)) == m_deleted_storages.end()); #endif TORRENT_ASSERT(st != 0); TORRENT_ASSERT(is_complete(p)); TORRENT_ASSERT((m & file::rw_mask) == file::read_only || (m & file::rw_mask) == file::read_write); file_set::iterator i = m_files.find(std::make_pair(st, file_index)); if (i != m_files.end()) { lru_file_entry& e = i->second; e.last_use = aux::time_now(); if (e.key != st && ((e.mode & file::rw_mask) != file::read_only || (m & file::rw_mask) != file::read_only)) { // this means that another instance of the storage // is using the exact same file. ec = errors::file_collision; return file_handle(); } e.key = st; // if we asked for a file in write mode, // and the cached file is is not opened in // write mode, re-open it if ((((e.mode & file::rw_mask) != file::read_write) && ((m & file::rw_mask) == file::read_write)) || (e.mode & file::random_access) != (m & file::random_access)) { // close the file before we open it with // the new read/write privilages, since windows may // file opening a file twice. However, since there may // be outstanding operations on it, we can't close the // file, we can only delete our reference to it. // if this is the only reference to the file, it will be closed defer_destruction = e.file_ptr; e.file_ptr = boost::make_shared<file>(); std::string full_path = fs.file_path(file_index, p); if (!e.file_ptr->open(full_path, m, ec)) { m_files.erase(i); return file_handle(); } #ifdef TORRENT_WINDOWS if (m_low_prio_io) set_low_priority(e.file_ptr); #endif TORRENT_ASSERT(e.file_ptr->is_open()); e.mode = m; } return e.file_ptr; } lru_file_entry e; e.file_ptr = boost::make_shared<file>(); if (!e.file_ptr) { ec = error_code(ENOMEM, get_posix_category()); return e.file_ptr; } std::string full_path = fs.file_path(file_index, p); if (!e.file_ptr->open(full_path, m, ec)) return file_handle(); #ifdef TORRENT_WINDOWS if (m_low_prio_io) set_low_priority(e.file_ptr); #endif e.mode = m; e.key = st; m_files.insert(std::make_pair(std::make_pair(st, file_index), e)); TORRENT_ASSERT(e.file_ptr->is_open()); file_handle file_ptr = e.file_ptr; // the file is not in our cache if ((int)m_files.size() >= m_size) { // the file cache is at its maximum size, close // the least recently used (lru) file from it remove_oldest(l); } return file_ptr; }
boost::intrusive_ptr<file> file_pool::open_file(void* st, std::string const& p , file_storage::iterator fe, file_storage const& fs, int m, error_code& ec) { TORRENT_ASSERT(st != 0); TORRENT_ASSERT(is_complete(p)); TORRENT_ASSERT((m & file::rw_mask) == file::read_only || (m & file::rw_mask) == file::read_write); mutex::scoped_lock l(m_mutex); file_set::iterator i = m_files.find(std::make_pair(st, fs.file_index(*fe))); if (i != m_files.end()) { lru_file_entry& e = i->second; e.last_use = time_now(); if (e.key != st && ((e.mode & file::rw_mask) != file::read_only || (m & file::rw_mask) != file::read_only)) { // this means that another instance of the storage // is using the exact same file. #if BOOST_VERSION >= 103500 ec = errors::file_collision; #endif return boost::intrusive_ptr<file>(); } e.key = st; // if we asked for a file in write mode, // and the cached file is is not opened in // write mode, re-open it if ((((e.mode & file::rw_mask) != file::read_write) && ((m & file::rw_mask) == file::read_write)) || (e.mode & file::no_buffer) != (m & file::no_buffer) || (e.mode & file::random_access) != (m & file::random_access)) { // close the file before we open it with // the new read/write privilages TORRENT_ASSERT(e.file_ptr->refcount() == 1); #if TORRENT_CLOSE_MAY_BLOCK mutex::scoped_lock l(m_closer_mutex); m_queued_for_close.push_back(e.file_ptr); l.unlock(); e.file_ptr = new file; #else e.file_ptr->close(); #endif std::string full_path = combine_path(p, fs.file_path(*fe)); if (!e.file_ptr->open(full_path, m, ec)) { m_files.erase(i); return boost::intrusive_ptr<file>(); } #ifdef TORRENT_WINDOWS // file prio is supported on vista and up #if _WIN32_WINNT >= 0x0600 if (m_low_prio_io) { // TODO: load this function dynamically from Kernel32.dll FILE_IO_PRIORITY_HINT_INFO priorityHint; priorityHint.PriorityHint = IoPriorityHintLow; SetFileInformationByHandle(e.file_ptr->native_handle(), FileIoPriorityHintInfo, &priorityHint, sizeof(PriorityHint)); } #endif #endif TORRENT_ASSERT(e.file_ptr->is_open()); e.mode = m; } TORRENT_ASSERT((e.mode & file::no_buffer) == (m & file::no_buffer)); return e.file_ptr; } // the file is not in our cache if ((int)m_files.size() >= m_size) { // the file cache is at its maximum size, close // the least recently used (lru) file from it remove_oldest(); } lru_file_entry e; e.file_ptr.reset(new (std::nothrow)file); if (!e.file_ptr) { ec = error_code(ENOMEM, get_posix_category()); return e.file_ptr; } std::string full_path = combine_path(p, fs.file_path(*fe)); if (!e.file_ptr->open(full_path, m, ec)) return boost::intrusive_ptr<file>(); e.mode = m; e.key = st; m_files.insert(std::make_pair(std::make_pair(st, fs.file_index(*fe)), e)); TORRENT_ASSERT(e.file_ptr->is_open()); return e.file_ptr; }
file_handle file_pool::open_file(storage_index_t st, std::string const& p , file_index_t const file_index, file_storage const& fs, int m, error_code& ec) { // potentially used to hold a reference to a file object that's // about to be destructed. If we have such object we assign it to // this member to be destructed after we release the std::mutex. On some // operating systems (such as OSX) closing a file may take a long // time. We don't want to hold the std::mutex for that. file_handle defer_destruction; std::unique_lock<std::mutex> l(m_mutex); #if TORRENT_USE_ASSERTS // we're not allowed to open a file // from a deleted storage! TORRENT_ASSERT(std::find(m_deleted_storages.begin(), m_deleted_storages.end() , std::make_pair(fs.name(), static_cast<void const*>(&fs))) == m_deleted_storages.end()); #endif TORRENT_ASSERT(is_complete(p)); TORRENT_ASSERT((m & file::rw_mask) == file::read_only || (m & file::rw_mask) == file::read_write); auto const i = m_files.find(std::make_pair(st, file_index)); if (i != m_files.end()) { lru_file_entry& e = i->second; e.last_use = aux::time_now(); // if we asked for a file in write mode, // and the cached file is is not opened in // write mode, re-open it if ((((e.mode & file::rw_mask) != file::read_write) && ((m & file::rw_mask) == file::read_write)) || (e.mode & file::random_access) != (m & file::random_access)) { file_handle new_file = std::make_shared<file>(); std::string full_path = fs.file_path(file_index, p); if (!new_file->open(full_path, m, ec)) return file_handle(); #ifdef TORRENT_WINDOWS if (m_low_prio_io) set_low_priority(new_file); #endif TORRENT_ASSERT(new_file->is_open()); defer_destruction = std::move(e.file_ptr); e.file_ptr = std::move(new_file); e.mode = m; } return e.file_ptr; } lru_file_entry e; e.file_ptr = std::make_shared<file>(); if (!e.file_ptr) { ec = error_code(boost::system::errc::not_enough_memory, generic_category()); return file_handle(); } std::string full_path = fs.file_path(file_index, p); if (!e.file_ptr->open(full_path, m, ec)) return file_handle(); #ifdef TORRENT_WINDOWS if (m_low_prio_io) set_low_priority(e.file_ptr); #endif e.mode = m; file_handle file_ptr = e.file_ptr; m_files.insert(std::make_pair(std::make_pair(st, file_index), e)); TORRENT_ASSERT(file_ptr->is_open()); if (int(m_files.size()) >= m_size) { // the file cache is at its maximum size, close // the least recently used (lru) file from it remove_oldest(l); } return file_ptr; }