Categorygithub.com/gdbu/atoms
repositorypackage
1.0.1
Repository: https://github.com/gdbu/atoms.git
Documentation: pkg.go.dev

# Packages

No description provided by the author

# README

Atoms GoDoc Status Go Report Card

Atoms is a QoL helper library which provides atomic primitives. The goal of this library is to reduce the amount of mundane boilplate code associated with managing atomic-friendly values

Provided primitives

  • int
  • uint
  • int32
  • int64
  • uint32
  • uint64
  • boolean
  • string

Non-primitive helpers

  • generic value (interface{})
  • mutex wrapper
  • rwmutex wrapper

Features

Numeric values

  • Load
  • Store
  • Swap
  • Add
  • CompareAndSwap
  • JSON Marshal/Unmarshal

Boolean

  • Get
  • Set (Compare and swap functionality)
  • JSON Marshal/Unmarshal

String

  • Load
  • Store
  • Swap
  • JSON

Generic

  • Load
  • Store
  • Swap
  • CompareAndSwap
  • JSON Marshal/Unmarshal

Usage

Int64

package main

import (
	"fmt"
	"github.com/gdbu/atoms"
)

func main() {
	var i atoms.Int64
	// Set value to 7
	i.Store(7)
	current := i.Load()
	fmt.Printf("Current value: %d\n", current)

	// Swap value with 13, returned value will be our old value
	old := i.Swap(13)
	fmt.Printf("Old value: %d\n", old)

	// Increment value by 6, returned value will be our new value
	new := i.Add(6)
	fmt.Printf("New value: %d\n", new)

	// Compare and swap value, will fail because value is 19 (not 20)
	changed := i.CompareAndSwap(20, 40)
	fmt.Printf("Changed: %v\n", changed)
}

Bool

package main

import (
	"fmt"
	"github.com/gdbu/atoms"
)

func main() {
	var b atoms.Bool
	// Get current state
	state := b.Get()
	fmt.Printf("State: %v\n", state)

	// Set value, will fail because value has not changed
	changed := b.Set(false)
	fmt.Printf("Changed: %v\n", changed)

	// Set value to true
	changed = b.Set(true)
	fmt.Printf("Changed: %v\n", changed)

	// Get current state
	state = b.Get()
	fmt.Printf("State: %v\n", state)
}

String

package main

import (
	"fmt"
	"github.com/gdbu/atoms"
)

func main() {
	var s atoms.String
	// Set value to "Hello world"
	s.Store("Hello world")
	current := s.Load()
	fmt.Printf("Current value: %s\n", current)

	// Swap value with "Goodbye world", returned value will be our old value
	old := s.Swap("Goodbye world")
	fmt.Printf("Old value: %s\n", old)

	current := s.Load()
	fmt.Printf("New current value: %s\n", current)
}

Value

package main

import (
	"encoding/json"
	"fmt"
	"log"

	"github.com/gdbu/atoms"
)

func main() {
	type dummy struct {
		V int `json:"v"`
	}
	var v atoms.Value

	// set the internal type
	v.Store(dummy{})

	b := []byte(`{ "v" : 45066 }`)
	if err := json.Unmarshal(b, &v); err != nil {
		log.Fatal(err)
	}
	v.CompareAndSwap(func(oldV interface{}) (newV interface{}, ok bool) {
		v, _ := oldV.(dummy)
		v.V++
		return v, true
	})

	dv, _ := v.Load().(dummy)

	fmt.Printf("%#+v\n", dv)
	fmt.Printf("0x%Xs\n", dv.V)
}

Mux/RWMux

package main

import (
	"fmt"
	"sync"

	"github.com/gdbu/atoms"
)

func main() {
	var wg sync.WaitGroup
	c := NewCounter()
	wg.Add(3)

	go func() {
		c.Increment("foo")
		wg.Done()
	}()

	go func() {
		c.Increment("foo")
		wg.Done()
	}()

	go func() {
		c.Increment("foo")
		wg.Done()
	}()

	// Wait for all goroutines to finish
	wg.Wait()

	// Output will be 3
	fmt.Println(c.Get("foo"))
}

// NewCounter will return a new counter
func NewCounter() *Counter {
	var c Counter
	// Initialize our internal map
	c.cm = make(map[string]uint64)
	return &c
}

// Counter manages a counter
type Counter struct {
	mux atoms.RWMux
	cm  map[string]uint64
}

// Increment will increment a given key
func (c *Counter) Increment(key string) {
	c.mux.Update(func() {
		c.cm[key]++
	})
}

// Get will get the counter value for a given key
func (c *Counter) Get(key string) (n uint64) {
	c.mux.Read(func() {
		n = c.cm[key]
	})

	return
}

Note - Check out the examples directory for compilable examples