[Development] Question about QCoreApplicationData::*_libpaths
Thiago Macieira
thiago.macieira at intel.com
Wed Jan 20 22:17:35 CET 2016
On Wednesday 20 January 2016 20:05:08 Kevin Kofler wrote:
> Thiago Macieira wrote:
> > We can only do that efficiently if we drop CoW. Creating an adapting API
> > is easy; making sure we don't do unnecessary copies because we've lost CoW
> > is the hard part.
>
> Would it be possible to wrap a QSharedDataPointer<VectorData<T> >, where
> class VectorData<T> : public QSharedData, public std::vector<T>? That would
> still be layered above std::vector (and d.data() would give you something
> that is-a std::vector) yet CoW. Or are there reasons why such an approach
> would not be workable for std::vector?
This causes double indirection to the data, something we've worked hard to
avoid. The most common operation you do on a vector is access an element, so
that should be fast.
Here's what the begin() const functions look like:
libc++: return __make_iter(this->__begin_);
libstdc++: return const_iterator(this->_M_impl._M_start);
QVector: return d->constBegin();
-> return data();
-> return static_cast<const T *>(QArrayData::data());
-> return reinterpret_cast<char *>(this) + offset;
(all inline)
or in my implementation, QArrayDataPointer::data() does:
return ptr;
The important thing to note is that there's exactly one pointer dereferenced
at all: this. Current QVector already loses a little by having
QArrayData::offset added.
But if we did what you suggest, then here's what QVector::begin() const would
look like:
typename std::vector<T>::const_iterator begin() const
{ return this->d->begin(); }
Now we needed to dereference this *and* the d pointer. This means potentially
two cachelines being read from and there's a data dependency, which in turn
means potential pipeline stall.
> Now I think the current QVector implementation is fine, but I'm also not
> convinced wrapping std::vector requires dropping CoW. The problems would
> probably show up somewhere else.
The options are:
a) accept the extra dereferencing
b) not wrap std::vector, but continue with our own array management
c) drop CoW
As I told Lars last night / this morning over IRC, what I would love to have
is an improved version of Qt 5's unsharable containers mode:
template<typename T> using QVector<T> = QtTools::Vector<T, CopyOnWrite>;
using QString = QtTools::String<CopyOnWrite>;
where QtTools::Vector<T, Trait> can do both CoW and non-CoW modes. You'd be
able to write code like:
QString foo()
{
QtTools::String<Unsharable> s(size, Qt::Uninitialized);
fill(s.data(), size); // no useless detach() emitted!
foreach (auto ch : s) // ditto
process(ch);
return s; // move-construction "steals" buffer
}
QtTools::String<Unsharable> s = foo(); // move-construction attempts to steal
The Unsharable modes for the containers would have the same complexity and
behaviour as the Standard Library counterparts. But they'd do more, since
they'd interoperate with the CoW containers too.
--
Thiago Macieira - thiago.macieira (AT) intel.com
Software Architect - Intel Open Source Technology Center
More information about the Development
mailing list