summaryrefslogtreecommitdiff
path: root/worker/worker.go
blob: ccb9939a3715a3d182af7430a28e6ae816f78a63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package worker

import (
	"auth-proxy/types"
	"runtime"
	"sync/atomic"
)

// NewWorkerPool creates and starts a new worker pool.
// The number of workers is determined by the number of CPU cores, with a minimum of 2 and a max of 16.
func NewWorkerPool() *types.WorkerPool {
	numWorkers := runtime.NumCPU()
	if numWorkers > 16 {
		numWorkers = 16
	}
	if numWorkers < 2 {
		numWorkers = 2
	}

	pool := &types.WorkerPool{
		Workers:    numWorkers,
		TaskQueue:  make(chan func(), numWorkers*2),
		ResultChan: make(chan interface{}, numWorkers*2),
		Active:     0,
	}

	for i := 0; i < numWorkers; i++ {
		pool.Wg.Add(1)
		go worker(pool)
	}

	return pool
}

// worker is a single worker goroutine that processes tasks from the TaskQueue.
func worker(p *types.WorkerPool) {
	defer p.Wg.Done()
	for task := range p.TaskQueue {
		atomic.AddInt64(&p.Active, 1)
		task()
		atomic.AddInt64(&p.Active, -1)
	}
}

// Submit adds a task to the worker pool's queue.
// This is a blocking operation if the queue is full.
func Submit(p *types.WorkerPool, task func()) {
	p.TaskQueue <- task
}

// ActiveWorkers returns the number of currently active (processing) workers.
func ActiveWorkers(p *types.WorkerPool) int64 {
	return atomic.LoadInt64(&p.Active)
}

// Close gracefully shuts down the worker pool.
// It closes the task queue and waits for all workers to finish their current tasks.
func Close(p *types.WorkerPool) {
	close(p.TaskQueue)
	p.Wg.Wait()
	close(p.ResultChan)
}