packs2
DEV 3 years ago
parent deb98e9d4e
commit 5f6fca2986

@ -0,0 +1,42 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name completer.go
// Created by DEV
// Modified 20/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 tasks
type (
Completer interface {
Complete (context CompletionContext, cid int)
}
CompleteFnc func (context CompletionContext, cid int)
)
func (f CompleteFnc) Complete (context CompletionContext, cid int) {
f(context,cid) }

@ -0,0 +1,301 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name completion.go
// Created by DEV
// Modified 20/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 tasks
import (
"activething.com/go/gogo/core/opts"
"activething.com/go/gogo/core/timers"
"context"
"sync"
"sync/atomic"
)
type (
Completion struct {
/*embedded*/context.Context
mux sync.RWMutex
wgr sync.WaitGroup
parent CompletionContext
expiration *timers.Expiration
mode CompletionMode
state uint32
pending uint32
cid int
result CompletionResult
dispatchFn dispatchFnc
cancelFn func()
completers []Completer
}
dispatchFnc func (*Completion, Completer, int) error
)
func NewCompletion (options ...opts.OptionErrFnc[Completion]) (*Completion,error) {
c,e := opts.ApplyAndCheck[Completion](&Completion {
mode : CompletionModeAll,
cid : CompletionFromSelf,
dispatchFn: dispatcher,
},options...)
if e != nil {
return nil,e
}
if c.expiration == nil {
c.expiration = timers.NewExpiration(0,nil)
}
return c,nil
}
func (c *Completion) Mode () CompletionMode {
return c.mode }
func (c *Completion) State () CompletionState {
return CompletionState(atomic.LoadUint32(&c.state)) }
func (c *Completion) Pending() int {
return int(atomic.LoadUint32(&c.pending)) }
func (c *Completion) IsCompleted () bool {
return c.State() > CompletionStateStarted }
func (c *Completion) Chrono () timers.Chronometer {
return c.expiration.Chono() }
func (c *Completion) Result () CompletionResult {
c.wgr.Wait()
return c.result
}
func (c *Completion) Wait () {
c.wgr.Wait() }
func (c *Completion) AddCompleter (cms ... Completer) error {
c.mux.Lock()
if c.State() != CompletionStateCreated {
c.mux.Unlock()
return G.ErrInvalidState
}
for _,cm := range cms {
c.completers = append(c.completers, cm)
}
c.mux.Unlock()
return nil
}
func (c *Completion) Cancel () {
c.notify(CompletionFromRequest,CompletionStateCanceled,nil,G.ErrCancelByRequest) }
func (c *Completion) Start (ctx context.Context) error {
return c.complete(ctx,nil,CompletionFromSelf) }
func (c *Completion) Complete (cmp CompletionContext, cid int) {
_ = c.complete(nil,cmp,cid) }
func (c *Completion) complete (ctx context.Context, cctx CompletionContext, cid int) error {
c.mux.Lock()
if c.State() != CompletionStateCreated {
c.mux.Unlock()
return G.ErrInvalidState
}
// Nos sirve para determinar de donde va a depender la expiracion
// en tiempo de la completion en caso de que exista, o bien de la
// completion padre o bien del contexto.
//
var ex timers.Expirer
if cctx != nil {
c.parent = cctx
c.Context= cctx
c.cid = cid
if c.parent.IsCompleted() {
c.mux.Unlock()
c.notify(CompletionFromParent,CompletionStateCanceled,nil,G.ErrCancelByParent)
return G.ErrCancelByParent
}
ex = c.parent
} else {
if ctx == nil {
c.Context = context.Background()
} else {
c.Context = ctx
if ctx.Err() != nil {
c.mux.Unlock()
c.notify(CompletionFromContext,CompletionStateCanceled,nil,G.ErrCancelByContext)
return G.ErrCancelByContext.WithCause(ctx.Err())
}
ch := make(chan struct{})
c.cancelFn = func(){ close(ch)}
go func(cc *Completion, ch chan struct{}){
select {
case <- ch:
case <- cc.Context.Done() :
er := G.ErrCancelByContext.WithCause(cc.Context.Err())
cc.notify(CompletionFromContext,CompletionStateCanceled,nil,er)
}
}(c,ch)
}
ex = ctx
}
if er := c.expiration.Start(ex); er != nil {
c.mux.Unlock()
c.notify(CompletionFromSelf,CompletionStateFaulted,nil,er)
return er
}
atomic.StoreUint32(&c.state,uint32(CompletionStateStarted))
c.wgr.Add(1)
go func (c *Completion) {
ln := len(c.completers)
if ln == 0 {
c.mux.Unlock()
c.notify(CompletionFromSelf, CompletionStateCompleted, nil, nil)
return
}
atomic.StoreUint32(&c.pending,uint32(ln))
cs := c.completers
c.mux.Unlock()
for ix, cm := range cs {
if c.IsCompleted() {
return
}
if er := c.dispatchFn(c,cm,ix); er != nil {
c.notify(CompletionFromSelf,CompletionStateFaulted,nil,er)
return
}
}
}(c)
return nil
}
func (c *Completion) Notify (frm int, val interface{}, err error) {
c.notify(frm,CompletionStateCompleted,val,err) }
func (c *Completion) notify (frm int, ste CompletionState, val interface{}, err error) {
c.mux.Lock()
os := c.State()
if os > CompletionStateStarted {
c.mux.Unlock()
return
}
if frm >= CompletionFromChild {
cn := atomic.AddUint32(&c.pending,-1)
switch {
case c.mode.IsAnyOrResult() && val != nil:
atomic.StoreUint32(&c.state,uint32(CompletionStateCompleted))
c.result = NewCompletionResultValue(frm, val)
case c.mode.IsAnyOrError() && err != nil:
atomic.StoreUint32(&c.state,uint32(CompletionStateFaulted))
c.result = NewCompletionResultError(frm, err)
case c.mode == completionModeTask:
c.result = NewCompletionResult(frm, val, err)
default:
if c.mode == CompletionModeAll {
if c.result == nil {
c.result = NewCompletionResultList(c.cid, NewCompletionResult(frm, val, err))
} else {
c.result.(*CompletionResultList).Add(NewCompletionResult(frm, val, err))
}
}
if cn == 0 {
atomic.StoreUint32(&c.state,uint32(CompletionStateCompleted))
} else {
c.mux.Unlock()
return
}
}
} else {
atomic.StoreUint32(&c.state,uint32(ste))
c.result = NewCompletionResult(frm,val,err)
}
_ = c.expiration.Stop()
if c.cancelFn != nil {
c.cancelFn()
}
c.wgr.Done()
c.mux.Unlock()
// Solo notificamos a las completions hijas y al padre en caso de que se haya iniciado
if os == CompletionStateStarted {
for _, ch := range c.completers {
// Notificamos solo a los completer que a su vez implementan
// CompletionContext
if cm, is := ch.(CompletionContext); is {
if !cm.IsCompleted() {
cm.Notify(CompletionFromParent, nil, G.ErrCancelByParent)
}
}
}
// Notificamos al padre en caso de que tenga y la completion no venga de el
if frm != CompletionFromParent && c.parent != nil {
c.parent.Notify(c.cid,c.result.Value(),c.result.Error())
}
}
}
func dispatcher (completion *Completion, completer Completer, cid int) error {
go completer.Complete(completion,cid)
return nil
}

@ -0,0 +1,39 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name completion_context.go
// Created by DEV
// Modified 20/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 tasks
import "context"
type (
CompletionContext interface {
context.Context
IsCompleted () bool
Notify (cid int, val interface {}, err error)
}
)

@ -0,0 +1,90 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name completion_mode.go
// Created by DEV
// Modified 20/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 tasks
const(
CompletionModeAll CompletionMode = iota
// CompletionModeAny Las tareas se ejecutaran haste que se
//produzca el primer resultado o el primer error
CompletionModeAny
//CompletionModeResult Las tareas se ejecutaran hasta que
//se obtenga el primer resultado.
CompletionModeResult
//CompletionModeError Las tareas se completaran en el momento de
//que se produzca un error.
CompletionModeError
//CompletionModeTask Modo para las completions de una sola task
completionModeTask
)
type (
CompletionMode uint8
)
func (m CompletionMode) IsAnyOrResult () bool {
return m == CompletionModeResult || m == CompletionModeAny }
func (m CompletionMode) IsAnyOrError () bool {
return m == CompletionModeError || m == CompletionModeAny }
func (m CompletionMode) String () string {
switch m {
case CompletionModeAll : return "all"
case CompletionModeAny : return "any"
case CompletionModeResult: return "result"
case CompletionModeError : return "error"
case completionModeTask : return "task"
default:
return "??"
}
}
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,91 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name completion_ops.go
// Created by DEV
// Modified 21/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 tasks
import (
"activething.com/go/gogo/core/opts"
"activething.com/go/gogog/core/timers"
"time"
)
// CompletionWithMode
// Desc: Función para el constructor de Completion,
// establece el mode de como se llegara a la completion
//
func CompletionWithMode (mode CompletionMode) opts.OptionErrFnc[Completion] {
return func(c *Completion) error {
c.mode = mode
return nil
}
}
// CompletionWithTimeout
// Desc: Función para el constructor de Completion
// Establece el tiempo máximo de la completion
//
func CompletionWithTimeout (tmo time.Duration) opts.OptionErrFnc[Completion] {
return func(c *Completion) error {
c.expiration = timers.NewExpiration(tmo,func(){
c.notify(CompletionFromTimer,CompletionStateCanceled,nil,G.ErrCancelByTimer)
})
return nil
}
}
// CompletionWithCompleters
// Desc: Función para el constructor de Completion,
// añade los objeto a completar en la completion
//
func CompletionWithCompleters (completers ... Completer) opts.OptionErrFnc[Completion] {
return func(c *Completion) error {
if c.State() != CompletionStateCreated {
return G.ErrInvalidState
}
for _, cm := range completers {
c.completers = append(c.completers, cm)
}
return nil
}
}
// CompletionWithWorkPool
// Desc: Función para el constructor de Completion,
// utiliza un pool de trabajo para completar
// las tareas.
//
func CompletionWithWorkPool (pool *WorkerPool) opts.OptionErrFnc[Completion] {
return func(c *Completion) error {
c.dispatchFn = dispatchFnc(func (cm *Completion, cr Completer, ci int) error {
return pool.DoWork(c,func(){
cr.Complete(cm,ci)
})
})
return nil
}
}

@ -0,0 +1,51 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name completion_result.go
// Created by DEV
// Modified 20/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 tasks
type (
CompletionResult interface {
CID () int
Value() any
Error() error
Kind () CompletionResultKind
}
)
func NewCompletionResult (cid int, val any, err error) CompletionResult {
if err != nil {
return *NewCompletionResultError(cid,err)
}
if val != nil {
return *NewCompletionResultValue(cid,val)
}
return CompletionResultVoid(cid)
}

@ -0,0 +1,73 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name completion_result_error.go
// Created by DEV
// Modified 20/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 tasks
type (
CompletionResultError struct {
cid int
err error
}
)
func NewCompletionResultError (cid int, err error) *CompletionResultError {
return &CompletionResultError{
cid : cid,
err : err,
}
}
func (r CompletionResultError) CID () int {
return r.cid }
func (_ CompletionResultError) Kind () CompletionResultKind {
return CompletionResultKindError }
func (_ CompletionResultError) Value () any {
return nil }
func (r CompletionResultError) Error () error {
return r.err }
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,83 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name completion_result_kind.go
// Created by DEV
// Modified 20/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 tasks
const(
CompletionResultKindVoid CompletionResultKind = iota
CompletionResultKindError
CompletionResultKindValue
CompletionResultKindList
)
type (
CompletionResultKind uint8
)
func (k CompletionResultKind) IsVoid () bool {
return k == CompletionResultKindVoid }
func (k CompletionResultKind) IsError() bool {
return k == CompletionResultKindError}
func (k CompletionResultKind) IsValue() bool {
return k == CompletionResultKindValue}
func (k CompletionResultKind) IsList () bool {
return k == CompletionResultKindList }
func (k CompletionResultKind) String () string {
switch k {
case CompletionResultKindVoid : return "void"
case CompletionResultKindValue: return "value"
case CompletionResultKindError: return "error"
case CompletionResultKindList : return "list"
default:
return "??"
}
}
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,87 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name completion_result_list.go
// Created by DEV
// Modified 20/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 tasks
type (
CompletionResultList struct {
cid int
results []CompletionResult
}
)
func NewCompletionResultList (cid int, results ... CompletionResult) *CompletionResultList {
ls := make([]CompletionResult,len(results))
copy(ls, results)
return &CompletionResultList{
cid: cid,
results: ls,
}
}
func (r *CompletionResultList) Add (rsl CompletionResult) {
if rsl != nil {
r.results = append(r.results, rsl)
}
}
func (r CompletionResultList) CID () int {
return r.cid }
func (_ CompletionResultList) Kind () CompletionResultKind {
return CompletionResultKindList }
func (_ CompletionResultList) Error () error {
return nil }
func (r CompletionResultList) Value () any {
return r.results }
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,73 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name completion_result_value.go
// Created by DEV
// Modified 20/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 tasks
type (
CompletionResultValue struct {
cid int
value any
}
)
func NewCompletionResultValue (cid int, value any) *CompletionResultValue {
return &CompletionResultValue{
cid : cid,
value: value,
}
}
func (r CompletionResultValue) CID () int {
return r.cid }
func (_ CompletionResultValue) Kind () CompletionResultKind {
return CompletionResultKindValue }
func (_ CompletionResultValue) Error () error {
return nil }
func (r CompletionResultValue) Value () any {
return r.value }
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,69 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name completion_result_void.go
// Created by DEV
// Modified 20/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 tasks
type (
CompletionResultVoid int
)
func (r CompletionResultVoid) CID () int {
return int(r)
}
func (_ CompletionResultVoid) Kind () CompletionResultKind {
return CompletionResultKindVoid }
func (_ CompletionResultVoid) Value () any {
return nil }
func (_ CompletionResultVoid) Error () error {
return nil }
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,58 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name completion_state.go
// Created by DEV
// Modified 20/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 tasks
const (
CompletionStateCreated CompletionState = iota
CompletionStateStarted
CompletionStateCompleted
CompletionStateCanceled
CompletionStateFaulted
)
type (
CompletionState uint32
)
func (s CompletionState) String () string {
switch s {
case CompletionStateCreated : return "created"
case CompletionStateStarted : return "started"
case CompletionStateCompleted: return "completed"
case CompletionStateCanceled : return "canceled"
case CompletionStateFaulted : return "faulted"
default: return "??"
}
}

@ -23,4 +23,48 @@
package tasks package tasks
import "activething.com/go/gogo/core/errs"
const (
CompletionFromChild int = 0
CompletionFromSelf int = -1
CompletionFromParent int = -2
CompletionFromContext int = -3
CompletionFromTimer int = -4
CompletionFromRequest int = -5
)
var (
G = struct {
ErrInvalidCompletion errs.ErrCode
ErrInvalidState errs.ErrCode
ErrCancelByParent errs.ErrCode
ErrCancelByRequest errs.ErrCode
ErrCancelByContext errs.ErrCode
ErrCancelByTimer errs.ErrCode
ErrPoolStarted errs.ErrCode
ErrPoolStopped errs.ErrCode
ErrPoolAcquire errs.ErrCode
}{
ErrInvalidCompletion: errs.ErrCode("syncs:tasks.invalid-completion"),
ErrInvalidState : errs.ErrCode("syncs:tasks.invalid-state"),
ErrCancelByParent : errs.ErrCode("syncs:tasks.cancel-by-parent"),
ErrCancelByRequest : errs.ErrCode("syncs:tasks.cancel-by-request"),
ErrCancelByContext : errs.ErrCode("syncs:tasks.cancel-by-context"),
ErrCancelByTimer : errs.ErrCode("syncs:tasks.cancel-by-timer"),
ErrPoolStarted : errs.ErrCode("syncs:tasks.pool-started"),
ErrPoolStopped : errs.ErrCode("syncs:tasks.pool-stopped"),
ErrPoolAcquire : errs.ErrCode("syncs:tasks.pool-acquire"),
}
)

@ -26,6 +26,7 @@ package tasks
import ( import (
"activething.com/go/gogo/core/opts" "activething.com/go/gogo/core/opts"
"activething.com/go/gogo/core/syncs" "activething.com/go/gogo/core/syncs"
"context"
"runtime" "runtime"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -91,8 +92,7 @@ func (p *WorkerPool) Stats () syncs.PoolStats {
func (p *WorkerPool) State () WorkerPoolState { func (p *WorkerPool) State () WorkerPoolState {
return WorkerPoolState(atomic.LoadUint32(&p.state)) return WorkerPoolState(atomic.LoadUint32(&p.state)) }
}
func (p *WorkerPool) Count () int32 { func (p *WorkerPool) Count () int32 {
return atomic.LoadInt32(&p.count) } return atomic.LoadInt32(&p.count) }
@ -141,11 +141,148 @@ func (p *WorkerPool) Done () <- chan struct{} {
func (p *WorkerPool) Start () error { func (p *WorkerPool) Start () error {
p.mux.Lock() p.mux.Lock()
st := WorkerPoolState(atomic.LoadUint32(&p.state))
st := p.State()
if st == WorkerPoolStateRunning { if st == WorkerPoolStateRunning {
p.mux.Unlock() p.mux.Unlock()
return G.ErrPoolStarted
}
if st == WorkerPoolStateStopped {
atomic.StoreInt32(&p.count,0)
}
p.doneCh = make(chan struct{})
p.mux.Unlock()
go func(p *WorkerPool) {
atomic.StoreUint32(&p.state,uint32(WorkerPoolStateRunning))
var ls []*worker
for {
p.clearWorkers(&ls)
select {
case <- p.doneCh:
return return
default:
time.Sleep(time.Duration(atomic.LoadInt64(&p.maxIdle)))
} }
}
}(p)
return nil
} }
func (p *WorkerPool) Stop () error {
p.mux.Lock()
if p.State() != WorkerPoolStateRunning {
p.mux.Unlock()
return G.ErrPoolStopped
}
atomic.StoreUint32(&p.state,uint32(WorkerPoolStateStopped))
close(p.doneCh)
p.doneCh = nil
ws := p.workers
for ix,wk := range ws {
wk.jobCh <- nil
ws[ix]=nil
}
p.workers = ws[:0]
p.mux.Unlock()
return nil
}
func (p *WorkerPool) DoWork(ctx context.Context, job func()) error {
p.mux.Lock()
if p.State() != WorkerPoolStateRunning {
p.mux.Unlock()
return G.ErrPoolStopped
}
wk := (*worker)(nil)
ws := p.workers
ln := len(ws) - 1
if ln >= 0 {
wk = ws[ln]
ws[ln] = nil
p.workers = ws[:ln]
p.mux.Unlock()
} else {
p.mux.Unlock()
if atomic.LoadInt32(&p.count) >= atomic.LoadInt32(&p.max) {
return G.ErrPoolAcquire
}
atomic.AddInt32(&p.count,1)
wk = p.pool.Get().(*worker)
go func(p *WorkerPool, w *worker, x context.Context) {
for job := range w.jobCh {
if job == nil {
break
}
job()
job = nil
p.mux.Lock()
done := false
if p.State() != WorkerPoolStateStopped {
w.lastTime = time.Now()
p.workers = append(p.workers, w)
done = true
p.stats.AddReleased()
}
p.mux.Unlock()
if !done {
break
}
}
atomic.AddInt32(&p.count,-1)
p.pool.Put(w)
}(p,wk,ctx)
}
p.stats.AddAcquired()
wk.jobCh <- job
return nil
}
func (p *WorkerPool) clearWorkers (cls *[]*worker) {
p.mux.Lock()
tm := time.Now()
mi := time.Duration(atomic.LoadInt64(&p.maxIdle))
ws := p.workers
ln := len(ws)
ix := 0
for ix <ln && tm.Sub(ws[ix].lastTime) > mi {
ix++
}
*cls = append((*cls)[:0],ws[:ix]...)
if ix > 0 {
nt := copy(ws,ws[ix:])
for ix:= nt; ix<ln; ix++ {
ws[ix]=nil
}
p.workers=ws[:nt]
}
p.mux.Unlock()
cl := *cls
for ix,wk := range cl {
wk.jobCh <- nil
cl[ix]=nil
}
}

@ -21,7 +21,7 @@
// limitations under the License. // limitations under the License.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
package times package timers
import ( import (
"sync/atomic" "sync/atomic"

@ -22,7 +22,7 @@
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
package times package timers
import ( import (
"time" "time"

@ -21,7 +21,7 @@
// limitations under the License. // limitations under the License.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
package times package timers
import ( import (
"sync/atomic" "sync/atomic"

@ -21,7 +21,7 @@
// limitations under the License. // limitations under the License.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
package times package timers
const ( const (

@ -21,7 +21,7 @@
// limitations under the License. // limitations under the License.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
package times package timers
import ( import (
"time" "time"

@ -0,0 +1,4 @@
module activething.com/go/gogo/core/timers
go 1.20

@ -0,0 +1,71 @@
// ------------------------------------------------------------------------
// 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 timers
import (
"activething.com/go/gogo/core/errs"
)
var (
G = struct {
ErrExpired errs.ErrCode
ErrTimeout errs.ErrCode
ErrIntervalInvalid errs.ErrCode
ErrNotStarted errs.ErrCode
ErrNotPaused errs.ErrCode
ErrAlreadyStarted errs.ErrCode
ErrTransitionInvalid errs.ErrCode
ErrTimerTaskInvalid errs.ErrCode
} {
ErrExpired: errs.ErrCode("expired"),
ErrTimeout: errs.ErrCode("timeout"),
ErrIntervalInvalid: errs.ErrCode("interval_invalid"),
ErrNotStarted: errs.ErrCode("not_started"),
ErrNotPaused: errs.ErrCode("not_paused"),
ErrAlreadyStarted: errs.ErrCode("already_started"),
ErrTransitionInvalid:errs.ErrCode("transition_invalid"),
ErrTimerTaskInvalid: errs.ErrCode("timer_task_invalid"),
}
)
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -21,7 +21,7 @@
// limitations under the License. // limitations under the License.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
package times package timers
import ( import (
"activething.com/go/gogo/core/contexts" "activething.com/go/gogo/core/contexts"

@ -21,7 +21,7 @@
// limitations under the License. // limitations under the License.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
package times package timers
import ( import (
"context" "context"

@ -21,7 +21,7 @@
// limitations under the License. // limitations under the License.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
package times package timers
import ( import (
"activething.com/go/gogo/core/opts" "activething.com/go/gogo/core/opts"

@ -21,7 +21,7 @@
// limitations under the License. // limitations under the License.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
package times package timers
const ( const (

@ -22,7 +22,7 @@
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
package times package timers
import ( import (
"time" "time"

@ -21,7 +21,7 @@
// limitations under the License. // limitations under the License.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
package times package timers
type ( type (

@ -0,0 +1,33 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name bmonth.go
// Created by DEV
// Modified 21/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 bdates
type (
BMonth uint32
)

@ -0,0 +1,125 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name bweek.go
// Created by DEV
// Modified 21/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 bdates
import "math/bits"
const(
BWeekDaysMon BWeekDays = 1 << iota
BWeekDaysTue
BWeekDaysWed
BWeekDaysThu
BWeekDaysFri
BWeekDaysSat
BWeekDaysSun
_BWeekFlag
BWeekDaysAll = 0x1111111
)
type (
// BWeekDays
// Type: uint8
// Desc: Representa una lista de los dias de la semana
// a través de un byte
BWeekDays uint8
)
func (w BWeekDays) GetFlag() bool {
return w&_BWeekFlag==_BWeekFlag }
func (w BWeekDays) SetFlag(val bool) BWeekDays {
if val {
return w|_BWeekFlag
}
return w&^_BWeekFlag
}
func (w BWeekDays) SetDay (num int, val bool) BWeekDays {
if num < 0 || num > 7 {
return w
}
if val {
w |= 1 << num-1
} else {
w &^= 1 << num-1
}
return w
}
func (w BWeekDays) GetDay (num int) bool {
if num < 0 || num > 7 {
return false
}
c := BWeekDays(1 << num-1)
return (w&c)==c
}
func (w BWeekDays) Invert () BWeekDays {
return ^w }
func (w BWeekDays) Count () int {
return bits.OnesCount8(uint8(w)) }
func (w BWeekDays) List () []int {
c := BWeekDays(1)
r := make([]int,0,7)
for i:=1; i<=7; i++ {
if c&w == c {
r = append(r,i)
}
c <<=1
}
return r
}
func (w BWeekDays) ToSlice () []bool {
c := BWeekDays(1)
r := make([]bool,7)
for i:=0; i<7; i++ {
r[i]=c&w == c
c <<=1
}
return r
}
func (w BWeekDays) Common (dst BWeekDays) BWeekDays { return w & dst }

@ -0,0 +1,31 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name byear.go
// Created by DEV
// Modified 21/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 bdates
type (
BYear [12]BMonth
)

@ -0,0 +1,102 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name days.go
// Created by DEV
// Modified 21/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 times
import "time"
type (
DateDays int32
)
func (d DateDays) AddDate(years, months, days int) DateDays {
return TimeToDays(d.ToTime().AddDate(years,months,days)) }
func (d DateDays) ToTime() time.Time {
return DaysToTime(d) }
func (d DateDays) Before (days DateDays) bool {
return d < days }
func (d DateDays) After (days DateDays) bool {
return d > days }
func (d DateDays) Compare(days DateDays) int {
if d < days {
return -1 }
if d == days {
return 0 }
return 1
}
func (d DateDays) Min (days DateDays) DateDays {
if d > days {
return days
}
return d
}
func (d DateDays) Max (days DateDays) DateDays {
if d < days {
return days
}
return d
}
func TimeToDays (time time.Time) DateDays {
_,x := time.Zone()
s := time.Unix() + int64(x)
if s >= 0 {
return DateDays(s/ secondsDay) }
return -DateDays((secondsDay -1 -s)/ secondsDay)
}
func DaysToTime(days DateDays) time.Time {
return time.Unix(int64(days) *secondsDay,0).UTC() }
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -0,0 +1,92 @@
// ------------------------------------------------------------------------
// Project atila
// Active Thing (activething.com) git.activething.com/go
//
// File name date_days_range.go
// Created by DEV
// Modified 21/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 times
import "activething.com/go/gogo/core/opts"
type (
DateDaysRange struct {
Start DateDays
End DateDays
}
)
func NewDateRange (options ...opts.OptionFnc[DateDaysRange]) *DateDaysRange {
return opts.Apply[DateDaysRange](&DateDaysRange{
//
},options...)}
func (r DateDaysRange) IsZero () bool {
return r.End-r.Start <= 0 }
func (r DateDaysRange) Size () DateDays {
return DateDays(r.End -r.Start) }
func (r DateDaysRange) Contains (days DateDays) bool {
if r.IsZero() {
return false }
return r.Start < days && r.End > days
}
func (r DateDaysRange) ContainsRange (drange DateDaysRange) bool {
if r.IsZero() {
return false }
return r.Start > drange.Start && r.End < drange.End
}
func (r DateDaysRange) IsRangeOverlap (drange DateDaysRange) bool {
if r.IsZero() {
return false }
if r.Start == drange.Start || r.Start == drange.End || r.End == drange.End {
return true }
if r.Start > drange.Start {
return drange.End < r.End
}
return r.End > drange.Start
}
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*/

@ -43,7 +43,9 @@ type (
) )
func (f FormatDurationFnc) FormatDuration (dur time.Duration, dst []byte) []byte { return f(dur,dst) } func (f FormatDurationFnc) FormatDuration (dur time.Duration, dst []byte) []byte {
return f(dur,dst) }
func WrapDurationFormatterQuoted (dfm DurationFormatter, qte byte) DurationFormatter { func WrapDurationFormatterQuoted (dfm DurationFormatter, qte byte) DurationFormatter {
return FormatDurationFnc(func(tme time.Duration, dst []byte) []byte { return FormatDurationFnc(func(tme time.Duration, dst []byte) []byte {
@ -55,8 +57,7 @@ func WrapDurationFormatterQuoted (dfm DurationFormatter, qte byte) DurationForma
func DurationMillis (dur time.Duration, dst []byte) []byte { func DurationMillis (dur time.Duration, dst []byte) []byte {
return strconv.AppendFloat(dst, float64(dur)/float64(time.Millisecond), 'f', -1, 64) return strconv.AppendFloat(dst, float64(dur)/float64(time.Millisecond), 'f', -1, 64) }
}

@ -1,4 +1,5 @@
module activething.com/go/gogog/core/times module activething.com/go/gogo/core/times
go 1.20 go 1.20

@ -2,9 +2,9 @@
// Project atila // Project atila
// Active Thing (activething.com) git.activething.com/go // Active Thing (activething.com) git.activething.com/go
// //
// File name rkey.go // File name gogo.go
// Created by DEV // Created by DEV
// Modified 05/02/2024 // Modified 21/02/2024
// //
// Copyright 2024 activething.com // Copyright 2024 activething.com
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -23,49 +23,49 @@
package times package times
import ( import "activething.com/go/gogo/core/errs"
"activething.com/go/gogo/core/errs"
)
const(
var ( secondsDay = 24 * 60 * 60
)
var (
G = struct { G = struct {
ErrExpired errs.ErrCode
ErrTimeout errs.ErrCode
ErrIntervalInvalid errs.ErrCode
ErrNotStarted errs.ErrCode
ErrNotPaused errs.ErrCode
ErrAlreadyStarted errs.ErrCode
ErrTransitionInvalid errs.ErrCode
ErrTimerTaskInvalid errs.ErrCode
} {
ErrExpired: errs.ErrCode("expired"),
ErrTimeout: errs.ErrCode("timeout"),
ErrIntervalInvalid: errs.ErrCode("interval_invalid"),
ErrNotStarted: errs.ErrCode("not_started"),
ErrNotPaused: errs.ErrCode("not_paused"),
ErrAlreadyStarted: errs.ErrCode("already_started"),
ErrTransitionInvalid:errs.ErrCode("transition_invalid"),
ErrTimerTaskInvalid: errs.ErrCode("timer_task_invalid"),
}
ErrInvalidDateRange errs.ErrCode
}{
ErrInvalidDateRange : errs.ErrCode("core:times.invalid-date-range"),
}
) )
/*
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
I HAVE NO DESIRE TO WALK ON WATER," SAID SIDDHARTA.
"LET THE OLD SHRAMANAS SATISFY THEMSELVES WITH SUCH SKILLS.
SIDDHARTA
- HERMANN HESSE -
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: func IsYearLeap (year int) bool {
return year%4 == 0 && (year%100 != 0 || year%400 == 0) }
func DaysInYear (year int) int {
if IsYearLeap(year) {
return 366 }
return 365
}
func DaysIn (year, month int) int {
if month <= 0 || month > 12 {
return 0 }
d := [12]int{ 31,28,31,30,31,30,31,30,31,30,31 }
if month == 2 && IsYearLeap(year) {
return 29 }
return d[month]
}
*/

@ -43,7 +43,8 @@ type (
) )
func (f FormatTimeFnc) FormatTime (tme time.Time, dst []byte) []byte { return f(tme,dst) } func (f FormatTimeFnc) FormatTime (tme time.Time, dst []byte) []byte {
return f(tme,dst) }
@ -58,28 +59,23 @@ func WrapTimeFormatterQuoted (tmf TimeFormatter, qte byte) TimeFormatter {
func TimeRFC3339Nano(tme time.Time, dst []byte) []byte { func TimeRFC3339Nano(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.RFC3339Nano) return tme.AppendFormat(dst, time.RFC3339Nano) }
}
func TimeANSIC(tme time.Time, dst []byte) []byte { func TimeANSIC(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.ANSIC) return tme.AppendFormat(dst, time.ANSIC) }
}
func TimeUnixDate(tme time.Time, dst []byte) []byte { func TimeUnixDate(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.UnixDate) return tme.AppendFormat(dst, time.UnixDate) }
}
func TimeRubyDate(tme time.Time, dst []byte) []byte { func TimeRubyDate(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.RubyDate) return tme.AppendFormat(dst, time.RubyDate) }
}
func TimeRFC822(tme time.Time, dst []byte) []byte { func TimeRFC822(tme time.Time, dst []byte) []byte {
return tme.AppendFormat(dst, time.RFC822) return tme.AppendFormat(dst, time.RFC822) }
}
func TimeRFC822Z(tme time.Time, dst []byte) []byte { func TimeRFC822Z(tme time.Time, dst []byte) []byte {

@ -12,6 +12,7 @@ use (
./core/syncs ./core/syncs
./core/results ./core/results
./core/times ./core/times
./core/timers
./core/crypts ./core/crypts
./core/values ./core/values

Loading…
Cancel
Save

Powered by TurnKey Linux.