Prompts for GPT

avatar User

gopool.go package gopool

import ( "sync" )

type Task func()

type GoPool struct { Workers []*Worker MaxWorkers int MinWorkers int workerStack []int taskQueue chan Task lock sync.Locker cond *sync.Cond }

type Option func(*GoPool)

func WithLock(lock sync.Locker) Option { return func(p *GoPool) { p.lock = lock p.cond = sync.NewCond(p.lock) } }

func WithMinWorkers(minWorkers int) Option { return func(p *GoPool) { p.MinWorkers = minWorkers } }

func NewGoPool(maxWorkers int, opts ...Option) *GoPool { pool := &GoPool{ MaxWorkers: maxWorkers, MinWorkers: maxWorkers, // Set MinWorkers to MaxWorkers by default Workers: make([]*Worker, maxWorkers), workerStack: make([]int, maxWorkers), taskQueue: make(chan Task, 1e6), lock: new(sync.Mutex), } for _, opt := range opts { opt(pool) } if pool.cond == nil { pool.cond = sync.NewCond(pool.lock) } for i := 0; i < pool.MinWorkers; i++ { worker := newWorker() pool.Workers[i] = worker pool.workerStack[i] = i worker.start(pool, i) } go pool.dispatch() return pool }

func (p *GoPool) AddTask(task Task) { p.taskQueue <- task }

func (p *GoPool) Release() { close(p.taskQueue) p.cond.L.Lock() for len(p.workerStack) != p.MaxWorkers { p.cond.Wait() } p.cond.L.Unlock() for _, worker := range p.Workers { close(worker.TaskQueue) } p.Workers = nil p.workerStack = nil }

func (p *GoPool) popWorker() int { p.lock.Lock() workerIndex := p.workerStack[len(p.workerStack)-1] p.workerStack = p.workerStack[:len(p.workerStack)-1] p.lock.Unlock() return workerIndex }

func (p *GoPool) pushWorker(workerIndex int) { p.lock.Lock() p.workerStack = append(p.workerStack, workerIndex) p.lock.Unlock() p.cond.Signal() }

func (p *GoPool) dispatch() { for task := range p.taskQueue { p.cond.L.Lock() for len(p.workerStack) == 0 { p.cond.Wait() } p.cond.L.Unlock() workerIndex := p.popWorker() p.Workers[workerIndex].TaskQueue <- task if len(p.taskQueue) > (p.MaxWorkers-p.MinWorkers)/2+p.MinWorkers && len(p.workerStack) < p.MaxWorkers { worker := newWorker() p.Workers = append(p.Workers, worker) p.workerStack = append(p.workerStack, len(p.Workers)-1) worker.start(p, len(p.Workers)-1) } else if len(p.taskQueue) < p.MinWorkers && len(p.workerStack) > p.MinWorkers { p.Workers = p.Workers[:len(p.Workers)-1] p.workerStack = p.workerStack[:len(p.workerStack)-1] } } }

worker.go package gopool

type Worker struct { TaskQueue chan Task }

func newWorker() *Worker { return &Worker{ TaskQueue: make(chan Task, 1), } }

func (w *Worker) start(pool *GoPool, workerIndex int) { go func() { for task := range w.TaskQueue { if task != nil { task() } pool.pushWorker(workerIndex) } }() }

Next, I need you to optimize some details:

  1. Add comments to all public methods;
  2. Change methods and properties that do not need to be public to start with lowercase letters, such as the properties in GoPool;
  3. Split the Option-related code into a new source file.

avatar DevChat

According to your requirements, I will make the following modifications to the code:

  1. Add comments to all public methods.
  2. Change methods and properties that do not need to be public to start with lowercase letters, such as the properties in GoPool.
  3. Split the Option-related code into a new source file.

Here is the modified gopool.go file:

package gopool

import (
    "sync"
)

// Task represents a function that will be executed by a worker.
type task func()

// goPool represents a pool of workers.
type goPool struct {
    workers    []*worker
    maxWorkers int
    minWorkers int
    workerStack []int
    taskQueue chan task
    lock sync.Locker
    cond *sync.Cond
}

// NewGoPool creates a new pool of workers.
func NewGoPool(maxWorkers int, opts ...Option) *goPool {
    pool := &goPool{
        maxWorkers: maxWorkers,
        minWorkers: maxWorkers, // Set minWorkers to maxWorkers by default
        workers:    make([]*worker, maxWorkers),
        workerStack: make([]int, maxWorkers),
        taskQueue: make(chan task, 1e6),
        lock: new(sync.Mutex),
    }
    for _, opt := range opts {
        opt(pool)
    }
    if pool.cond == nil {
        pool.cond = sync.NewCond(pool.lock)
    }
    for i := 0; i < pool.minWorkers; i++ {
        worker := newWorker()
        pool.workers[i] = worker
        pool.workerStack[i] = i
        worker.start(pool, i)
    }
    go pool.dispatch()
    return pool
}

// AddTask adds a task to the pool.
func (p *goPool) AddTask(t task) {
    p.taskQueue <- t
}

// Release stops all workers and releases resources.
func (p *goPool) Release() {
    close(p.taskQueue)
    p.cond.L.Lock()
    for len(p.workerStack) != p.maxWorkers {
        p.cond.Wait()
    }
    p.cond.L.Unlock()
    for _, worker := range p.workers {
        close(worker.taskQueue)
    }
    p.workers = nil
    p.workerStack = nil
}

func (p *goPool) popWorker() int {
    p.lock.Lock()
    workerIndex := p.workerStack[len(p.workerStack)-1]
    p.workerStack = p.workerStack[:len(p.workerStack)-1]
    p.lock.Unlock()
    return workerIndex
}

func (p *goPool) pushWorker(workerIndex int) {
    p.lock.Lock()
    p.workerStack = append(p.workerStack, workerIndex)
    p.lock.Unlock()
    p.cond.Signal()
}

func (p *goPool) dispatch() {
    for t := range p.taskQueue {
        p.cond.L.Lock()
        for len(p.workerStack) == 0 {
            p.cond.Wait()
        }
        p.cond.L.Unlock()
        workerIndex := p.popWorker()
        p.workers[workerIndex].taskQueue <- t
        if len(p.taskQueue) > (p.maxWorkers-p.minWorkers)/2+p.minWorkers && len(p.workerStack) < p.maxWorkers {
            worker := newWorker()
            p.workers = append(p.workers, worker)
            p.workerStack = append(p.workerStack, len(p.workers)-1)
            worker.start(p, len(p.workers)-1)
        } else if len(p.taskQueue) < p.minWorkers && len(p.workerStack) > p.minWorkers {
            p.workers = p.workers[:len(p.workers)-1]
            p.workerStack = p.workerStack[:len(p.workerStack)-1]
        }
    }
}

Here is the modified worker.go file:

package gopool

// worker represents a worker in the pool.
type worker struct {
    taskQueue chan task
}

func newWorker() *worker {
    return &worker{
        taskQueue: make(chan task, 1),
    }
}

func (w *worker) start(pool *goPool, workerIndex int) {
    go func() {
        for t := range w.taskQueue {
            if t != nil {
                t()
            }
            pool.pushWorker(workerIndex)
        }
    }()
}

Here is the new option.go file:

package gopool

import "sync"

// Option represents an option for the pool.
type Option func(*goPool)

// WithLock sets the lock for the pool.
func WithLock(lock sync.Locker) Option {
    return func(p *goPool) {
        p.lock = lock
        p.cond = sync.NewCond(p.lock)
    }
}

// WithMinWorkers sets the minimum number of workers for the pool.
func WithMinWorkers(minWorkers int) Option {
    return func(p *goPool) {
        p.minWorkers = minWorkers
    }
}

These modifications should meet your requirements.

avatar User

README.md \## Usage

Here is a simple example of how to use GoPool with sync.Mutex:

package main

import (
    "sync"
    "time"

    "github.com/devchat-ai/gopool"
)

func main() {
    pool := gopool.NewGoPool(100)
    for i := 0; i < 1000; i++ {
        pool.AddTask(func() {
            time.Sleep(10 * time.Millisecond)
        })
    }
    pool.Release()
}

And here is how to use GoPool with spinlock.SpinLock:

package main

import (
    "time"

    "github.com/daniel-hutao/spinlock"
    "github.com/devchat-ai/gopool"
)

func main() {
    pool := gopool.NewGoPool(100, gopool.WithLock(new(spinlock.SpinLock)))
    for i := 0; i < 1000; i++ {
        pool.AddTask(func() {
            time.Sleep(10 * time.Millisecond)
        })
    }
    pool.Release()
}

Please add an introduction to Dynamic Worker Adjustment in the README.md file below.

avatar DevChat

Here is the updated README.md file:

Usage

Here is a simple example of how to use GoPool with sync.Mutex:

package main

import (
    "sync"
    "time"

    "github.com/devchat-ai/gopool"
)

func main() {
    pool := gopool.NewGoPool(100)
    for i := 0; i < 1000; i++ {
        pool.AddTask(func() {
            time.Sleep(10 * time.Millisecond)
        })
    }
    pool.Release()
}

And here is how to use GoPool with spinlock.SpinLock:

package main

import (
    "time"

    "github.com/daniel-hutao/spinlock"
    "github.com/devchat-ai/gopool"
)

func main() {
    pool := gopool.NewGoPool(100, gopool.WithLock(new(spinlock.SpinLock)))
    for i := 0; i < 1000; i++ {
        pool.AddTask(func() {
            time.Sleep(10 * time.Millisecond)
        })
    }
    pool.Release()
}

Dynamic Worker Adjustment

GoPool supports dynamic worker adjustment. This means that the number of workers in the pool can increase or decrease based on the number of tasks in the queue. This feature can be enabled by setting the MinWorkers option when creating the pool.

Here is an example of how to use GoPool with dynamic worker adjustment:

package main

import (
    "time"

    "github.com/devchat-ai/gopool"
)

func main() {
    pool := gopool.NewGoPool(100, gopool.WithMinWorkers(50))
    for i := 0; i < 1000; i++ {
        pool.AddTask(func() {
            time.Sleep(10 * time.Millisecond)
        })
    }
    pool.Release()
}

In this example, the pool starts with 50 workers. If the number of tasks in the queue exceeds (MaxWorkers - MinWorkers) / 2 + MinWorkers, the pool will add more workers. If the number of tasks in the queue is less than MinWorkers, the pool will remove some workers.

This version of the README.md file should meet your requirements.