Повышение слабого_потока в многопоточной программе для реализации пула ресурсов - PullRequest
4 голосов
/ 29 января 2010

Я думаю об использовании boost :: weak_ptr для реализации пула объектов, так что они будут получены, когда никто не использует один из объектов. Однако меня беспокоит то, что это многопоточная среда, и кажется, что существует условие состязания между последним shared_ptr и тем, что объект выходит из области видимости, и новым shared_ptr, созданным из weak_ptr. Обычно вы защищаете такие операции блокировкой или чем-то еще; однако весь смысл в том, что вы не знаете, когда shared_ptr выходит из области видимости.

Не понимаю ли я что-то о boost :: shared_ptr и boost :: weak_ptr? Если нет, есть ли у кого-нибудь хорошие предложения о том, что делать?

Спасибо.

Andrew

Ответы [ 3 ]

11 голосов
/ 29 января 2010

Чтобы использовать weak_ptr, вам обычно нужно получить сильную ссылку, создав с ней shared_ptr. Этот последний шаг является атомарным: вы либо получаете сильную ссылку назад, либо вы получаете bad_weak_ptr исключение. (В качестве альтернативы, позвоните lock() на weak_ptr и получите либо сильную ссылку, либо ноль.)

Пример (с lock(); достаточно легко адаптировать к другому стилю):

void do_something(weak_ptr<foo> weak) {
    // Grab strong reference
    shared_ptr<foo> strong(weak.lock());
    if (strong) {
        // We now have a strong reference to use
    } else {
        // No strong references left; object already freed
    }
}
3 голосов
/ 18 января 2012

И boost::weak_ptr, и boost::shared_ptr похожи, если речь идет о безопасности потоков: они не являются потокобезопасными, если есть риск, что объект где-нибудь будет уничтожен. Если ваш объект, на который есть ссылка в boost::shared_ptr, или когда на слабый_приемник ссылаются постоянно, то использование может использовать shared/weak ptrs без какого-либо риска.

Но если какая-то операция разыменовывает последний живой экземпляр объекта, тогда вы не можете выполнять некоторые операции над weak_ptr: в частности: вы не можете присвоить weak_ptr другой weak_ptr, потому что она использует shared_ptr внутренне. Кроме того, вы не можете использовать блокировку, потому что результат не определен. Кроме того, метод expired() бесполезен: он может возвращать true, но затем на следующей строке вашего кода ваш объект может быть уже просрочен.

0 голосов
/ 29 января 2010

Да, иш. С точки зрения доступа к указателям, Boost должен был сделать все безопасно; это часть их идеи.

Тем не менее, если вы ожидаете задержку между тем, когда выйдет последний shared_ptr, и когда вы захотите сделать следующий, вы получите нулевой указатель. (Если вы проверяете должным образом, у вас должен быть случай сбоя ApproPro).

Но вы не можете получить неверный shared_ptr

...