lib/nfs/Cancellable: use boost::intrusive::list
Reduce Remove() overhead because we don't have to walk the list to find an iterator by reference.
This commit is contained in:
parent
3560dc4be6
commit
fb4e6ac923
@ -22,13 +22,15 @@
|
|||||||
|
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
#include <list>
|
#include <boost/intrusive/list.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class CancellablePointer {
|
class CancellablePointer
|
||||||
|
: public boost::intrusive::list_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> {
|
||||||
public:
|
public:
|
||||||
typedef T *pointer_type;
|
typedef T *pointer_type;
|
||||||
typedef T &reference_type;
|
typedef T &reference_type;
|
||||||
@ -38,7 +40,7 @@ private:
|
|||||||
pointer_type p;
|
pointer_type p;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit constexpr CancellablePointer(reference_type _p):p(&_p) {}
|
explicit CancellablePointer(reference_type _p):p(&_p) {}
|
||||||
|
|
||||||
CancellablePointer(const CancellablePointer &) = delete;
|
CancellablePointer(const CancellablePointer &) = delete;
|
||||||
|
|
||||||
@ -70,7 +72,8 @@ public:
|
|||||||
typedef typename CT::const_reference_type const_reference_type;
|
typedef typename CT::const_reference_type const_reference_type;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::list<CT> List;
|
typedef boost::intrusive::list<CT,
|
||||||
|
boost::intrusive::constant_time_size<false>> List;
|
||||||
typedef typename List::iterator iterator;
|
typedef typename List::iterator iterator;
|
||||||
typedef typename List::const_iterator const_iterator;
|
typedef typename List::const_iterator const_iterator;
|
||||||
List list;
|
List list;
|
||||||
@ -97,28 +100,14 @@ private:
|
|||||||
return std::find_if(list.begin(), list.end(), MatchPointer(p));
|
return std::find_if(list.begin(), list.end(), MatchPointer(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
class MatchReference {
|
|
||||||
const CT &c;
|
|
||||||
|
|
||||||
public:
|
|
||||||
constexpr explicit MatchReference(const CT &_c):c(_c) {}
|
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
bool operator()(const CT &a) const {
|
|
||||||
return &a == &c;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
iterator Find(CT &c) {
|
iterator Find(CT &c) {
|
||||||
return std::find_if(list.begin(), list.end(),
|
return list.iterator_to(c);
|
||||||
MatchReference(c));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const_iterator Find(const CT &c) const {
|
const_iterator Find(const CT &c) const {
|
||||||
return std::find_if(list.begin(), list.end(),
|
return list.iterator_to(c);
|
||||||
MatchReference(c));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -142,21 +131,9 @@ public:
|
|||||||
CT &Add(reference_type p, Args&&... args) {
|
CT &Add(reference_type p, Args&&... args) {
|
||||||
assert(Find(p) == list.end());
|
assert(Find(p) == list.end());
|
||||||
|
|
||||||
list.emplace_back(p, std::forward<Args>(args)...);
|
CT *c = new CT(p, std::forward<Args>(args)...);
|
||||||
return list.back();
|
list.push_back(*c);
|
||||||
}
|
return *c;
|
||||||
|
|
||||||
void RemoveLast() {
|
|
||||||
list.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RemoveOptional(CT &ct) {
|
|
||||||
auto i = Find(ct);
|
|
||||||
if (i == list.end())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
list.erase(i);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Remove(CT &ct) {
|
void Remove(CT &ct) {
|
||||||
@ -164,6 +141,7 @@ public:
|
|||||||
assert(i != list.end());
|
assert(i != list.end());
|
||||||
|
|
||||||
list.erase(i);
|
list.erase(i);
|
||||||
|
delete &ct;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cancel(reference_type p) {
|
void Cancel(reference_type p) {
|
||||||
|
@ -161,7 +161,7 @@ NfsConnection::Open(const char *path, int flags, NfsCallback &callback,
|
|||||||
|
|
||||||
auto &c = callbacks.Add(callback, *this);
|
auto &c = callbacks.Add(callback, *this);
|
||||||
if (!c.Open(context, path, flags, error)) {
|
if (!c.Open(context, path, flags, error)) {
|
||||||
callbacks.RemoveLast();
|
callbacks.Remove(c);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +176,7 @@ NfsConnection::Stat(struct nfsfh *fh, NfsCallback &callback, Error &error)
|
|||||||
|
|
||||||
auto &c = callbacks.Add(callback, *this);
|
auto &c = callbacks.Add(callback, *this);
|
||||||
if (!c.Stat(context, fh, error)) {
|
if (!c.Stat(context, fh, error)) {
|
||||||
callbacks.RemoveLast();
|
callbacks.Remove(c);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ NfsConnection::Read(struct nfsfh *fh, uint64_t offset, size_t size,
|
|||||||
|
|
||||||
auto &c = callbacks.Add(callback, *this);
|
auto &c = callbacks.Add(callback, *this);
|
||||||
if (!c.Read(context, fh, offset, size, error)) {
|
if (!c.Read(context, fh, offset, size, error)) {
|
||||||
callbacks.RemoveLast();
|
callbacks.Remove(c);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,8 +41,8 @@ class NfsConnection : SocketMonitor, DeferredMonitor {
|
|||||||
NfsConnection &connection;
|
NfsConnection &connection;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit constexpr CancellableCallback(NfsCallback &_callback,
|
explicit CancellableCallback(NfsCallback &_callback,
|
||||||
NfsConnection &_connection)
|
NfsConnection &_connection)
|
||||||
:CancellablePointer<NfsCallback>(_callback),
|
:CancellablePointer<NfsCallback>(_callback),
|
||||||
connection(_connection) {}
|
connection(_connection) {}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user