Вход/Регистрация
Эффективное использование STL
вернуться

Мейерс Скотт

Шрифт:

template<typename T, typename Heap>

SpecificHeapAllocator{

public:

 …

 pointer allocate(size_type numObjects,const void *localityHint=0) {

return static_cast<pointer>(Heap::alloc(numObjects*sizeof(T), localityHint));

 }

 void deallocate(pointer ptrToMemory, size_type numObjects) {

Heap::dealloc(ptrToMemory);

 }

 …

};

Затем

SpecialHeapAllocator
группирует элементы контейнеров:

vector<int, SpecificHeapAllocator<int, Heap1> > v; // Разместить элементы

set<int, SpecificHeapAllocator<int, Heap1> > s; // v и s в Heapl

list<Widget,

 SpecificHeapAllocator<Widget, Heap2> > L; // Разместить элементы

map<int, string, less<int>, // L и m в Heap2

SpecificHeapAllocator<pair<const int, string>, Heap2> > m;

В приведенном примере очень важно, чтобы

Heap1
и
Неар2
были типами, а не объектами. В STL предусмотрен синтаксис инициализации разных контейнеров STL разными объектами распределителей одного типа, но я не буду его приводить. Дело в том, что если бы
Heap1
и
Неар2
были бы объектами вместо типов, это привело бы к нарушению ограничения эквивалентности, подробно описанного в совете 10.

Как показывают приведенные примеры, распределители приносят пользу во многих ситуациях. При соблюдении ограничения об эквивалентности однотипных распределителей у вас не будет проблем с применением нестандартных распределителей для управления памятью, группировки, а также использования общей памяти и других специализированных пулов.

Совет 12. Разумно оценивайте потоковую безопасность контейнеров STL

Мир стандартного C++ выглядит старомодным и не подверженным веяниям времени. В этом мире все исполняемые файлы компонуются статически, в нем нет ни файлов, отображаемых на память, ни общей памяти. В нем нет графических оконных систем, сетей и баз данных, нет и других процессов. Вероятно, не стоит удивляться тому, что в Стандарте не сказано ни слова о программных потоках. О потоковой безопасности в STL можно уверенно сказать только одно: что она полностью зависит от реализации.

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

«Золотой стандарт» поддержки многопоточности в контейнерах STL (которым руководствуется большинство разработчиков) был определен компанией SGI и опубликован на ее web-сайте, посвященном STL [21]. Фактически в нем сказано, что в лучшем случае можно надеяться на следующее:

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

• безопасность записи в разные контейнеры. Несколько потоков могут одновременно производить запись в разные контейнеры.

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

Многопоточное программирование считается сложной задачей, и многие программисты желают, чтобы реализации STL изначально обеспечивали полную потоковую безопасность. Это избавило бы их от необходимости самостоятельно синхронизировать доступ. Конечно, это было бы очень удобно, однако добиться этой цели очень сложно. Рассмотрим несколько способов реализации полной потоковой безопасности контейнеров:

• блокировка контейнера на время вызова любой функции;

• блокировка контейнера в течение жизненного цикла каждого возвращаемого итератора (например посредством вызова

begin
или
end
);

• блокировка контейнера на протяжении работы каждого алгоритма, вызванного для этого контейнера. В действительности это бессмысленно, поскольку, как будет показано в совете 32, алгоритм не располагает средствами идентификации контейнера, с которым он работает. Тем не менее, мы изучим этот вариант — будет поучительно увидеть, почему он в принципе неработоспособен.

Рассмотрим следующий фрагмент, который ищет в

vector<int>
первое вхождение числа 5 и заменяет его нулем:

  • Читать дальше
  • 1
  • ...
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: