- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
class session {
public:
session(int id, boost::asio::io_service &io_service) :
id(id),
timer(io_service)
{
timer.expires_from_now(session_timeout);
timer.async_wait(boost::bind(&session::on_timeout, this, _1));
}
void on_timeout(const boost::system::error_code &error) {
if (error)
return;
std::cout << "Session timed out " << id << std::endl;
}
private:
int id;
boost::asio::deadline_timer timer;
};
std::map<boost::asio::ip::udp::endpoint, boost::shared_pointer<session> > sessions;
sessions.erase(endpoint) приводит к небольшому насилию над трупом сессии... Ничего конечно не вылетает, и никогда не сломается, но совесть мучает, неприятно пользоваться UB'ом.
defecate-plusplus 18.03.2013 14:14 # +2
?
bormand 18.03.2013 14:55 # 0
LispGovno 18.03.2013 15:28 # +3
bormand 18.03.2013 15:30 # +1
defecate-plusplus 18.03.2013 14:31 # +6
т.е. каждый таймер имеет четкую метку во времени, когда надо сработать - и недостаток основной специализации asio::deadline_timer в том, что она построена поверх posix_time, т.е. даты-времени
при совпадении пары условий (зависит от реализации в конкретной версии буста, но на моей памяти примерно достаточно, чтобы в очереди был другой таймер короче, например) и переводе системных часов назад - например, на 1 сутки, можно ждать не 30 секунд, а 1 сутки и 30 секунд
аналогично при переводе вперед - можно сломать "хорошие" соединения, посчитав их истекшими
вряд-ли кого то это сильно коснется, но я не мог это не рассказать, т.к. это когда-то решал)
bormand 18.03.2013 15:01 # 0
Так а в asio других таймеров вроде бы и нет?
defecate-plusplus 18.03.2013 15:33 # +3
defecate-plusplus 18.03.2013 19:53 # +2
http://pastebin.com/mmQ9VWje
я помню свою радость, когда в буст добавили chrono, хоть и простая, но очень полезная либа
LispGovno 18.03.2013 19:56 # −6
LispGovno 18.03.2013 19:56 # −6
bormand 18.03.2013 20:00 # 0
Листать же потом неудобно эти портянки. А спойлеров тут нет. Потому и внешний линк.
LispGovno 18.03.2013 20:04 # +6
Для говнокода это не проблема. Народ, навались, создай спойлер в комментах с кодом, заминусовав!
vistefan 20.03.2013 14:25 # +1
govnomonad 23.03.2013 05:44 # 0
LispGovno 18.03.2013 20:02 # −1
LispGovno 18.03.2013 19:58 # −1
Я все жду когда в бууст добавят unique_ptr наконец
defecate-plusplus 18.03.2013 20:08 # +1
LispGovno 18.03.2013 20:32 # 0
http://www.boost.org/doc/libs/1_53_0/doc/html/move.html
defecate-plusplus 18.03.2013 21:05 # 0
собсно, думаю, в этом году все подтянутся к нужной мне планке
roman-kashitsyn 18.03.2013 14:33 # +2
defecate-plusplus 18.03.2013 14:37 # +1
не всегда код написан так, что вызов метода on_my_timer у мертвого объекта это переварит (да и это само по себе ub, как было написано автором)
но обычно, если лень/медленно возиться с shared_from_this(), все на это забивают, главное выйти по ошибке до того, как полезешь в свои члены
defecate-plusplus 18.03.2013 14:45 # +2
bormand 18.03.2013 15:13 # +1
Вот и остается два варианта:
1) Не заморачиваться с shared_from_this и насильно удалять сессию вместе со всеми ее кишками, забив на UB, как я и показал в топике. Если в колбеках не забывать обрабатывать ошибки - все корректно деинициализируется, но на душе остается неприятный осадок.
2) Заморочиться с shared_from_this, а для кошерного завершения сессии вызывать cleanup(), который вызовет у подобъектов cleanup() который вызовет... Ну, в общем, куча бойлерплейта отменяющего таймеры да подчищающего shared_ptr'ы.
Может я упускаю какое-то более изящное решение?
LispGovno 18.03.2013 15:31 # 0
Вот почему нет weak_from_this? :/
LispGovno 18.03.2013 15:33 # 0
C shared_from_this получить shared_ptr, а потом с него получить weak_ptr
bormand 18.03.2013 15:41 # +1
LispGovno 18.03.2013 16:10 # 0
LispGovno 18.03.2013 16:18 # 0
bormand 18.03.2013 19:04 # +1
defecate-plusplus 18.03.2013 19:40 # +2
LispGovno 18.03.2013 19:49 # −2
Я вот тоже подумывал написать нечто подобное, только я собираюсь в рамках С++03 и boost.
defecate-plusplus 18.03.2013 15:39 # +2
если пользоваться п.1, необходимо еще учитывать редкий момент, когда ровно в момент запуска коллбека (как тут - честный таймаут), во втором потоке у объекта вызывается деструктор - и ты такой гейзенбаг будешь сто лет искать
bormand 18.03.2013 15:47 # +1
Ну сокет и сессии разруливаются в одном потоке, а другие потоки к ним напрямую никогда не лезут. Так что особых проблем не должно возникнуть.
> weak
Вот насчет weak_ptr надо подумать, может не так он и мешается, раз уже двое мне его советуют ;)
defecate-plusplus 18.03.2013 15:56 # +2
в эту очередь встанет коллбек на on_timer(error_code()), и пусть ты при этом "однопоточно" деструктишь сессию, коллбек тебе придет именно так, как он был запощен
спасет только io_service.stop, что не есть решение
bormand 18.03.2013 16:03 # +1
OMG... дочитал документацию по cancel() до конца, и понял в чем ужас ситуации: These handlers can no longer be cancelled, and therefore are passed an error code that indicates the successful completion of the wait operation.
Т.е. я так понимаю адекватно отменить таймер невозможно?
bormand 18.03.2013 16:14 # 0
roman-kashitsyn 18.03.2013 15:08 # +3
LispGovno 18.03.2013 15:34 # +1
guest 22.03.2013 17:15 # 0
LispGovno 22.03.2013 17:17 # 0
It unusable at asynchronous programming. Inconvenient as ass.
guest 22.03.2013 17:24 # +1
LispGovno 18.03.2013 15:26 # 0
bormand 18.03.2013 15:36 # +1
3.14159265 18.03.2013 16:13 # +9
UB - КРЕСТОСТАНДАРТЕН
guest 19.03.2013 17:48 # −1