Инструменты параллельного программирования могут облегчить выражение даже не-многопоточных идей. Вот пример, извлеченный из RPC пакета. Клиентская программа выполняет цикл получения данных из какого-либо источника, возможно сети. Чтобы избежать выделения и освобождения буферов, она сохраняет свободный список, и использует буферизованный канал для его представления. Если канал пуст, выделяется новый буфер. Когда буфер сообщений готов, он отправляется на сервер serverChan
.
var freeList = make(chan *Buffer, 100)
var serverChan = make(chan *Buffer)
func client() {
for {
var b *Buffer
// Берем буфер, если он доступен;
// иначе - аллоцируем новый.
select {
case b = <-freeList:
// Получили буфер; больше ничего не делаем.
default:
// Нет свободных, поэтому аллоцируем новый.
b = new(Buffer)
}
// Читаем следующее сообщение из сети.
load(b)
serverChan <- b // Отправляем на сервер.
}
}
Цикл сервера получает каждое сообщение от клиента, обрабатывает его, и возвращает буфер в свободный список.
func server() {
for {
b := <-serverChan // Ожидание работы.
process(b)
// Повторно используем буфер, если есть место.
select {
case freeList <- b:
// Буфер в свободном списке;
// больше ничего не делаем.
default:
// Список свободных полон, просто продолжаем.
}
}
}
Клиент пытается получить буфер из freeList
; если ни один не доступен, он выделяет новый. Отправка сервером в freeList
возвращает b
в список свободных если список не полный, иначе буфер выбрасывается, чтобы быть утилизированным сборщиком мусора. (Условие default
в select
операторах выполняются, когда ни один другой случай не готов, это означает, что select
никогда не блокируется.) Эта реализация создает список без утечек памяти всего в несколько строк, полагаясь на буферизованный канал и сборщик мусора для учета.
Читайте также:
Комментариев нет:
Отправить комментарий