delayed

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 27, 2018 License: MIT Imports: 5 Imported by: 0

README

Delayed Methods

usage


fn := delayed.Call(500 * time.Millisecond, func() {
  fmt.Prinln("hello, world.")
})


fn.Reset(100 * time.Millisecond, func() {
  fmt.Prinln("hello, world. This should execute")
})

Cancel a delayed function

fn.Cancel() cancels the delayed execution and return true or false to indicate if cancel was required/happened.

Reset delay and func

fn.Reset(newDelay, func(){...}) cancels the delayed execution and starts a new one with the new delay and the new func

Reset delay

fn.ResetDelay(newDelay) cancels the delayed execution and starts a new one with the new delay.

Reset Func

fn.ResetFunc(func(){ ... }) cancels the delayed execution and starts a new one to execute the new func

Hacks

Enabled debug logs

use -tags debug to enable debug logs e.g. go test -race -tags debug -run Example

Documentation

Overview

Example (Idler)
package main

import (
	"sync"
	"time"

	"github.com/sthaha/delayed"
	"github.com/sthaha/delayed/testutils"
)

type idlerstat int

const (
	running idlerstat = 0
	idled   idlerstat = 1
)

var stat = running

func status() idlerstat {
	return stat
}

var unidleRequested = false

var fn delayed.Fn

func unidle() {
	info := testutils.Logger("unidle")

	info("-------------------------------")
	if unidleRequested {
		info("Already scheduled to unidle, ignoring this call")
		return
	}

	unidleRequested = true

	info("unidle: going to delayed unidle")

	fn.Reset(3*time.Second, func() {
		info("unidle: unidling ...")
		if status() == running {
			info("unidle: No need to idle since it is already unidled")
			return
		}
		stat = running
		unidleRequested = false
	})
}

func idle() {
	info := testutils.Logger("idle")

	info("-------------------------------")
	if unidleRequested {
		info("Ignoring Idle request since unidle has been requested earlier")
		return
	}

	info("going to delayed idle")

	fn.Reset(3*time.Second, func() {

		if status() == idled {
			info("No need to idle since it is already idled")
			return
		}
		info("idling ... - START")
		time.Sleep(500 * time.Millisecond)
		info("idling ... - DONE")
		stat = idled
	})
}

func simulateIdler(wg *sync.WaitGroup) {
	defer wg.Done()

	idle()
	time.Sleep(200 * time.Millisecond)
	idle()
	time.Sleep(200 * time.Millisecond)
	unidle()
	time.Sleep(200 * time.Millisecond)
	idle()
	time.Sleep(200 * time.Millisecond)
	unidle()
	time.Sleep(5 * time.Second)
	idle()
}

func main() {
	info := testutils.Logger("main")
	wg := &sync.WaitGroup{}

	wg.Add(1)
	info("starting test run")
	simulateIdler(wg)
	wg.Wait()
	info("done")
	// HACK: output below is used as hack to run the test
	// run this using go test -race -run Example

}
Output:

Example (Long_running_fn)
package main

import (
	"fmt"
	"sync/atomic"
	"time"

	"github.com/sthaha/delayed"
	"github.com/sthaha/delayed/testutils"
)

func main() {
	//
	debug := testutils.Logger("main")

	var count uint64

	fn, _ := delayed.Call(100*time.Millisecond, func() {
		debug := testutils.Logger("first")

		debug("going to execute")
		atomic.AddUint64(&count, 1)
		// simulate some activity while a Reset could be called from
		// else where in the code
		time.Sleep(500 * time.Millisecond)

		debug("execute done")
	})

	// give enough time for the call to run
	time.Sleep(110 * time.Millisecond)
	debug("going to schedule another")

	fn.Reset(100*time.Millisecond, func() {
		debug := testutils.Logger("second")

		debug("going to execute")
		atomic.AddUint64(&count, 1)

		time.Sleep(200 * time.Millisecond)
		debug("execute done")
	})

	time.Sleep(110 * time.Millisecond)

	called := atomic.LoadUint64(&count)
	fmt.Printf("not mutex protected thus count is %d\n", called)

	// wait for both to finish
	time.Sleep(800 * time.Millisecond)

	called = atomic.LoadUint64(&count)
	fmt.Printf("expect calls to be %d\n", called)

}
Output:

not mutex protected thus count is 2
expect calls to be 2
Example (Long_running_fn_fixed)
package main

import (
	"fmt"
	"sync"
	"sync/atomic"
	"time"

	"github.com/sthaha/delayed"
	"github.com/sthaha/delayed/testutils"
)

func main() {
	debug := testutils.Logger("main")

	var count uint64

	var m sync.Mutex

	fn, _ := delayed.Call(100*time.Millisecond, func() {
		m.Lock()
		defer m.Unlock()

		debug := testutils.Logger("first")

		debug("going to execute")
		atomic.AddUint64(&count, 1)
		// simulate some activity while a Reset could be called from
		// else where in the code
		time.Sleep(500 * time.Millisecond)

		debug("execute done")
	})

	// give enough time for the call to run
	time.Sleep(110 * time.Millisecond)
	debug("going to schedule another")

	fn.Reset(100*time.Millisecond, func() {
		m.Lock()
		defer m.Unlock()
		debug := testutils.Logger("second")

		debug("going to execute")
		atomic.AddUint64(&count, 1)

		time.Sleep(200 * time.Millisecond)
		debug("execute done")
	})

	time.Sleep(110 * time.Millisecond)

	called := atomic.LoadUint64(&count)
	fmt.Printf("mutex protected thus count is %d\n", called)

	// wait for both to finish
	time.Sleep(800 * time.Millisecond)

	called = atomic.LoadUint64(&count)
	fmt.Printf("expect calls to be %d\n", called)
	time.Sleep(800 * time.Millisecond)

}
Output:

mutex protected thus count is 1
expect calls to be 2

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Callable added in v0.3.0

type Callable interface {
	Call() error
	Cancel() bool
	Reset(time.Duration, func()) error
	ResetDelay(time.Duration) error
	ResetFunc(func()) error
}

Callable is the interface a delayed function call must satisfy

type FakeFn added in v0.3.0

type FakeFn struct {
	Clock clockwork.FakeClock
	// contains filtered or unexported fields
}

FakeFn satisfies a Callable where the clock can be controlled/mocked

func FakeCall added in v0.3.0

func FakeCall(d time.Duration, fn func()) *FakeFn

func NewFakeFn added in v0.3.0

func NewFakeFn(d time.Duration, fn func()) *FakeFn

func (*FakeFn) Call added in v0.3.0

func (m *FakeFn) Call() error

func (*FakeFn) Cancel added in v0.3.0

func (m *FakeFn) Cancel() bool

func (*FakeFn) Reset added in v0.3.0

func (m *FakeFn) Reset(d time.Duration, fn func()) error

func (*FakeFn) ResetDelay added in v0.3.0

func (m *FakeFn) ResetDelay(d time.Duration) error

func (*FakeFn) ResetFunc added in v0.3.0

func (m *FakeFn) ResetFunc(fn func()) error

type Fn

type Fn struct {
	// contains filtered or unexported fields
}

Fn represents a fun to called after some duration has elapsed

func Call

func Call(d time.Duration, fn func()) (*Fn, error)

Call executes a fn after the duration and returns a handle to the function so that it can be cancelled or overridden

func NewFn added in v0.2.0

func NewFn(d time.Duration, fn func()) *Fn

NewFn returns an instance of delayed Fn

func (*Fn) Call

func (f *Fn) Call() error

Call waits for the duration to elapse and then calls fn in its own goroutine.

func (*Fn) Cancel

func (f *Fn) Cancel() bool

Cancel cancels the function that was scheduled by Call

func (*Fn) Reset added in v0.2.0

func (f *Fn) Reset(d time.Duration, fn func()) error

Reset resets both duration and the fn to call.

func (*Fn) ResetDelay added in v0.2.0

func (f *Fn) ResetDelay(d time.Duration) error

ResetDelay resets the delay and starts again

func (*Fn) ResetFunc added in v0.2.0

func (f *Fn) ResetFunc(fn func()) error

ResetFunc resets func to be invoked

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL