monadic

package
v0.5.1 Latest Latest
Warning

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

Go to latest
Published: Jan 2, 2025 License: MIT Imports: 1 Imported by: 0

README

xpool/monadic

Definition

The intent of this package is to support monadic objects in the xpool. By default is uses a Resetter[S any] monadic interface Reset(state S).

We define a different Pool interface, where we set a new state S on the object when we get it from the pool, and we reset the state by setting a zero value of state S before put it back to the object pool.

// Pool monadic is a type-safe object pool interface.
type Pool[S, T any] interface {
    // Get fetch one item from object pool. If needed, will create another object.
    // The state S will be used in the resetter.
    Get(state S) T

    // Put return the object to the pull.
    // A zero value of T will be used in the resetter.
    Put(object T)
}

Usage

We offer two constructors:

    // besides the log, both calls are equivalent

    // the monadic pool will try to call `Reset([]byte)` method by default.
    pool:= monadic.New[[]byte](func() *bytes.Reader {
        return bytes.NewReader(nil)
    })

    // the monadic pool will try to call the specific resetter callback.
    pool:= monadic.NewWithCustomResetter(func() *bytes.Reader {
        return bytes.NewReader(nil)
    }, func(r *bytes.Reader, b []byte) {
        r.Reset(b)

        log.Println("just reset the *bytes.Buffer")
    })

using the second constructor, you can build more complex resetters, like:

    // can infer types from resetter
    poolReader := monadic.NewWithCustomResetter(func() io.ReadCloser {
        return flate.NewReader(nil)
    }, func(object io.ReadCloser, state io.Reader) {
        reseter, _ := reader.(flate.Resetter)
		_ = reseter.Reset(state, nil)
    })

Documentation

Overview

The intent of monadic is to support monadic objects.

Different than xpool.Pool, the monadic Pool handle two different generic types: S and T

  • T is the type of the object returned from the pool
  • S is the state, where we set before return an object, and reset it back to zero value of S when put back to the pool.

In other words, instead having to do:

pool := xpool.New(func() *bytes.Reader { // you must use a type or interface that exposes a Reset() method
  return bytes.NewReader(nil)
})

br := pool.Get()
defer func() { br.Reset(nil) ; pool.Put(br) }()

br.Reset(payload)
// use the byte reader here

We can use New to create a monadic Pool that manage the state of bytes.Reader via Reset method implicity:

pool := monadic.New[[]byte](func() io.Reader { // you can use any interface that you want
  return bytes.NewReader(nil)
}

br := pool.Get(payload) // implicit Reset(payload) -- Get(state) is monadic, instead the niladic version on xpool.Pool
defer pool.Put(br)      // implicit Reset(nil)     -- the zero value of state S, []byte on this case

// use byte reader here as io.Reader

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Pool

type Pool[S, T any] interface {
	// Get fetch one item from object pool. If needed, will create another object.
	// The state S will be used in the resetter.
	Get(state S) T

	// Put return the object to the pull.
	// A zero value of T will be used in the resetter.
	Put(object T)
}

Pool monadic is a type-safe object pool interface. This interface is parameterized on two generic types:

  • T is reserved for the type of the object that will be stored on the pool.
  • S is reserved for the status of the object to be setted before return the object from the pool.

func New

func New[S any, T Resetter[S]](
	ctor func() T,
) Pool[S, T]

New is the constructor of an Pool for a given set of generic types S and T. Receives the constructor of the type T. It sets a trivial resetter, T must be a Resetter will call Reset(state S) before return the object on Get(state S) will call Reset(zero value of S) before push back to the pool.

Example
package main

import (
	"bytes"
	"io"
	"os"

	"github.com/peczenyj/xpool/monadic"
)

func main() {
	var pool monadic.Pool[[]byte, *bytes.Reader] = monadic.New[[]byte, *bytes.Reader](func() *bytes.Reader {
		return bytes.NewReader(nil)
	})

	reader := pool.Get([]byte(`payload`))
	defer pool.Put(reader)

	_, _ = io.Copy(os.Stdout, reader)
}
Output:

payload

func NewWithCustomResetter added in v0.5.0

func NewWithCustomResetter[S, T any](
	ctor func() T,
	customResetter func(object T, state S),
) Pool[S, T]

NewWithCustomResetter is the constructor of an Pool for a given set of generic types S and T. Receives the constructor of the type T as a callback. We can specify a special resetter, to be called with a zero value of S before return the object from the pool. Be careful, the custom resetter must be thread safe.

Example
package main

import (
	"bytes"
	"compress/flate"
	"io"
	"log"
	"os"
	"strings"

	"github.com/peczenyj/xpool/monadic"
)

func main() {
	poolWriter := monadic.New[io.Writer, *flate.Writer](func() *flate.Writer {
		zw, _ := flate.NewWriter(nil, flate.DefaultCompression)
		return zw
	})

	poolReader := monadic.NewWithCustomResetter[io.Reader, io.ReadCloser](func() io.ReadCloser {
		return flate.NewReader(nil)
	}, func(reader io.ReadCloser, state io.Reader) {
		reseter, _ := reader.(flate.Resetter)
		_ = reseter.Reset(state, nil)
	})

	var b bytes.Buffer

	r := strings.NewReader("hello, world!\n")

	zwc := poolWriter.Get(&b)
	defer poolWriter.Put(zwc)

	if _, err := io.Copy(zwc, r); err != nil {
		log.Fatal(err)
	}

	if err := zwc.Close(); err != nil {
		log.Fatal(err)
	}

	zrc := poolReader.Get(&b)
	defer poolReader.Put(zrc)

	_, _ = io.Copy(os.Stdout, zrc)

}
Output:

hello, world!

type Resetter

type Resetter[S any] interface {
	Reset(state S)
}

Resetter monadic interface.