Энтони Уильямс - Параллельное программирование на С++ в действии. Практика разработки многопоточных программ

Тут можно читать онлайн Энтони Уильямс - Параллельное программирование на С++ в действии. Практика разработки многопоточных программ - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming, издательство ДМК Пресс, год 2012. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    Параллельное программирование на С++ в действии. Практика разработки многопоточных программ
  • Автор:
  • Жанр:
  • Издательство:
    ДМК Пресс
  • Год:
    2012
  • Город:
    Москва
  • ISBN:
    978-5-94074-448-1
  • Рейтинг:
    5/5. Голосов: 11
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 100
    • 1
    • 2
    • 3
    • 4
    • 5

Энтони Уильямс - Параллельное программирование на С++ в действии. Практика разработки многопоточных программ краткое содержание

Параллельное программирование на С++ в действии. Практика разработки многопоточных программ - описание и краткое содержание, автор Энтони Уильямс, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru
В наши дни компьютеры с несколькими многоядерными процессорами стали нормой. Стандарт С++11 языка С++ предоставляет развитую поддержку многопоточности в приложениях. Поэтому, чтобы сохранять конкурентоспособность, вы должны овладеть принципами и приемами их разработки, а также новыми средствами языка, относящимися к параллелизму.
Книга «Параллельное программирование на С++ в действии» не предполагает предварительных знаний в этой области. Вдумчиво читая ее, вы научитесь писать надежные и элегантные многопоточные программы на С++11. Вы узнаете о том, что такое потоковая модель памяти, и о том, какие средства поддержки многопоточности, в том числе запуска и синхронизации потоков, имеются в стандартной библиотеке. Попутно вы познакомитесь с различными нетривиальными проблемами программирования в условиях параллелизма.

Параллельное программирование на С++ в действии. Практика разработки многопоточных программ - читать онлайн бесплатно полную версию (весь текст целиком)

Параллельное программирование на С++ в действии. Практика разработки многопоточных программ - читать книгу онлайн бесплатно, автор Энтони Уильямс
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

int main() {

std::function offset_42 = make_offseter(42);

std::function offset_123 = make_offseter(123);

std::cout <<

offset_42(12) << "," << offset_123(12) << std::endl;

std::cout <<

offset_42(12) << "," << offset_123(12) << std::endl;

}

два раза выведет числа 54, 135, потому что функция, возвращенная после первого обращения к make_offseter, всегда добавляет 42 к переданному ей аргументу Напротив, функция, возвращенная после второго обращения к make_offseter, добавляет к своему аргументу 123. Это самый безопасный вид захвата локальных переменных — все значения копируются, поэтому лямбда-функцию можно вернуть и вызывать вне контекста функции, в которой она была создана. Но это не единственно возможное решение, можно захватывать локальные переменные и по ссылке. В таком случае попытка вызвать лямбда-функцию после того, как переменные, на которые указывают ссылки, были уничтожены в результате выхода из области видимости объемлющей их функции или блока, приведёт к неопределённому поведению, точно так же, как обращение к уничтоженной переменной в любом другом случае.

Лямбда-функция, захватывающая все локальные переменные по ссылке, начинается интродуктором [&]:

int main() {

int offset = 42; ← (1)

std::function offset_a =

[&](int j){return offset + j;};← (2)

offset = 123; ← (3)

std::function offset_b =

[&](int j){return offset + j;};← (4)

std::cout <<

offset_a(12) << "," << offset_b(12) << std::endl; ← (5)

offset = 99; ← (6)

std::cout <<

offset_a(12) << "," << offset_b(12) << std::endl; ← (7)

}

Если функция make_offseterиз предыдущего примера захватывала копию смещения offset, то функция offset_aв этом примере, начинающаяся интродуктором [&], захватывает offsetпо ссылке (2). Неважно, что начальное значение offsetбыло равно 42 (1); результат вызова offset_a(12)зависит от текущего значения offset. Значение offsetбыло изменено на 123 (3)перед порождением второй (идентичной) лямбда-функции offset_b (4), но эта вторая функция снова производит захват по ссылке, поэтому результат, как и прежде, зависит от текущего значения offset.

Теперь при печати первой строки (5), offsetвсё еще равно 123, поэтому печатаются числа 133, 135. Однако к моменту печати второй строки (7) offsetстало равно 99 (6), поэтому печатается 111, 111. И offset_a, и offset_bприбавляют текущее значение offset(99) к переданному аргументу (12).

Но ведь это С++, поэтому вам не обязательно выбирать между всем или ничем; вполне можно захватывать одни переменные по значению, а другие по ссылке. Более того, можно даже указывать, какие именно переменные захватить. Нужно лишь изменить лямбда-интродуктор. Если требуется скопировать все видимые переменные, кроме одной-двух, то воспользуйтесь интродуктором [=], но после знака равенства перечислите переменные, захватываемые по ссылке, предпослав им знаки амперсанда. В следующем примере печатается 1239, потому что переменная iкопируется в лямбда-функцию, a jи kзахватываются по ссылке:

int main() {

int i=1234, j=5678, k=9;

std::function f=[=,&j,&k] {return i+j+k;};

i = 1;

j = 2;

k = 3;

std::cout << f() << std::endl;

}

Можно поступить и наоборот — по умолчанию захватывать по ссылке, но некоторое подмножество переменных копировать. В таком случае воспользуйтесь интродуктором [&], а после знака амперсанда перечислите переменные, захватываемые по значению. В следующем примере печатается 5688, потому что iзахватывается по ссылке, a jи kкопируются:

int main() {

int i=1234, j=5678, k= 9;

std::function f=[&,j,k] {return i+j+k;};

i = 1;

j = 2;

k = 3;

std::cout << f() << std::endl;

}

Если требуется захватить только именованные переменные, то можно опустить знак =или &и просто перечислить захватываемые переменные, предпослав знак амперсанда тем, что должны захватываться по ссылке, а не по значению. В следующем примере печатается 5682, потому что iи kзахвачены по ссылке, a jскопирована

int main() {

int i=1234, j=5678, k=9;

std::function f=[&i, j, &k] {return i+j+k;};

i = 1;

j = 2;

k = 3;

std::cout << f() << std::endl;

}

Последний способ заодно гарантирует, что захвачены только необходимые переменные, потому что ссылка на локальную переменную, отсутствующую в списке захвата, приведёт к ошибке компиляции. Выбирая этот вариант, нужно соблюдать осторожность при доступе к членам класса, если лямбда-функция погружена в функцию-член класса. Члены класса нельзя захватывать непосредственно; если к ним необходим доступ из лямбда-функции, то необходимо захватить указатель this, включив его в список захвата. В следующем примере лямбда-функция захватывает thisдля доступа к члену класса some_data:

struct X {

int some_data;

void foo(std::vector& vec) {

std::for_each(vec.begin(), vec.end(),

[this](int& i){ i += some_data; });

}

};

В контексте параллелизма лямбда-функции особенно полезны для задания предикатов функции std::condition_variable::wait()(см. раздел 4.1.1) и в сочетании с std::packaged_task<>(раздел 4.2.1) или пулами потоков для упаковки небольших задач. Их можно также передавать конструктору std::threadв качестве функций потока (раздел 2.1.1) и в качестве исполняемой функции в таких параллельных алгоритмах, как parallel_for_each()(раздел 8.5.1).

А.6. Шаблоны с переменным числом параметров

Функции с переменным числом параметров, например printf, используются уже давно, а теперь появились и шаблоны с переменным числом параметров (variadic templates). Такие шаблоны применяются во многих местах библиотеки С++ Thread Library. Например, конструктор std::threadдля запуска потока (раздел 2.1.1) — это шаблон функции с переменным числом параметров, a std::packaged_task<>(раздел 4.2.2) — шаблон класса с переменным числом параметров. С точки зрения пользователя, достаточно знать, что шаблон принимает неограниченное количество параметров, но если вы хотите написать такой шаблон или просто любопытствуете, как это работает, то детали будут небезынтересны.

При объявлении шаблонов с переменным числом параметров, по аналогии с обычными функциями, употребляется многоточие ( ...) в списке параметров шаблона:

template

class my_template {};

Переменное число параметров допустимо и в частичных специализациях шаблона, даже если основной шаблон содержит фиксированное число параметров. Например, основной шаблон std::packaged_task<>(раздел 4.2.1) — это простой шаблон с единственным параметром:

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Энтони Уильямс читать все книги автора по порядку

Энтони Уильямс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




Параллельное программирование на С++ в действии. Практика разработки многопоточных программ отзывы


Отзывы читателей о книге Параллельное программирование на С++ в действии. Практика разработки многопоточных программ, автор: Энтони Уильямс. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x