Нужна библиотека, которая выполняет задачи пулом из n воркеров. Одновременно
выполняется не больше n задач, остальные ждут в очереди ёмкостью m. Задачи
кладут по одной, в том числе из разных горутин. Когда задачи закончились, пул
закрывают и ждут, пока доработает всё, что успели положить.
type Task interface {
Do()
}
var (
ErrQueueFull = errors.New("queue is full")
ErrClosed = errors.New("pool is closed")
)
// New запускает пул из n воркеров с очередью на m задач. n >= 1, m >= 1.
func New(n, m int) *Pool
// Submit ставит задачу в очередь. Никогда не блокируется.
func (p *Pool) Submit(t Task) error
// Close перестаёт принимать задачи и ждёт завершения всех принятых.
func (p *Pool) Close()
Требования
- Одновременно выполняется не больше
n задач. При этом пул действительно
параллелен: если задач хватает, работают все n воркеров.
- Если очередь заполнена (все воркеры заняты и в очереди уже
m задач),
Submit сразу возвращает ErrQueueFull. Ждать освобождения места нельзя.
Submit после Close возвращает ErrClosed, без паники, даже если вызовы
идут конкурентно с Close.
Close возвращается только после того, как выполнены все задачи, принятые
через Submit (то есть вернувшие nil). Повторный Close ничего не делает.
- После
Close в пуле не остаётся горутин.
- Код должен проходить
go test -race.
Пример
p := New(2, 10)
for i := 0; i < 5; i++ {
if err := p.Submit(sleepTask(100 * time.Millisecond)); err != nil {
log.Println(err)
}
}
p.Close() // ≈ 300 мс: 5 задач по 100 мс на 2 воркерах
Устно: как разложить такую библиотеку по пакетам и файлам, что из неё
экспортировать?
Разбор и эталонное решение — после своей попытки: на собеседовании подсказок не будет.
Сначала попробуй сам — подсказки не дают готовый ответ.