Потокобезопасный умный указатель

valera_ee
valera_ee

На просторах интернета встречаются решения, которые предоставляют вариант умного указателя, в котором доступ к ресурсу защищён либо мьютексом, либо спинлокером.  

К примеру статья на хабре  https://habr.com/ru/post/328348/

Имеено за простоту и удобство использование мне это решение очень нравится, хотя оно не лишено недостатков.
Довольно элегантно выглядит решение:

thread_safe_ptr<Object> p = make_thread_safe_ptr<Object>();

void func_thread1(thread_safe_ptr<Object> p) 
{
    // выполнение в потоке 1
    p->process();
}

void func_thread2(thread_safe_ptr<Object> p) 
{
    // выполнение в потоке 2
    p->process();
}
7
рейтинг
10 комментариев
yndx-antoshkka

Нечто подобное есть в Boost https://www.boost.org/doc/libs/1_69_0/doc/html/thread/sds.html

Идея интересная, если готовы взяться - стоит проверить что подобные идеи раньше не предлагались и начать писать предложение.

yndx-antoshkka
valera_ee

yndx-antoshkka, Чтобы убедиться в работоспособности я сделал простенький вариант с простым тестом (проект на Qt 5):
 https://github.com/ValeraMikhaylovsky/thread_safe_ptr

Если идея вам покажется интересной, то готов услышать критику по реализации и продолжить работу в этом направлении.

valera_ee
Обновлено 
valera_ee

Посмотрел на boost::synchronized_value , идея таже, но реализация, на мой взгляд, не самая удобная. В реализации boost нужно вручную прописывать блокировку через RAII boost::strict_lock_ptr, по запарке можно и забыть, особенно если над проектом коллектив трудится. В моём варианте блокировка выполняется автоматически при доступе к ресурсу. Я не являюсь автором этой идею, реализацию увидел на хабре:
https://habr.com/ru/post/184436/
https://habr.com/ru/post/328348/

valera_ee
Обновлено 
valera_ee

valera_ee, Более внимательно посмотрел почему используют RAII в boost, проверил свой указатель на dedadlock и получил его при следующем коде:

thread_safe_ptr<Object> pObject(std::make_shared<Object>());

pObject->setValue(3);

if (pObject->valid() && pObject->method()) {
        // to do
}    

Но, конкретно в этом случае, если модифицировать код в стиле с++17, deadlock не происходит:

if (bool t_ok = pObject->valid(); t_ok && pObject->method()) {
    // to do
}

 

valera_ee
Обновлено 
valera_ee

Повторил тест на deadlock для варианта sf::safe_ptr ( https://habr.com/ru/post/328348/ ), там эта проблема решена.

valera_ee
valera_ee

Решение проблемы выполнено через рекурсивный мьютекс, скорость, конечно, не большая, но вариант рабочий, для ускорения можно рекурсивный вариант спинлока заиспользовать.

valera_ee
Олег Власов

Вроде в С++20 хотят добавить atomic_shared_ptr

cppreference.com

Олег Власов
valera_ee

Олег Власов, Я читал, но если я правильно понял, там доступ не к ресурсам, а к методам сомого shared_ptr будет потокобезопасным, если не прав поправьте меня.

valera_ee
Олег Власов

valera_ee, Я поподробнее прочитал про atomic_shared_ptr. Ты прав, он защиает сам shared_ptr, а не то на что указывает.

Олег Власов
Обновлено 
valera_ee

Обновил код  на github как самого указателя так и теста, в текущем исполнении меня полностью устраивает поведение умного указателя. Хотелось бы услышать мнение разработчиков, которые более глубоко разбираются в теме многопоточного программирования.

valera_ee
Обновлено 
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).
Все предложения