crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> weak_ptr from intrusive, свой велосипед
alexy
  опции профиля:
сообщение 15.4.2015, 0:02
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 44
Регистрация: 4.8.2010
Пользователь №: 1931

Спасибо сказали: 0 раз(а)




Репутация:   0  


shared_ptr нельзя создать в конструкторе...
у меня сейчас в многопоточном коде часто появляются двухэтапные конструкторы. снчала создаешь shared_ptr потом вызываешь какой-нибудь registr или еще что-нибудь, куча отложенных созданий объектов, когда я бы мог создать его в конструкторе ,но создаю в фукнции ,которой он нужен, из-за этого появляются дополнительные проверки "не создал ли я его уже?", которых можно было бы избежать, если бы...
к тому же мне не нравится shared_from_this с точки зрения ООП, это как бы деталь реализации, закравшаяся в интерфейс.

может спасти intrusive_ptr, но у него нет weak_ptr и значит проблема циклических ссылок будет.

вобщем сегодня я накатал такой код. не уверен в правильности использвания std::atomic. выбрал shared_ptr для быстроты реализации. потом хочу сделать структуру, одно поле будет счетчиком ссылок для объекта, другое для weak_ptr'а.

выкладываю: может кому интересно или у кого-то уже есть свои проверенные наработки, лучше чем у меня, поделитесь пожалуйста.

зы: а что, нельзя загружать файлы hpp ??
Прикрепленные файлы
Прикрепленный файл  intrusive_weak_ptr.hpp.txt ( 3.67 килобайт ) Кол-во скачиваний: 394
 
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 15.4.2015, 0:53
Сообщение #2


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Цитата
shared_ptr нельзя создать в конструкторе...

А зачем? Чтобы иметь член класса-указатель на себя самого? Или чтобы вызывать глобальные статические функции?
В любом случае, лучше использовать factory[method].
class MyAwesomeObj {
  ...
}
class MyAwesomeFactory {
  virtual std::shared_ptr<MyAwesomeObj> create() {
    std::shared_ptr<MyAwesomeObj> obj = std::shared_ptr<MyAwesomeObj>( new MyAwesomeObj );
    MyAwesomeSingletonRegistry::Instance().registerAwesome( obj );
    return obj;
  }
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
alexy
  опции профиля:
сообщение 15.4.2015, 14:19
Сообщение #3


Студент
*

Группа: Участник
Сообщений: 44
Регистрация: 4.8.2010
Пользователь №: 1931

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(lanz @ 15.4.2015, 1:53) *
Или чтобы вызывать глобальные статические функции?

ага, для нескольких типов у меня есть реестр.
также вревовидные структуры.. некоторым нужно обязательно создать определенных детей. то есть например класс дерево обязательно должен содержать один лист и один орех, другое по желанию :)

Цитата(lanz @ 15.4.2015, 1:53) *
В любом случае, лучше использовать factory[method].


а чем лучше?
нужно создавать паралельную эрархию классов. а если я хочу указатель на созданный тип, а не на базовый? с фабрикой останется только dynamic_cast.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 15.4.2015, 14:58
Сообщение #4


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Цитата
а чем лучше?

Separation of concerns, разделяете тип хранения (shared_ptr), реестры и ваш класс. Тип хранения это деталь реализации.
Вот например сейчас у вас один реестр, а захотите например 2, из которых один записывает в БД. Добавляете новую фабрику, с 2 реестрами и все. Хотите создаете с одним реестром, хотите с двумя. А если у вас занесение в реестр в конструкторе как вы это реализуете? параметр передавать в конструктор? if-then-else?
Цитата
а если я хочу указатель на созданный тип, а не на базовый?

Interface segregation principle, значит у базового типа плохой интерфейс, возможно стоит сделать еще один? :lol:
Если не хочется много писать, сделайте factory template:
template <typename T>
class MySharedFactory {
  std::shared_ptr<T> create() { return std::shared_ptr<T>(new T); }
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
alexy
  опции профиля:
сообщение 15.4.2015, 15:48
Сообщение #5


Студент
*

Группа: Участник
Сообщений: 44
Регистрация: 4.8.2010
Пользователь №: 1931

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(lanz @ 15.4.2015, 15:58) *
Separation of concerns, разделяете тип хранения
...
Interface segregation principle, значит у базового типа плохой интерфейс, возможно стоит сделать еще один? :lol:


это интересно.. может и стоит использовать фабрику..
еще проблема с параметрами для инициализации. на одном форуме нашел, что это не возможно. там чел потом сделал политику фкнциионирования, которую и передавал в качестве единственного параметра в фабрику.
реестр - это не просто тип хранения, это обеспечение некторых функций, требуемых от объекта.

это вобще сервер в нете. там есть класс сессии, это сеанс взаимодействия с пользователем. он регистрируется в реестре, например, если у пользователя пропадет интеренет, то есть специальный поток, который убивает сессии, которые слишком долго висят. также юзверь может подключится к этой сесии с другого клиента ну и т.д.
есть сессия для всех, есть с обязательным залогиниванием. ей нужно в конструкторе передать параметры токена юзера. иначе, если этого не сделать, то выходит, что сессия будет какое-то время с незалогиненым пользователем.

ЗЫ: да, мои гуглинья наводят меня на мысль, что это действительно никому не нужно и люди юзают другие способы. выходит что обычно такое рашется именно фабрикой?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 15.4.2015, 16:11
Сообщение #6


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Цитата
еще проблема с параметрами для инициализации. на одном форуме нашел, что это не возможно. там чел потом сделал политику фкнциионирования, которую и передавал в качестве единственного параметра в фабрику.

Почему же невозможно, можно в метод create передавать все нужные параметры.

Цитата
ЗЫ: да, мои гуглинья наводят меня на мысль, что это действительно никому не нужно и люди юзают другие способы. выходит что обычно такое рашется именно фабрикой?

Просто делать это в конструкторе - плодить лишние зависимости.

Тут надо подумать, кто является владельцем сессии и на него возложить заботу о создании, хранении и т.п. Самой сессии знать о центральном реестре и других сессиях на мой взгляд излишне.

Сообщение отредактировал lanz - 15.4.2015, 16:11
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 16.4.2015, 9:17
Сообщение #7


Профессионал
*****

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


может, я не совсем понимаю идею, но чем не устраивает make_shared, например?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 16.4.2015, 9:33
Сообщение #8


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Цитата
может, я не совсем понимаю идею, но чем не устраивает make_shared, например?

После создания хочется выполнять еще какие-то обязательные действия, не только завернуть указатель.

Цитата
иначе, если этого не сделать, то выходит, что сессия будет какое-то время с незалогиненым пользователем.

Это как раз не страшно. Введите состояния сессии и отслеживайте их.
Просто если логинится в конструкторе, то как обрабатывать ошибки?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 16.4.2015, 13:20
Сообщение #9


Профессионал
*****

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


один фиг непонятно, чего хотели получить в итоге. а можно пример использования класса и что конкретно не получается?
можно создавать shared_ptr и использовать инициализацию в конструкторе, при этом можно в конструктор передавать shared_ptr'ы на другие объекты. можно через enable_shared_from_this создавать weak_ptr на себя и потом возвращать shared_ptr, полученный из this, через какой-то метод.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
alexy
  опции профиля:
сообщение 16.4.2015, 13:44
Сообщение #10


Студент
*

Группа: Участник
Сообщений: 44
Регистрация: 4.8.2010
Пользователь №: 1931

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(lanz @ 16.4.2015, 10:33) *
Просто если логинится в конструкторе, то как обрабатывать ошибки?

ну, я ввел понятие токена. сессия без логина, не принимает никаких параметоров, сессия с логином, принимает строку токена, ну и не создается (throw login_error) если токен не верен.

я вот гуглил. виджеты, на сколько я понимаю, так создать нельзя. потому что везде они создаются обычным new. и действительно, у меня есть виджет, который содержит другие виджеты, то есть у него прямо в конструкторе создаются неслько других виджетов, которые он должен удалить когда удалится сам. как им указать родителя в конструкторе?

я просто делаю клиента html, сделал виджетами. один может содержать другой, но есть root - это как бы <html></html> и у него несколько виджетов - <head> <body> и пара других. изначально сделал widget_ptr, и метод parent возращает widget_ptr, но оказалось, что так не получится если я хочу создать в конструкторе виджеты, то есть если он составной.
мне кажется как-то не правильно создавать в фабричном методе внутренние детали виджета.

Цитата(Iron Bug @ 16.4.2015, 14:20) *
один фиг непонятно, чего хотели получить в итоге. а можно пример использования класса и что конкретно не получается?
можно создавать shared_ptr и использовать инициализацию в конструкторе, при этом можно в конструктор передавать shared_ptr'ы на другие объекты. можно через enable_shared_from_this создавать weak_ptr на себя и потом возвращать shared_ptr, полученный из this, через какой-то метод.

да, я об этом писал в первом посте. мне не нравится shared_from_this() то есть если он public, то выходит что это реализация в интерфейсе. я делаю его protected. но в конструкторе все равно не получается. то есть получится, если сделать какой-нибудь метод, get_shared, тогда выйдет
auto sptr_ = new foo();
std::shared_ptr<foo> sptr = sptr_->get_shared();

а сам get_shared, после первого использования должен сделать shared_to_this.release(); или что-нибудь в этом духе, чтобы остался только weak_to_this...

по мне лучше что-нибудь в таком духе (в конструкторе)
// в заголовочном файле
// typedef boost::intrusive_ptr<widget_base> widget_ptr;

root_widget::root_widget()
    : root_html_(new with_contenet()), body_(new with_content()), head_(new with_content())
{
    *root_html_ << *head_ << *body_;
    // shared_ptr здесь не передать
    //root_html _.parent(/*shared_from_*/this);

    // только пока с этим тоже облом - все равно будет вызванно intrusive_ptr_release
    // это баг в intrusive_ptr?
    boost::intrusive_ptr<widget_base> this_ptr (this, false);

    root_html_->parent(this_ptr); // здесь он преобразуется в weak_ptr
}

// в другом файле, где определяется with_content
widget_ptr with_content::parent() const
{
    return parent_.lock();
}


Сообщение отредактировал alexy - 16.4.2015, 13:46
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 28.3.2024, 12:52