Russian Qt Forum

Qt => Кладовая готовых решений => Тема начата: navrocky от Сентябрь 28, 2010, 09:29



Название: implicit sharing
Отправлено: navrocky от Сентябрь 28, 2010, 09:29
В этом посте не буду оригинален, я попытался себе упростить написание классов со скрытым разделением ресурсов (implicit sharing). QT у себя внутри использует этот подход во многих классах, но почему-то я не нашел у них никаких вспомогательных классов для этого, ну если не считать QAtomicInt :)

Вот что у меня получилось:
Код
C++ (Qt)
#pragma once
 
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
 
template <class Body>
class implicit_sharing
{
public:
   implicit_sharing()
   : body_(boost::make_shared<Body>())
   {
   }
 
   /*! Call this from all non const methods. */
   void detach()
   {
       if (body_.unique())
           return;
       boost::shared_ptr<Body> old = body_;
       body_ = boost::make_shared<Body>(*(body_.get()));
   }
 
   /*! Access to shared body. */
   inline Body* operator->() const
   {
       return body_.get();
   }
 
   inline Body* operator->()
   {
       detach();
       return body_.get();
   }
 
private:
   boost::shared_ptr<Body> body_;
};
 

Пример использования:
Код
C++ (Qt)
class my_data
{
public:
   int val() const {return d->val;}
 
   void set_val(int val)
   {
       d->val = val;
   }
 
private:
   struct impl
   {
       int val;
   };
   implicit_sharing<impl> d;
};
 

В этом классе я углядел пока две проблемы:
  • проблемы с многопоточностью
  • отсутствие возможности передать в конструктор impl параметры из конструктора класса-носителя

Вместо boost::shared_ptr можно, конечно же, использовать QSharedPtr, правда с потерей оптимальности, т.к. нет в Qt make_shared.

Буду рад если это кому то поможет и вдвойне рад если кто-то поможет тут устранить проблемы ;)


Название: Re: implicit sharing
Отправлено: maxxant от Сентябрь 28, 2010, 17:59
не понял.
всё есть и с примерами:

http://doc.qt.nokia.com/4.6/implicit-sharing.html
http://doc.qt.nokia.com/4.6/qshareddatapointer.html



Название: Re: implicit sharing
Отправлено: navrocky от Сентябрь 28, 2010, 18:03
да, действительно не углядел... одним велосипедом больше стало :D

ЗЫЖ хотя в моем варианте меньше буков писать, для себя я использую эту реализацию вместо QSharedDataPointer..


Название: Re: implicit sharing
Отправлено: navrocky от Ноябрь 02, 2014, 18:07
Всё таки моя реализация лучше, чем QSharedData + QSharedDataPointer. Только сейчас, попробовав QSharedData  в работе, я это понял  :)

Когда используешь QSharedDataPointer в наследнике QObject, то необходимо определить структуру Data полностью в хедере, т.к. метакомпилятор что-то там досоздает и возникает ошибка компиляции.

Код
C++ (Qt)
class MyObject : public QObject
{
   Q_OBJECT
public:
   MyObject();
private:
   struct Data;
   QSharedDataPointer<Data> d;
};
 

Код:
/usr/include/qt5/QtCore/qshareddata.h:87:45: error: invalid use of incomplete type 'struct MyObject::Data'
     inline ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; }

А часто хочется скрыть реализацию, упрятав её с внутренними зависимостями в cpp файл.

Более того:

1) с QSharedDataPointer надо писать больше буков. Надо создать Data во всех конструкторах, в моём случае это не надо делать, создание происходит автоматически.

2) не надо наследовать Data от QSharedData

PS. Если использовать c++11, то зависимость от буста можно выкинуть.


Название: Re: implicit sharing
Отправлено: Авварон от Ноябрь 06, 2014, 13:08
Код:
/usr/include/qt5/QtCore/qshareddata.h:87:45: error: invalid use of incomplete type 'struct MyObject::Data'
     inline ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; }

Вынесите деструктор в цпп и будет счастье


Название: Re: implicit sharing
Отправлено: navrocky от Ноябрь 12, 2014, 18:55
Код:
/usr/include/qt5/QtCore/qshareddata.h:87:45: error: invalid use of incomplete type 'struct MyObject::Data'
     inline ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; }

Вынесите деструктор в цпп и будет счастье

Деструктор QSharedDataPointer, вы шутите?