13.2.9. Реализация параллельных итераторов
13.2.9. Реализация параллельных итераторов
Предположим, что нужно параллельно обходить несколько объектов, то есть для каждого объекта найти первый элемент, потом второй, потом третий и т.д.
Рассмотрим следующий пример. Пусть compose — имя магического метода, который выполняет композицию итераторов. Допустим еще, что у каждого объекта есть стандартный итератор each и что каждый объект возвращает по одному элементу на каждой итерации.
arr1 = [1, 2, 3, 4]
arr2 = [5, 10, 15, 20]
compose(arr1, arr2) {|a,b| puts "#{а} и #{b}" }
# Должно быть напечатано:
# 1 и 5
# 2 и 10
# 3 и 15
# 4 и 20
Можно было бы, конечно, использовать для этой цели zip. Но если нужно более элегантное решение, при котором все элементы не будут храниться одновременно, то без потоков не обойтись. Такое решение представлено в листинге 13.7.
Листинг 13.7. Параллельные итераторы
def compose(*objects)
threads = []
for obj in objects do
threads << Thread.new(obj) do |myobj|
me = Thread.current
me[:queue] = []
myobj.each {|x| me[:queue].push(x) }
end
end
list = [0] # Фиктивное значение, отличное от nil.
while list.nitems > 0 do # Еще есть не nil.
list = []
for thr in threads
list << thr[:queue].shift # Удалить по одному из каждого.
end
yield list if list.nitems > 0 # He вызывать yield, если все равны nil.
end
end
x = [1, 2, 3, 4, 5, 6, 7, 8]
y = " первый второй третий четвертый пятый "
z = %w[a b с d e f]
compose(x, у, z) {|a,b,c| p [a, b, c] }
# Выводится:
# [1, " первый ", "a"]
# [2, " второй ", "b"]
# [3, " третий ", "c"]
# [4, " четвертый ", "d"]
# [5, " пятый ", "e"]
# [6, nil, "f"]
# [7, nil, nil]
# [8, nil, nil]
Обратите внимание: мы не предполагаем, что все объекты имеют одно и то же число элементов. Если один итератор доходит до конца раньше остальных, то он будет генерировать значения nil до тех пор, пока не закончит работу «самый длинный» итератор.
Конечно, можно написать и более общий метод, который на каждой итерации будет обрабатывать более одного элемента. (В конце концов, не все итераторы возвращают по одному значению за раз.) Можно было бы в первом параметре передавать число значений для каждого итератора.
Можно также пользоваться произвольными итераторами (а не только стандартным each). Их имена можно было бы передавать в виде строк, а вызывать с помощью метода send. Много чего еще можно придумать.
Впрочем, мы полагаем, что приведенного кода достаточно для большинства целей. Вариации на эту тему оставляем читателю в качестве упражнения.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКДанный текст является ознакомительным фрагментом.
Читайте также
Реализация TCP/IP
Реализация TCP/IP Прежде чем перейти к описанию функционирования модулей протоколов TCP/IP, рассмотрим еще одну структуру данных, называемую управляющим блоком протокола (Protocol Control Block, PCB), который в случае TCP/IP называется Internet PCB, и представлен структурой inpcb, определенной в
Частотный анализ в последовательно-параллельных цепях переменного тока
Частотный анализ в последовательно-параллельных цепях переменного тока На рис. 2.13 приведена еще одна цепь на переменном токе. Значения параметров: V=100?0° В; R1=10 Ом; R2=10 Ом, L=100 мГн и С=10 мкФ. Предположим, что резонансная частота неизвестна, и ее необходимо предварительно
12. Кодирование параллельных вычислений
12. Кодирование параллельных вычислений РезюмеЕсли ваше приложение использует несколько потоков или процессов, следует минимизировать количество совместно используемых объектов, где это только можно (см. рекомендацию 10), и аккуратно работать с
Теги итераторов (Iterator tags)
Теги итераторов (Iterator tags) Чтобы осуществлять алгоритмы только в терминах итераторов, часто бывает необходимо вывести тип значения и тип расстояния из итератора. Для решения этой задачи требуется, чтобы для итератора i любой категории, отличной от итератора вывода,
Примеры использования тегов итераторов
Примеры использования тегов итераторов Для всех типов обычных указателей мы можем определить value_type и distance_type с помощью следующего:template ‹class T›inline T* value_type(const T*) {return (T*)(0);}template ‹class T›inline ptrdiff_t* distance_type(const T*) {return (ptrdiff_t*)(0);}Тогда, если мы хотим осуществить обобщённую функцию
Адаптеры итераторов (Iterator adaptors)
Адаптеры итераторов (Iterator adaptors) Обратные итераторы (Reverse iterators) Двунаправленные итераторы и итераторы произвольного доступа имеют соответствующие адаптеры обратных итераторов, которые выполняют итерации через структуру данных в противоположном направлении.Они имеют
11.2. Реализация
11.2. Реализация Во всех более-менее сложных C-программах требуется тщательно продумать организацию, чтобы сохранить модульность и обеспечить удобство сопровождения. Наша демонстрационная программа разделена на четыре главных исходных файла.В каждом исходном файле
12.4.6. Пять категорий итераторов
12.4.6. Пять категорий итераторов Для поддержки полного набора обобщенных алгоритмов стандартная библиотека определяет пять категорий итераторов, положив в основу классификации множество операций. Это итераторы чтения (InputIterator), записи (OutputIterator), однонаправленные
7.3.2 Реализация
7.3.2 Реализация Реализующие slist функции в основном просты. Единственая настоящая сложность – что делать в случае ошибки, если, например, пользователь попытается get() что-нибудь из пустого списка. Мы обсудим это в #7.3.4. Здесь приводятся определения членов slist. Обратите
14.5. Реализация
14.5. Реализация Теперь мы приступим к реализации нашей оболочки, следуя тем идеям, которые обсуждались в предыдущем разделе. На рис. 14.9 показаны основные объекты, которыми манипулирует оболочка. Цель — это вопрос, подлежащий рассмотрению; Трасса — это цепочка,
Василий Щепетнёв: О параллельных мирах Василий Щепетнев
Василий Щепетнёв: О параллельных мирах Василий Щепетнев Опубликовано 30 ноября 2011 года Алексей Жариков в комментариях к недавней колонке спрашивает: "Как вы думаете, разрешил бы ваш любимый Гайдай зрителю поменять концовку «Кавказской пленницы»
12.10. РЕАЛИЗАЦИЯ
12.10. РЕАЛИЗАЦИЯ Обычно на этапе кодирования всплывают все неприятные проблемы, которые только можно себе представить. Чем больше проект, тем больше проблем. Вот почему первые три шага так важны.Если все из вышеописанных шагов полностью пройдены, то реализация программы
Василий Щепетнёв: О параллельных мирах
Василий Щепетнёв: О параллельных мирах Автор: Василий ЩепетневОпубликовано 30 ноября 2011 годаАлексей Жариков в комментариях к недавней колонке спрашивает: "Как вы думаете, разрешил бы ваш любимый Гайдай зрителю поменять концовку "Кавказской пленницы" так, чтобы зло
Фултон Хэл
Просмотр ограничен
Смотрите доступные для ознакомления главы 👉