You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
active/core/cronus/expiration.go

183 lines
4.0 KiB

// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name rkey.go
// Created by DEV
// Modified 05/02/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package cronus
import (
"sync/atomic"
"time"
)
type (
Expiration struct {
timer *time.Timer
times Chrono
state uint32
source uint32
timeout int64
deadline int64
expireFn func()
}
)
func NewExpiration(duration time.Duration, expirer func()) *Expiration {
ex := &Expiration{
times: *NewChrono(false),
state: uint32(TimerStateCreated),
source: uint32(ExpirationSourceSelf),
timeout: int64(duration),
expireFn: expirer,
}
if duration > 0 {
atomic.StoreUint32(&ex.source,uint32(ExpirationSourceTimer))
}
return ex
}
func (e *Expiration) Reset() {
e.times.Reset()
atomic.StoreUint32(&e.state ,uint32(TimerStateCreated))
atomic.StoreUint32(&e.source,uint32(ExpirationSourceSelf))
atomic.StoreInt64 (&e.timeout ,0)
atomic.StoreInt64 (&e.deadline,0)
if e.timer != nil {
if !e.timer.Stop() {
select {
case <- e.timer.C:
default:
}
}
}
}
func (e *Expiration) State() TimerState {
return TimerState(atomic.LoadUint32(&e.state)) }
func (e *Expiration) Chono() Chronometer {
return &e.times }
func (e *Expiration) Source() ExpirationSource {
return ExpirationSource(atomic.LoadUint32(&e.source)) }
func (e *Expiration) Timeout() time.Duration {
return time.Duration(atomic.LoadInt64(&e.timeout)) }
func (e *Expiration) Deadline() time.Time {
return time.Unix(0,atomic.LoadInt64(&e.deadline)) }
func (e *Expiration) Start(expirer Expirer) error {
if !atomic.CompareAndSwapUint32(&e.state,uint32(TimerStateCreated),uint32(TimerStateStarted)) {
return G.ErrAlreadyStarted
}
st := e.times.Start()
to := time.Duration(atomic.LoadInt64(&e.timeout))
dl := st.Add(to)
if expirer != nil {
pd, ph := expirer.Deadline()
if ph {
if pd.Before(st) {
atomic.StoreUint32(&e.state ,uint32(TimerStateExpired))
atomic.StoreUint32(&e.source,uint32(ExpirationSourceParent))
return G.ErrExpired
}
if pd.Before(dl) {
atomic.StoreInt64 (&e.deadline,pd.UnixNano())
atomic.StoreUint32(&e.source ,uint32(ExpirationSourceParent))
return nil
}
}
}
if atomic.LoadUint32(&e.source) == uint32(ExpirationSourceTimer) {
atomic.StoreInt64 (&e.deadline,dl.UnixNano())
if e.timer == nil {
e.timer = time.NewTimer(to)
} else {
e.timer.Reset(to)
}
go func(ex *Expiration) {
select {
case <-ex.timer.C:
atomic.StoreUint32(&ex.state,uint32(TimerStateExpired))
ex.times.Stop()
if ex.expireFn != nil {
ex.expireFn()
}
return
}
}(e)
}
return nil
}
func (e *Expiration) Stop() error {
if !atomic.CompareAndSwapUint32(&e.state,uint32(TimerStateStarted), uint32(TimerStateStopped)) {
return G.ErrNotStarted
}
e.times.Stop()
if e.timer != nil && !e.timer.Stop() {
select {
case <-e.timer.C:
}
}
return nil
}
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

Powered by TurnKey Linux.