- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
void User::AddFriend(User& newFriend)
{
friends_.push_back(&newFriend);
pDB_->AddFriend(GetName(), newFriend.GetName());
}
//...VS...
void User::AddFriend(User& newFriend)
{
friends_.push_back(&newFriend);
try
{
pDB_->AddFriend(GetName(), newFriend.GetName());
}
catch (...)
{
friends_.pop_back();
throw;
}
}
//...VS...
class VectorInserter//Глобальный безопасный вектороВставлятель.
{
public:
VectorInserter(std::vector<User*>& v, User& u)
: container_(v), commit_(false)
{
container_.push_back(&u);
}
void Commit() throw()
{
commit_ = true;
}
~VectorInserter()
{
if (!commit_) container_.pop_back();
}
private:
std::vector<User*>& container_;
bool commit_;
};
void User::AddFriend(User& newFriend)
{
VectorInserter ins(friends_, &newFriend);
pDB_->AddFriend(GetName(), newFriend.GetName());
// Everything went fine, commit the vector insertion
ins.Commit();
}
В последнем примере автор статьи забыл, что он рискует уронить всю программу, если container_.pop_back(); кинет исключение в момент размотки стека из-за другого исключения.
RFC1925, (6a): It is always possible to add another level of indirection.
другими словами: основная проблема которую решает OOP, это облегчение программистам добавление оберток и прочей воды, что бы начальству было чего показать и самое главное рассказать.
Такими темпами автор и до STM дойдет.
В конце я помечтал, что он сделал вот так:
Интересно, как бы это в STM бы выглядело.
Штатная реализация предоставляет лишь богомерзкий unsafeIOToSTM без возможности откатов.
P.S. вот, нашёл такой вопрос на SO:
А вот сумеречный стм надо бы покурить, вроде как функционала хватит для работы с координатором.
Интересно, STM не на уровне компилятора в С++ загнулся?
Не самая приятная процедура... Придется дельту считать, а хаскель вроде бы не умеет сравнивать ссылки (поправьте, если ошибаюсь), поэтому преимущество от расшаренных общих данных в снимках нам реализовать не удастся. Только полное сравнение, только хардкор...
И к тому же это совсем не D из ACID, хотя для многих применений было бы достаточно.
обновить друзей
Когда заводишь нового друга - его нужно обновить и обмыть. Так уж принято в обществе.
Этот класс все же страхует от исключений при вставке в базу, а не от ошибок программиста.
Вроде как опасным указателем изначально предполагалось указывать на мелкие объектики, из которых составлена большая структура данных...
Резонно. По хорошему ещё и bormand::vector<T> реализованный через std::vector<bormand_ptr<std::vector<T> > >.
Гугли hazard pointer. В бусте такого нет, так как это какой-то питух взял на это авторские права. Типа если вы используете мою мега идею - платите бабки.
Какой год не могли добавить в буст этот странник_птр. В результате плюнули на всё и выкатили boost::lockfree без него из-за какого-то патентованого питуха.
Пока тред работает с неким объектом он держит указатель на него в своем списке used.
Если треду хочется удалить объект, он отстегивает его от структуры данных (локфри способом) и добавляет его в свой список done. Периодически тред мониторит этот список, и освобождает все объекты, которых нет в used у других тредов
Вот как-то так.... В общем эти указатели нужны для решения проблемы освобождения в lock-free алгоритмах, и вне их контекста, имхо, бесполезны...
The only place that can throw an exception is the construction of the new node, but this will clean up after itself, and the list hasn’t been modified yet, so that’s perfectly safe.
Там же утечка будет, если конструктор копирования сфейлится? Либо я туплю, либо автор :)
Утекает только если: В зависимости от порядка конструирования аргументов (а это ID) память или утечет или не утечет.
Спасибо, что-то меня переклинило с этим new. Оно же ничего мне не вернет (т.к. должно перевбросить исключение), а значит само должно справиться с утечкой. Поэтому все норм, и тупанул я, а не автор.
> с комментом на китайском
Это якудза торгуют поддельными ускоренными опасными указателями, покупайте опасные указатели только из проверенных источников
void User::AddFriend(User& newFriend)
{
pDB_->AddFriend(GetName(), newFriend.GetName());
friends_.push_back(&newFriend);
}
Ну или автор боится исключения во время push_back.