made file_pool use std::map instead of multi-index, and use std::string::operator< instead of the quite inefficient filesystem::path::operator<
This commit is contained in:
parent
1eb2799a03
commit
9523d88909
|
@ -38,9 +38,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
#include <boost/multi_index_container.hpp>
|
|
||||||
#include <boost/multi_index/member.hpp>
|
|
||||||
#include <boost/multi_index/ordered_index.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
|
@ -53,12 +50,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
|
||||||
using boost::multi_index::multi_index_container;
|
|
||||||
using boost::multi_index::ordered_non_unique;
|
|
||||||
using boost::multi_index::ordered_unique;
|
|
||||||
using boost::multi_index::indexed_by;
|
|
||||||
using boost::multi_index::member;
|
|
||||||
namespace fs = boost::filesystem;
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
struct TORRENT_EXPORT file_pool : boost::noncopyable
|
struct TORRENT_EXPORT file_pool : boost::noncopyable
|
||||||
|
@ -72,28 +63,21 @@ namespace libtorrent
|
||||||
void resize(int size);
|
void resize(int size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void remove_oldest();
|
||||||
|
|
||||||
int m_size;
|
int m_size;
|
||||||
|
|
||||||
struct lru_file_entry
|
struct lru_file_entry
|
||||||
{
|
{
|
||||||
lru_file_entry(): last_use(time_now()) {}
|
lru_file_entry(): last_use(time_now()) {}
|
||||||
mutable boost::shared_ptr<file> file_ptr;
|
mutable boost::shared_ptr<file> file_ptr;
|
||||||
fs::path file_path;
|
|
||||||
void* key;
|
void* key;
|
||||||
ptime last_use;
|
ptime last_use;
|
||||||
int mode;
|
int mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef multi_index_container<
|
typedef std::map<std::string, lru_file_entry> file_set;
|
||||||
lru_file_entry, indexed_by<
|
|
||||||
ordered_unique<member<lru_file_entry, fs::path
|
|
||||||
, &lru_file_entry::file_path> >
|
|
||||||
, ordered_non_unique<member<lru_file_entry, ptime
|
|
||||||
, &lru_file_entry::last_use> >
|
|
||||||
, ordered_non_unique<member<lru_file_entry, void*
|
|
||||||
, &lru_file_entry::key> >
|
|
||||||
>
|
|
||||||
> file_set;
|
|
||||||
|
|
||||||
file_set m_files;
|
file_set m_files;
|
||||||
boost::mutex m_mutex;
|
boost::mutex m_mutex;
|
||||||
|
|
|
@ -60,9 +60,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <boost/iterator_adaptors.hpp>
|
#include <boost/iterator_adaptors.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/limits.hpp>
|
#include <boost/limits.hpp>
|
||||||
#include <boost/multi_index/member.hpp>
|
|
||||||
#include <boost/multi_index/ordered_index.hpp>
|
|
||||||
#include <boost/multi_index_container.hpp>
|
|
||||||
#include <boost/next_prior.hpp>
|
#include <boost/next_prior.hpp>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
|
|
@ -37,9 +37,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
using boost::multi_index::nth_index;
|
|
||||||
using boost::multi_index::get;
|
|
||||||
|
|
||||||
boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p
|
boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p
|
||||||
, int m, error_code& ec)
|
, int m, error_code& ec)
|
||||||
{
|
{
|
||||||
|
@ -48,12 +45,10 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT((m & file::rw_mask) == file::read_only
|
TORRENT_ASSERT((m & file::rw_mask) == file::read_only
|
||||||
|| (m & file::rw_mask) == file::read_write);
|
|| (m & file::rw_mask) == file::read_write);
|
||||||
boost::mutex::scoped_lock l(m_mutex);
|
boost::mutex::scoped_lock l(m_mutex);
|
||||||
typedef nth_index<file_set, 0>::type path_view;
|
file_set::iterator i = m_files.find(p.string());
|
||||||
path_view& pt = get<0>(m_files);
|
if (i != m_files.end())
|
||||||
path_view::iterator i = pt.find(p);
|
|
||||||
if (i != pt.end())
|
|
||||||
{
|
{
|
||||||
lru_file_entry e = *i;
|
lru_file_entry& e = i->second;
|
||||||
e.last_use = time_now();
|
e.last_use = time_now();
|
||||||
|
|
||||||
if (e.key != st && ((e.mode & file::rw_mask) != file::read_only
|
if (e.key != st && ((e.mode & file::rw_mask) != file::read_only
|
||||||
|
@ -76,7 +71,6 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
// close the file before we open it with
|
// close the file before we open it with
|
||||||
// the new read/write privilages
|
// the new read/write privilages
|
||||||
i->file_ptr.reset();
|
|
||||||
TORRENT_ASSERT(e.file_ptr.unique());
|
TORRENT_ASSERT(e.file_ptr.unique());
|
||||||
e.file_ptr->close();
|
e.file_ptr->close();
|
||||||
if (!e.file_ptr->open(p, m, ec))
|
if (!e.file_ptr->open(p, m, ec))
|
||||||
|
@ -87,7 +81,6 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(e.file_ptr->is_open());
|
TORRENT_ASSERT(e.file_ptr->is_open());
|
||||||
e.mode = m;
|
e.mode = m;
|
||||||
}
|
}
|
||||||
pt.replace(i, e);
|
|
||||||
TORRENT_ASSERT((e.mode & file::no_buffer) == (m & file::no_buffer));
|
TORRENT_ASSERT((e.mode & file::no_buffer) == (m & file::no_buffer));
|
||||||
return e.file_ptr;
|
return e.file_ptr;
|
||||||
}
|
}
|
||||||
|
@ -96,12 +89,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
// the file cache is at its maximum size, close
|
// the file cache is at its maximum size, close
|
||||||
// the least recently used (lru) file from it
|
// the least recently used (lru) file from it
|
||||||
typedef nth_index<file_set, 1>::type lru_view;
|
remove_oldest();
|
||||||
lru_view& lt = get<1>(m_files);
|
|
||||||
lru_view::iterator i = lt.begin();
|
|
||||||
// the first entry in this view is the least recently used
|
|
||||||
TORRENT_ASSERT(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use));
|
|
||||||
lt.erase(i);
|
|
||||||
}
|
}
|
||||||
lru_file_entry e;
|
lru_file_entry e;
|
||||||
e.file_ptr.reset(new (std::nothrow)file);
|
e.file_ptr.reset(new (std::nothrow)file);
|
||||||
|
@ -114,34 +102,41 @@ namespace libtorrent
|
||||||
return boost::shared_ptr<file>();
|
return boost::shared_ptr<file>();
|
||||||
e.mode = m;
|
e.mode = m;
|
||||||
e.key = st;
|
e.key = st;
|
||||||
e.file_path = p;
|
m_files.insert(std::make_pair(p.string(), e));
|
||||||
pt.insert(e);
|
|
||||||
TORRENT_ASSERT(e.file_ptr->is_open());
|
TORRENT_ASSERT(e.file_ptr->is_open());
|
||||||
return e.file_ptr;
|
return e.file_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void file_pool::remove_oldest()
|
||||||
|
{
|
||||||
|
file_set::iterator i = std::min_element(m_files.begin(), m_files.end()
|
||||||
|
, boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _1))
|
||||||
|
< boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _2)));
|
||||||
|
if (i == m_files.end()) return;
|
||||||
|
m_files.erase(i);
|
||||||
|
}
|
||||||
|
|
||||||
void file_pool::release(fs::path const& p)
|
void file_pool::release(fs::path const& p)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock l(m_mutex);
|
boost::mutex::scoped_lock l(m_mutex);
|
||||||
|
|
||||||
typedef nth_index<file_set, 0>::type path_view;
|
file_set::iterator i = m_files.find(p.string());
|
||||||
path_view& pt = get<0>(m_files);
|
if (i != m_files.end()) m_files.erase(i);
|
||||||
path_view::iterator i = pt.find(p);
|
|
||||||
if (i != pt.end()) pt.erase(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_pool::release(void* st)
|
void file_pool::release(void* st)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock l(m_mutex);
|
boost::mutex::scoped_lock l(m_mutex);
|
||||||
TORRENT_ASSERT(st != 0);
|
TORRENT_ASSERT(st != 0);
|
||||||
using boost::tie;
|
|
||||||
|
|
||||||
typedef nth_index<file_set, 2>::type key_view;
|
for (file_set::iterator i = m_files.begin();
|
||||||
key_view& kt = get<2>(m_files);
|
i != m_files.end();)
|
||||||
|
{
|
||||||
key_view::iterator start, end;
|
if (i->second.key == st)
|
||||||
tie(start, end) = kt.equal_range(st);
|
m_files.erase(i++);
|
||||||
kt.erase(start, end);
|
else
|
||||||
|
++i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_pool::resize(int size)
|
void file_pool::resize(int size)
|
||||||
|
@ -153,15 +148,8 @@ namespace libtorrent
|
||||||
if (int(m_files.size()) <= m_size) return;
|
if (int(m_files.size()) <= m_size) return;
|
||||||
|
|
||||||
// close the least recently used files
|
// close the least recently used files
|
||||||
typedef nth_index<file_set, 1>::type lru_view;
|
|
||||||
lru_view& lt = get<1>(m_files);
|
|
||||||
lru_view::iterator i = lt.begin();
|
|
||||||
while (int(m_files.size()) > m_size)
|
while (int(m_files.size()) > m_size)
|
||||||
{
|
remove_oldest();
|
||||||
// the first entry in this view is the least recently used
|
|
||||||
TORRENT_ASSERT(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use));
|
|
||||||
lt.erase(i++);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,8 +107,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
namespace fs = boost::filesystem;
|
namespace fs = boost::filesystem;
|
||||||
using boost::bind;
|
using boost::bind;
|
||||||
using namespace ::boost::multi_index;
|
|
||||||
using boost::multi_index::multi_index_container;
|
|
||||||
|
|
||||||
#if defined TORRENT_DEBUG && defined TORRENT_STORAGE_DEBUG && TORRENT_USE_IOSTREAM
|
#if defined TORRENT_DEBUG && defined TORRENT_STORAGE_DEBUG && TORRENT_USE_IOSTREAM
|
||||||
namespace
|
namespace
|
||||||
|
|
Loading…
Reference in New Issue