Преимущества:
1. Переносимо настолько, насколько потокобезопасность boost::shared_ptr переносима, при этом она реализована по возможности на атомарных операциях (см boost/smart_ptr/detail/ ).
2. Флаг завершения взводится неявно при возврате из потоковой функции, но при этом можно взвести его заранее явно.
Здравствуйте, Alexander G, Вы писали:
AG>Один тред запускает другой тред для выполнения долгой операции и периодически опрашивает флаг завершения. AG>При установке флага — получает результаты.
А вот с "получает результаты" заминочка. Предложенный вариант не будет работать, т.к. weak_ptr<>::expired() не передаёт видимость данных между потоками, которые освободили ассоциированный shared_ptr, и потоком которому expired() вернул true (кто-то обещал?).
Это можно видеть например в sp_counted_base_gcc_sparc.hpp:
Здравствуйте, remark, Вы писали:
R>А вот с "получает результаты" заминочка. Предложенный вариант не будет работать, т.к. weak_ptr<>::expired() не передаёт видимость данных между потоками, которые освободили ассоциированный shared_ptr, и потоком которому expired() вернул true (кто-то обещал?).
угу, понял.
R>Да и вообще необходимость использования поллинга как-то смущает, почему не сделать просто: R>
В таком варианте смущает возможность удаления адресата PostMessage до вызова PostMessage, во время вызова PostMessage, между PostMessage и получением сообщения — прийдётся предусмотреть проверку "существует ли адресат" и продление жизни адресата на время отправки сообщения.
Здравствуйте, remark, Вы писали:
R>А вот с "получает результаты" заминочка. Предложенный вариант не будет работать, т.к. weak_ptr<>::expired() не передаёт видимость данных между потоками, которые освободили ассоциированный shared_ptr, и потоком которому expired() вернул true (кто-то обещал?). R>Это можно видеть например в sp_counted_base_gcc_sparc.hpp: R>
Кстати, по-моему, та же проблема и в самом shared_ptr, т.е. они не обеспечивают и синхронизацию доступа к самому объекту, их sp_counted_base вообще ничего не гарантирует LOL
DESCRIPTION
This collection of functions provides atomic memory opera-
tions. There are 8 different classes of atomic operations:
atomic_add(3C) These functions provide an atomic addition
of a signed value to a variable.
atomic_and(3C) These functions provide an atomic logical
'and' of a value to a variable.
atomic_bits(3C) These functions provide atomic bit setting
and clearing within a variable.
atomic_cas(3C) These functions provide an atomic comparison
of a value with a variable. If the com-
parison is equal, then swap in a new value
for the variable, returning the old value of
the variable in either case.
atomic_dec(3C) These functions provide an atomic decrement
on a variable.
atomic_inc(3C) These functions provide an atomic increment
on a variable.
atomic_or(3C) These functions provide an atomic logical
'or' of a value to a variable.
atomic_swap(3C) These functions provide an atomic swap of a
value with a variable, returning the old
value of the variable.
SunOS 5.10 Last change: 12 Aug 2004 1
Standard C Library Functions atomic_ops(3C)
ATTRIBUTES
See attributes(5) for descriptions of the following attri-
butes:
SEE ALSO
atomic_add(3C), atomic_and(3C), atomic_bits(3C),
atomic_cas(3C), atomic_dec(3C), atomic_inc(3C),
atomic_or(3C), atomic_swap(3C), membar_ops(3C), attri-
butes(5)
NOTES
Atomic instructions ensure global visibility of atomically-
modified variables on completion. In a relaxed store order
system, this does not guarantee that the visibility of other
variables will be synchronized with the completion of the
atomic instruction. If such synchronization is required,
memory barrier instructions must be used. See
membar_ops(3C).
Atomic instructions can be expensive. since they require
synchronization to occur at a hardware level. This means
they should be used with care to ensure that forcing
hardware level synchronization occurs a minimum number of
times. For example, if you have several variables that need
to be incremented as a group, and each needs to be done
atomically, then do so with a mutex lock protecting all of
them being incremented rather than using the atomic_inc(3C)
operation on each of them.
Здравствуйте, Alexander G, Вы писали:
AG>Здравствуйте, remark, Вы писали:
R>>А вот с "получает результаты" заминочка. Предложенный вариант не будет работать, т.к. weak_ptr<>::expired() не передаёт видимость данных между потоками, которые освободили ассоциированный shared_ptr, и потоком которому expired() вернул true (кто-то обещал?).
AG>угу, понял.
Этот флаг можно было бы легко реализовать самому... если бы не отсутствие портируемых атомарных операций. С приходом великого и могучего C++0x жизнь станет гораздо проще:
std::atomic<bool> completion;
// on thread end, or manually by thread function:
completion.store(true, std:memory_order_release);
// completion pollingif (completion.load(std:memory_order_acquire) == true))
...
R>>Да и вообще необходимость использования поллинга как-то смущает, почему не сделать просто: R>>
AG>В таком варианте смущает возможность удаления адресата PostMessage до вызова PostMessage, во время вызова PostMessage, между PostMessage и получением сообщения — прийдётся предусмотреть проверку "существует ли адресат" и продление жизни адресата на время отправки сообщения.
Ну тут я подразумевал, что получатель WM_WORK_ACCOMPLISHED живёт столько же, сколько в твоём коде жил обработчик WM_TIMER. Если получатель может удалиться, не дождавшишь получения, то надо наворачивать что-то ещё.
1. weak_ptr должен быть готов к любым операциям с другими shared_ptr и weak_ptr в любом потоке?
2. если в сбросе shared_ptr будет всё корректно, то его синхронизация может быть выполнена таким образом, что как барьер для своих данных её использовать всё равно нельзя?
Здравствуйте, Alexander G, Вы писали:
AG>Правильно ли я понимаю, что:
AG>1. weak_ptr должен быть готов к любым операциям с другими shared_ptr и weak_ptr в любом потоке?
да
AG>2. если в сбросе shared_ptr будет всё корректно, то его синхронизация может быть выполнена таким образом, что как барьер для своих данных её использовать всё равно нельзя?
Сложно сказать. Во-первых, это ничего не документировано, поэтому что они подразумевают сказать сложно. Во-вторых, может зависеть от того как именно использовать, например, если попробовать соорудить shared_ptr из weak_ptr и это провалится, то синхронизация будет обеспечена. Но expired() для этого всё-таки видимо не предназначен.
AG>