НавязчивыйКрюки могут быть сконфигурированы для использования других указателей, чем необработанные указатели. Когданапрягает.Крюк сконфигурирован с умным указателем в качестве аргумента, эта конфигурация указателя передается контейнерам. Например, если следующий крюк выполнен с умным указателем (например, офсетным указателем отBoost.Interprocess).:
#include <boost/intrusive/list.hpp>
#include <boost/interprocess/offset_ptr.hpp>
using namespace boost::intrusive;
namespace ip = boost::interprocess;
class shared_memory_data
: public list_base_hook< void_pointer< ip::offset_ptr<void> > >
{
int data_id_;
public:
int get() const { return data_id_; }
void set(int id) { data_id_ = id; }
};
Любой интрузивный список, построенный с использованием этого крючка, будет готов для совместной памяти, потому что интрузивный список также будет использовать офсетные указатели внутри. Например, мы можем создать назойливый список в общей памяти, объединяющийBoost.InterprocessиBoost.Intrusive:
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
typedef list<shared_memory_data> intrusive_list_t;
int main()
{
const int MaxElem = 100;
const int ShmSize = 50000;
const char *ShmName = get_shared_memory_name();
{
ip::shared_memory_object::remove(ShmName);
ip::managed_shared_memory shm(ip::create_only, ShmName, ShmSize);
typedef ip::allocator
< shared_memory_data, ip::managed_shared_memory::segment_manager>
shm_allocator_t;
typedef ip::vector<shared_memory_data, shm_allocator_t> shm_vector_t;
shm_allocator_t shm_alloc(shm.get_segment_manager());
shm_vector_t *pshm_vect =
shm.construct<shm_vector_t>(ip::anonymous_instance)(shm_alloc);
pshm_vect->resize(MaxElem);
for(int i = 0; i < MaxElem; ++i) (*pshm_vect)[i].set(i);
intrusive_list_t *plist = shm.construct<intrusive_list_t>(ip::anonymous_instance)();
plist->insert(plist->end(), pshm_vect->begin(), pshm_vect->end());
int checker = 0;
for( intrusive_list_t::const_iterator it = plist->begin(), itend(plist->end())
; it != itend; ++it, ++checker){
if(it->get() != checker) return false;
}
shm.destroy_ptr(plist);
shm.destroy_ptr(pshm_vect);
}
ip::shared_memory_object::remove(ShmName);
return 0;
}
Не каждый умный указатель совместим сBoost.Intrusive:
- Совместимость с C++11<
std::pointer_traits
>требования.Boost.Intrusiveиспользует свой собственный<pointer_traits
>класс для реализации этих функций в компиляторах C++11 и C++03.
- Он должен иметь ту же семантику владения, что и сырой указатель. Это означает, что умные указатели управления ресурсами (например,<
boost::shared_ptr
>) не могут быть использованы.
Преобразование из умного указателя в необработанный указатель будет осуществляться в виде рекурсивного вызова<operator->()
>до тех пор, пока функция не вернет необработанный указатель.