mirror of
https://gitee.com/johng/gf.git
synced 2024-12-02 12:17:53 +08:00
198 lines
5.6 KiB
Go
198 lines
5.6 KiB
Go
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
|
//
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
// If a copy of the MIT was not distributed with this file,
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
package gtimer
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/gogf/gf/v2/container/gtype"
|
|
)
|
|
|
|
func New(options ...TimerOptions) *Timer {
|
|
t := &Timer{
|
|
queue: newPriorityQueue(),
|
|
status: gtype.NewInt(StatusRunning),
|
|
ticks: gtype.NewInt64(),
|
|
}
|
|
if len(options) > 0 {
|
|
t.options = options[0]
|
|
} else {
|
|
t.options = DefaultOptions()
|
|
}
|
|
go t.loop()
|
|
return t
|
|
}
|
|
|
|
// Add adds a timing job to the timer, which runs in interval of `interval`.
|
|
func (t *Timer) Add(ctx context.Context, interval time.Duration, job JobFunc) *Entry {
|
|
return t.createEntry(createEntryInput{
|
|
Ctx: ctx,
|
|
Interval: interval,
|
|
Job: job,
|
|
IsSingleton: false,
|
|
Times: -1,
|
|
Status: StatusReady,
|
|
})
|
|
}
|
|
|
|
// AddEntry adds a timing job to the timer with detailed parameters.
|
|
//
|
|
// The parameter `interval` specifies the running interval of the job.
|
|
//
|
|
// The parameter `singleton` specifies whether the job running in singleton mode.
|
|
// There's only one of the same job is allowed running when it's a singleton mode job.
|
|
//
|
|
// The parameter `times` specifies limit for the job running times, which means the job
|
|
// exits if its run times exceeds the `times`.
|
|
//
|
|
// The parameter `status` specifies the job status when it's firstly added to the timer.
|
|
func (t *Timer) AddEntry(ctx context.Context, interval time.Duration, job JobFunc, isSingleton bool, times int, status int) *Entry {
|
|
return t.createEntry(createEntryInput{
|
|
Ctx: ctx,
|
|
Interval: interval,
|
|
Job: job,
|
|
IsSingleton: isSingleton,
|
|
Times: times,
|
|
Status: status,
|
|
})
|
|
}
|
|
|
|
// AddSingleton is a convenience function for add singleton mode job.
|
|
func (t *Timer) AddSingleton(ctx context.Context, interval time.Duration, job JobFunc) *Entry {
|
|
return t.createEntry(createEntryInput{
|
|
Ctx: ctx,
|
|
Interval: interval,
|
|
Job: job,
|
|
IsSingleton: true,
|
|
Times: -1,
|
|
Status: StatusReady,
|
|
})
|
|
}
|
|
|
|
// AddOnce is a convenience function for adding a job which only runs once and then exits.
|
|
func (t *Timer) AddOnce(ctx context.Context, interval time.Duration, job JobFunc) *Entry {
|
|
return t.createEntry(createEntryInput{
|
|
Ctx: ctx,
|
|
Interval: interval,
|
|
Job: job,
|
|
IsSingleton: true,
|
|
Times: 1,
|
|
Status: StatusReady,
|
|
})
|
|
}
|
|
|
|
// AddTimes is a convenience function for adding a job which is limited running times.
|
|
func (t *Timer) AddTimes(ctx context.Context, interval time.Duration, times int, job JobFunc) *Entry {
|
|
return t.createEntry(createEntryInput{
|
|
Ctx: ctx,
|
|
Interval: interval,
|
|
Job: job,
|
|
IsSingleton: true,
|
|
Times: times,
|
|
Status: StatusReady,
|
|
})
|
|
}
|
|
|
|
// DelayAdd adds a timing job after delay of `interval` duration.
|
|
// Also see Add.
|
|
func (t *Timer) DelayAdd(ctx context.Context, delay time.Duration, interval time.Duration, job JobFunc) {
|
|
t.AddOnce(ctx, delay, func(ctx context.Context) {
|
|
t.Add(ctx, interval, job)
|
|
})
|
|
}
|
|
|
|
// DelayAddEntry adds a timing job after delay of `interval` duration.
|
|
// Also see AddEntry.
|
|
func (t *Timer) DelayAddEntry(ctx context.Context, delay time.Duration, interval time.Duration, job JobFunc, isSingleton bool, times int, status int) {
|
|
t.AddOnce(ctx, delay, func(ctx context.Context) {
|
|
t.AddEntry(ctx, interval, job, isSingleton, times, status)
|
|
})
|
|
}
|
|
|
|
// DelayAddSingleton adds a timing job after delay of `interval` duration.
|
|
// Also see AddSingleton.
|
|
func (t *Timer) DelayAddSingleton(ctx context.Context, delay time.Duration, interval time.Duration, job JobFunc) {
|
|
t.AddOnce(ctx, delay, func(ctx context.Context) {
|
|
t.AddSingleton(ctx, interval, job)
|
|
})
|
|
}
|
|
|
|
// DelayAddOnce adds a timing job after delay of `interval` duration.
|
|
// Also see AddOnce.
|
|
func (t *Timer) DelayAddOnce(ctx context.Context, delay time.Duration, interval time.Duration, job JobFunc) {
|
|
t.AddOnce(ctx, delay, func(ctx context.Context) {
|
|
t.AddOnce(ctx, interval, job)
|
|
})
|
|
}
|
|
|
|
// DelayAddTimes adds a timing job after delay of `interval` duration.
|
|
// Also see AddTimes.
|
|
func (t *Timer) DelayAddTimes(ctx context.Context, delay time.Duration, interval time.Duration, times int, job JobFunc) {
|
|
t.AddOnce(ctx, delay, func(ctx context.Context) {
|
|
t.AddTimes(ctx, interval, times, job)
|
|
})
|
|
}
|
|
|
|
// Start starts the timer.
|
|
func (t *Timer) Start() {
|
|
t.status.Set(StatusRunning)
|
|
}
|
|
|
|
// Stop stops the timer.
|
|
func (t *Timer) Stop() {
|
|
t.status.Set(StatusStopped)
|
|
}
|
|
|
|
// Close closes the timer.
|
|
func (t *Timer) Close() {
|
|
t.status.Set(StatusClosed)
|
|
}
|
|
|
|
type createEntryInput struct {
|
|
Ctx context.Context
|
|
Interval time.Duration
|
|
Job JobFunc
|
|
IsSingleton bool
|
|
Times int
|
|
Status int
|
|
}
|
|
|
|
// createEntry creates and adds a timing job to the timer.
|
|
func (t *Timer) createEntry(in createEntryInput) *Entry {
|
|
var (
|
|
infinite = false
|
|
)
|
|
if in.Times <= 0 {
|
|
infinite = true
|
|
}
|
|
var (
|
|
intervalTicksOfJob = int64(in.Interval / t.options.Interval)
|
|
)
|
|
if intervalTicksOfJob == 0 {
|
|
// If the given interval is lesser than the one of the wheel,
|
|
// then sets it to one tick, which means it will be run in one interval.
|
|
intervalTicksOfJob = 1
|
|
}
|
|
var (
|
|
nextTicks = t.ticks.Val() + intervalTicksOfJob
|
|
entry = &Entry{
|
|
job: in.Job,
|
|
ctx: in.Ctx,
|
|
timer: t,
|
|
ticks: intervalTicksOfJob,
|
|
times: gtype.NewInt(in.Times),
|
|
status: gtype.NewInt(in.Status),
|
|
isSingleton: gtype.NewBool(in.IsSingleton),
|
|
nextTicks: gtype.NewInt64(nextTicks),
|
|
infinite: gtype.NewBool(infinite),
|
|
}
|
|
)
|
|
t.queue.Push(entry, nextTicks)
|
|
return entry
|
|
}
|