Чтение онлайн

на главную - закладки

Жанры

C++. Сборник рецептов

Когсуэлл Джефф

Шрифт:

boost::once_flag Conn::initFlag_ = BOOST_ONCE_INIT;

Затем в моей рабочей функции я вызываю

call_once
, которая синхронизирует доступ к моему инициализированному флагу и, следовательно, предотвращает параллельное выполнение другой инициализации. Я передаю в
call_once
два аргумента:

boost::call_once(Conn::init, Conn::initFlag_);

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

выполнить инициализацию, но только первый в этом преуспеет.

12.5. Передача аргумента функции потока

Проблема

Требуется передать аргумент в вашу функцию потока, однако средствами библиотеки Boost Threads предусматривается передача только функторов без аргументов.

Решение

Создайте адаптер функтора, который принимает ваши параметры и возвращает функтор без параметров. Адаптер функтора можно использовать там, где должен был бы быть функтор потока. Пример 12.6 показывает, как это можно сделать.

Пример 12.6. Передача аргументов функции потока

#include <iostream>

#include <string>

#include <functional>

#include <boost/thread/thread.hpp>

// typedef используется для того, чтобы приводимые ниже объявления лучше

// читались

typedef void (*WorkerFunPtr)(const std::string&);

template<typename FunT, // Тип вызываемой функции

 typename ParamT> // тип ее параметра

struct Adapter {

 Adapter(FunT f, ParamT& p) : // Сконструировать данный адаптер и

f_(f), p_(&p) {} // установить члены на значение функции и ее

// аргумента

 void operator { // Просто вызов функции с ее аргументом

f_(*p_);

 }

private:

 FunT f_;

 ParamT* p_; // Использовать адрес параметра. чтобы избежать лишнего

// копирования

};

void worker(const std::string& s) {

 std::cout << s << '\n';

}

int main {

 std::string s1 = "This is the first thread!";

 std::string s2 = "This is the second thread!";

 boost::thread thr1(Adapter<WorkerFunPtr, std::string>(worker, s1));

 boost::thread thr2(Adapter<WorkerFunPtr, std::string>(worker, s2));

 thr1.join;

 thr2.join;

}

Обсуждение

Здесь

приходится решать принципиальную проблему, причем характерную не только для потоков или проекта Boost, а общую проблему, возникающую при необходимости передачи функтора с одной сигнатурой туда, где требуется другая сигнатура. Решение состоит в создании адаптера.

Синтаксис может показаться немного путаным, но фактически в примере 12.6 создается временный функтор, который может вызываться конструктором потока как функция без аргументов (требуется именно такая функция). Но прежде всего используйте

typedef
, чтобы указатель функции лучше воспринимался в тексте.

typedef void (*WorkerFunPtr)(const std::string&);

Это создает тип

WorkerFunPtr
, который является указателем на функцию, принимающую по ссылке аргумент типа
string
и возвращающую тип
void
. После этого я создал шаблон класса
Adapter
. Он обеспечивает инстанцирование динамического функтора. Обратите внимание на конструктор:

template<Typename FunT,

 typename ParamT>

struct Adapter {

 Adapter(FunT f, ParamT& p) : f_(f), p_(&p) {}

 // ...

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

p
любого типа. Ради повышения эффективности я сохраняю адрес параметра, а не его значение.

Теперь рассмотрим следующую строку главного потока.

boost::thread thr1(Adapter<WorkerFunPtr, std::string>(worker, s1))

Аргумент конструктора

thr1
представляет собой реализацию шаблона класса
Adapter
, использующую в качестве параметров два типа
WorkerFunPtr
и
std::string
. Это именно те два типа, которые являются членами адаптера
f_
и
p_
. Наконец,
Adapter
перегружает
operator
, поэтому он может вызываться как функция. Его вызов означает просто выполнение следующей функции.

f_(*p_);

Применяя шаблон класса

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

Глава 13

Интернационализация

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

70 Рублей

Кожевников Павел
1. 70 Рублей
Фантастика:
фэнтези
боевая фантастика
попаданцы
постапокалипсис
6.00
рейтинг книги
70 Рублей

Жатва душ. Остров мертвых

Сугралинов Данияр
Фантастика:
боевая фантастика
рпг
5.20
рейтинг книги
Жатва душ. Остров мертвых

Сердце Дракона. Том 9

Клеванский Кирилл Сергеевич
9. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.69
рейтинг книги
Сердце Дракона. Том 9

Как я строил магическую империю 6

Зубов Константин
6. Как я строил магическую империю
Фантастика:
попаданцы
аниме
фантастика: прочее
фэнтези
5.00
рейтинг книги
Как я строил магическую империю 6

Леди для короля. Оборотная сторона короны

Воронцова Александра
3. Королевская охота
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Леди для короля. Оборотная сторона короны

Кодекс Крови. Книга VI

Борзых М.
6. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга VI

Газлайтер. Том 4

Володин Григорий
4. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 4

АллатРа

Новых Анастасия
Научно-образовательная:
психология
история
философия
обществознание
физика
6.25
рейтинг книги
АллатРа

Газлайтер. Том 10

Володин Григорий
10. История Телепата
Фантастика:
боевая фантастика
5.00
рейтинг книги
Газлайтер. Том 10

Дорога к счастью

Меллер Юлия Викторовна
Любовные романы:
любовно-фантастические романы
6.11
рейтинг книги
Дорога к счастью

Газлайтер. Том 8

Володин Григорий
8. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 8

Камень Книга седьмая

Минин Станислав
7. Камень
Фантастика:
фэнтези
боевая фантастика
6.22
рейтинг книги
Камень Книга седьмая

Николай I Освободитель. Книга 2

Савинков Андрей Николаевич
2. Николай I
Фантастика:
героическая фантастика
альтернативная история
5.00
рейтинг книги
Николай I Освободитель. Книга 2

Секретарша генерального

Зайцева Мария
Любовные романы:
современные любовные романы
эро литература
короткие любовные романы
8.46
рейтинг книги
Секретарша генерального