Читаем Параллельное программирование на С++ в действии полностью

Третий вариант — возвращать не копию вытолкнутого элемента по значению, а указатель на него. Его достоинство в том, указатели можно копировать, не опасаясь исключений, поэтому указанную Каргиллом проблему мы обходим. А недостаток в том, что возврат указателя заставляет искать средства для управления выделенной объекту памятью, так что для таких простых типов, как целые числа, накладные расходы на управление памятью могут превысить затраты на возврат типа по значению. В любом интерфейсе, где применяется этот вариант, в качестве типа указателя было бы разумно избрать std::shared_ptr; мало того что это предотвращает утечки памяти, поскольку объект уничтожается вместе с уничтожением последнего указателя на него, так еще и библиотека полностью контролирует схему распределения памяти и не требует использования new и delete. Это существенно с точки зрения оптимизации — требование, чтобы память для всякого хранящегося в стеке объекта выделялась с помощью new, повлекло бы заметные накладные расходы по сравнению с исходной версией, небезопасной относительно потоков.

Вариант 4: реализовать одновременно вариант 1 и один из вариантов 2 или 3

Никогда не следует пренебрегать гибкостью, особенно в обобщенном коде. Если остановиться на варианте 2 или 3, то будет сравнительно нетрудно реализовать и вариант 1, а это оставит пользователю возможность выбрать наиболее подходящее решение ценой очень небольших накладных расходов.

Пример определения потокобезопасного стека

В листинге 3.4 приведено определение класса стека со свободным от гонок интерфейсом. В нем реализованы приведенные выше варианты 1 и 3: имеется два перегруженных варианта функции-члена pop() — один принимает ссылку на переменную, в которой следует сохранить значение, а второй возвращает std::shared_ptr<>. Интерфейс предельно прост, он содержит только функции: push() и pop().

Листинг 3.4. Определение класса потокобезопасного стека

#include

struct empty_stack: std::exception {

 const char* what() const throw();

};

template

class threadsafe_stack {

public:

 threadsafe_stack();

 threadsafe_stack(const threadsafe_stack&);

 threadsafe_stack& operator=(const threadsafe_stack&)

  = delete;←(1)

 void push(T new_value);

 std::shared_ptr pop();

 void pop(T& value);

 bool empty() const;

};

Упростив интерфейс, мы добились максимальной безопасности — даже операции со стеком в целом ограничены: стек нельзя присваивать, так как оператор присваивания удален (1) (см. приложение А, раздел А.2) и функция swap() отсутствует. Однако стек можно копировать в предположении, что можно копировать его элементы. Обе функции pop() возбуждают исключение empty_stack, если стек пуст, поэтому программа будет работать, даже если стек был модифицирован после вызова empty(). В описании варианта 3 выше отмечалось, что использование std::shared_ptr позволяет стеку взять на себя распределение памяти и избежать лишних обращений к new и delete. Теперь из пяти операций со стеком осталось только три: push(), pop() и empty(). И даже empty() лишняя. Чем проще интерфейс, тем удобнее контролировать доступ к данным — можно захватывать мьютекс на все время выполнения операции. В листинге 3.5 приведена простая реализация в виде обертки вокруг класс std::stack<>.

Листинг 3.5. Определение класса потокобезопасного стека

#include

#include

#include

#include

struct empty_stack: std::exception {

 const char* what() const throw();

};

template

class threadsafe_stack {

private:

 std::stack data;

 mutable std::mutex m;

public:

 threadsafe_stack(){}

 threadsafe_stack(const threadsafe_stack& other) {

  std::lock_guard lock(other.m);

  data = other.data; ←┐(1) Копирование производится в теле

 }                    │конструктора

 threadsafe_stack& operator=(const threadsafe_stack&) = delete;

 void push(T new_value) {

  std::lock_guard lock(m);

  data.push(new_value);

 }

 std::shared_ptr pop()│Перед тем как выталкивать значение,

 {                      ←┘проверяем, не пуст ли стек

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных

Все жанры