mutexmap

package module
v0.0.0 Latest Latest
Warning

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

Go to latest
Published: Mar 10, 2026 License: MIT Imports: 2 Imported by: 0

README

GitHub Workflow Status (branch) GoDoc Coverage Status Supported Go Versions GitHub Release Go Report Card

MutexMap - A Thread-Safe Map for Go

A thread-safe map implementation using sync.RWMutex to synchronize access. This package is optimized to handle concurrent reads and writes, providing efficient and reliable operations in multi-thread applications.


CHINESE README

中文说明

Overview

Go's standard map is not safe when accessed concurrently. This package wraps a map[K]V with sync.RWMutex to provide thread safety. With RWMutex, multiple readers can access the map at once, while writes are synchronized to prevent race conditions.

Main highlights:

  • Thread-safety: Prevents data races in concurrent environments.
  • Efficient Reads: Read operations (Get, Range) allow simultaneous access without blocking.
  • Synchronous Write: Write operations (Set, Delete, Getset) are synchronous.

This package is suitable when you need frequent reads and infrequent writes with a shared map.

Installation

go get github.com/yylego/mutexmap  

Example Usage

Basic Operations
package main

import (
	"fmt"
	"github.com/yylego/mutexmap"
)

func main() {
	mp := mutexmap.NewMap[string, int](10)

	mp.Set("key1", 100)
	mp.Set("key2", 200)

	if value, found := mp.Get("key1"); found {
		fmt.Println("Key1 Value:", value)
	}

	mp.Range(func(key string, value int) bool {
		fmt.Println(key, value)
		return true
	})
}

⬆️ Source: Source

Using Getset for Cached Initialization
package main

import (
	"fmt"

	"github.com/yylego/mutexmap"
)

func main() {
	mp := mutexmap.NewMap[string, string](10)

	value, status := mp.Getset("exampleKey", func() string {
		return "This is a computed value"
	})
	fmt.Println("Status:", status, "Value:", value)

	value, status = mp.Getset("exampleKey", func() string {
		return "New value"
	})
	fmt.Println("Status:", status, "Value:", value)
}

⬆️ Source: Source

Features

  • Concurrent Access: Allows multiple goroutines to read and write to the map with thread protection.
  • Optimized Reads: Supports simultaneous reads to improve performance.
  • Custom Initialization: Use Getset to set a new value when the given ID does not exist.

Method Reference

Method Description
NewMap[K comparable, V any](cap int) Creates a new Map with starting capacity hint.
Get(k K) (V, bool) Retrieves the value associated with the ID. Returns false when the ID does not exist.
Set(k K, v V) Associates a value with the given ID. Overwrites if the ID exists.
Delete(k K) Removes the association from the map.
Len() int Returns the count of associations in the map.
Range(func(k K, v V) bool) Iterates through each association. Stops when the function returns false.
Getset(k K, func() V) (V, enum) Gets a value and sets it when it doesn't exist, preventing duplicate computation.

Examples

This section demonstrates various usage patterns and techniques with MutexMap.

Concurrent Access Patterns

Safe concurrent reads and writes:

mp := mutexmap.NewMap[string, int](10)

// Multiple goroutines can access the map with thread protection
go func() {
    mp.Set("counter", 100)
}()

go func() {
    if value, ok := mp.Get("counter"); ok {
        fmt.Println("Value:", value)
    }
}()

Concurrent initialization with Getset:

mp := mutexmap.NewMap[string, *Database](10)

// Multiple goroutines requesting the same resource
// Just one creates it, the rest wait and receive the same instance
db, status := mp.Getset("primary", func() *Database {
    return ConnectDatabase("primary")
})
Safe Initialization Patterns

On-demand configuration loading:

configMap := mutexmap.NewMap[string, Config](10)

config, status := configMap.Getset("app", func() Config {
    return LoadConfigFromFile("config.json")
})
// First call: status == mutexmap.CacheSet
// Subsequent calls: status == mutexmap.CacheGet

Database connection pooling:

connMap := mutexmap.NewMap[string, *sql.DB](5)

conn, _ := connMap.Getset("mysql", func() *sql.DB {
    db, _ := sql.Open("mysql", "user:pass@/dbname")
    return db
})
Check-And-Act Operations

Check before update:

mp := mutexmap.NewMap[string, int](10)
mp.Set("score", 100)

if value, found := mp.Get("score"); found {
    mp.Set("score", value+10) // Increment existing value
}

Delete if exists:

if _, found := mp.Get("tempData"); found {
    mp.Delete("tempData")
}
Iteration Patterns

Process each item:

mp.Range(func(key string, value int) bool {
    fmt.Printf("%s: %d\n", key, value)
    return true // Continue iteration
})

Find specific entry:

mp.Range(func(key string, value int) bool {
    if value > 100 {
        fmt.Println("Found:", key)
        return false // Stop iteration
    }
    return true
})

Count matching entries:

count := 0
mp.Range(func(key string, value int) bool {
    if value > threshold {
        count++
    }
    return true
})
Type-Safe Usage

String to struct mapping:

type Account struct {
    ID   int
    Name string
}

accountMap := mutexmap.NewMap[string, Account](10)
accountMap.Set("user1", Account{ID: 1, Name: "Alice"})

Int to function mapping:

handlerMap := mutexmap.NewMap[int, func() error](10)
handlerMap.Set(404, func() error {
    return fmt.Errorf("not found")
})
Cache Use Cases

API response caching:

cache := mutexmap.NewMap[string, APIResponse](100)

response, status := cache.Getset(requestURL, func() APIResponse {
    return FetchFromAPI(requestURL)
})

Computed value caching:

resultCache := mutexmap.NewMap[string, int](50)

result, _ := resultCache.Getset("expensive-computation", func() int {
    return PerformExpensiveCalculation()
})

Session management:

sessions := mutexmap.NewMap[string, Session](100)

session, status := sessions.Getset(sessionID, func() Session {
    return CreateNewSession(sessionID)
})
Batch Operations

Bulk insert:

data := map[string]int{"a": 1, "b": 2, "c": 3}
mp := mutexmap.NewMap[string, int](len(data))

for k, v := range data {
    mp.Set(k, v)
}

Bulk check:

keys := []string{"key1", "key2", "key3"}
found := make(map[string]bool)

for _, key := range keys {
    if _, ok := mp.Get(key); ok {
        found[key] = true
    }
}

Benefits

  1. Thread Protection: Required when sharing maps across multiple threads.
  2. Efficient Reads: Read lock (RLock) allows simultaneous read access without contention.
  3. Write Protection: Write lock (Lock) maintains data coherence during changes.
  4. Smart Initialization: The Getset method avoids redundant computation.

📄 License

MIT License. See LICENSE.


🤝 Contributing

Contributions are welcome! Report bugs, suggest features, and contribute code:

  • 🐛 Found a mistake? Open an issue on GitHub with reproduction steps
  • 💡 Have a feature idea? Create an issue to discuss the suggestion
  • 📖 Documentation confusing? Report it so we can improve
  • 🚀 Need new features? Share the use cases to help us understand requirements
  • Performance issue? Help us optimize through reporting slow operations
  • 🔧 Configuration problem? Ask questions about complex setups
  • 📢 Follow project progress? Watch the repo to get new releases and features
  • 🌟 Success stories? Share how this package improved the workflow
  • 💬 Feedback? We welcome suggestions and comments

🔧 Development

New code contributions, follow this process:

  1. Fork: Fork the repo on GitHub (using the webpage UI).
  2. Clone: Clone the forked project (git clone https://github.com/yourname/repo-name.git).
  3. Navigate: Navigate to the cloned project (cd repo-name)
  4. Branch: Create a feature branch (git checkout -b feature/xxx).
  5. Code: Implement the changes with comprehensive tests
  6. Testing: (Golang project) Ensure tests pass (go test ./...) and follow Go code style conventions
  7. Documentation: Update documentation to support client-facing changes and use significant commit messages
  8. Stage: Stage changes (git add .)
  9. Commit: Commit changes (git commit -m "Add feature xxx") ensuring backward compatible code
  10. Push: Push to the branch (git push origin feature/xxx).
  11. PR: Open a merge request on GitHub (on the GitHub webpage) with detailed description.

Please ensure tests pass and include relevant documentation updates.


🌟 Support

Welcome to contribute to this project via submitting merge requests and reporting issues.

Project Support:

  • Give GitHub stars if this project helps you
  • 🤝 Share with teammates and (golang) programming friends
  • 📝 Write tech blogs about development tools and workflows - we provide content writing support
  • 🌟 Join the ecosystem - committed to supporting open source and the (golang) development scene

Have Fun Coding with this package! 🎉🎉🎉

GitHub Stars

starring

Documentation

Overview

Package mutexmap provides thread-safe map implementations with fine-grained locking Supports concurrent read and write operations through sync.RWMutex Offers both basic thread-safe map and advanced on-demand loading cache map Enables safe concurrent access without outside synchronization

mutexmap 包提供具有细粒度锁的线程安全 map 实现 通过 sync.RWMutex 支持并发读写操作 提供基础线程安全 map 和高级按需加载缓存 map 无需外部同步即可实现安全的并发访问

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CacheStatus

type CacheStatus string

CacheStatus represents the result status of a cache operation Indicates if a value was retrieved from cache, computed and set

CacheStatus 代表缓存操作的结果状态 指示值是从缓存中获取的还是计算后设置的

const (
	CacheGet CacheStatus = "GET" // Value retrieved from existing cache // 从现有缓存中获取的值
	CacheSet CacheStatus = "SET" // Value computed and stored in cache // 计算后存储到缓存的值
)

type Map

type Map[K comparable, V any] struct {
	// contains filtered or unexported fields
}

Map provides a thread-safe map implementation using sync.RWMutex Supports generic keys (comparable) and values (any) Offers concurrent reads and exclusive writes Implements Getset method with double-checked locking pattern

Map 提供使用 sync.RWMutex 的线程安全 map 实现 支持泛型键(可比较)和泛型值(任意) 提供并发读操作和独占写操作 实现具有双重检查锁定模式的 Getset 方法

func New

func New[K comparable, V any]() *Map[K, V]

New creates a new thread-safe map with default starting size of 8 Returns a Map instance that supports concurrent operations Use NewMap to set a custom starting size

New 创建具有默认初始容量 8 的新线程安全 map 返回支持并发操作的 Map 实例 如需指定初始容量请使用 NewMap

func NewMap

func NewMap[K comparable, V any](cap int) *Map[K, V]

NewMap creates a new thread-safe map with the given starting size The cap sets the starting size hint to optimize allocation Returns a Map instance sized to fit the expected element count

NewMap 创建具有指定初始容量的新线程安全 map cap 参数设置底层 map 的初始大小提示 返回针对预期元素数量优化的 Map 实例

func (*Map[K, V]) Delete

func (a *Map[K, V]) Delete(k K)

Delete removes the mapping from the map Safe to use even when the id does not exist (becomes a no-op) Uses write lock to ensure exclusive access when deleting Blocks any concurrent operations when executing

Delete 从 map 中删除键值对 如果键不存在则无操作(删除不存在的键是安全的) 使用写锁以确保删除期间的独占访问 执行期间阻塞所有其他操作

func (*Map[K, V]) Get

func (a *Map[K, V]) Get(k K) (V, bool)

Get retrieves the value associated with a given id Returns the value and true when found, zero value and false when absent Uses read lock to enable concurrent Get operations Thread-safe and allows multiple concurrent Get operations

Get 获取与指定键关联的值 如果键存在则返回值和 true,否则返回零值和 false 使用读锁以允许并发 Get 操作 与其他 Get 操作的并发读取是线程安全的

func (*Map[K, V]) Getset

func (a *Map[K, V]) Getset(k K, calculate func() V) (v V, status CacheStatus)

Getset retrieves the value at the id, computes and stores it when absent Uses double-checked locking pattern to cut down lock contention and skip redundant calculations Returns the value and an enum showing if a new value was created

Getset 获取与键关联的值,如果键不存在,则计算并存储新值 使用双重检查锁定模式以减少锁竞争并避免重复计算 它返回值以及一个枚举值,指示是否创建了新值

func (*Map[K, V]) Len

func (a *Map[K, V]) Len() int

Len returns the count of mappings in the map Provides a snapshot at the invocation time Uses read lock to enable concurrent Len operations with Get Note: the count can change at once because of concurrent modifications

Len 返回 map 中键值对的数量 提供调用时刻的 map 大小快照 使用读锁以允许与 Get 的并发 Len 操作 由于并发修改,返回后计数可能立即改变

func (*Map[K, V]) Range

func (a *Map[K, V]) Range(run func(k K, v V) bool)

Range iterates through each mapping, calling the given function on it Processes mappings in sequence, stopping when the callback returns false Uses read lock to block modifications but enables multiple Range executions Stops iteration when callback returns false, which supports selective processing

Range 遍历 map 中的每个键值对,应用给定的函数 对每个条目调用函数,直到处理完所有条目或函数返回 false 使用读锁以防止迭代期间的修改,但允许并发 Range 调用 当回调返回 false 时停止迭代,实现条件处理

func (*Map[K, V]) Set

func (a *Map[K, V]) Set(k K, v V)

Set inserts a new mapping and updates when the id exists Replaces existing value without checking its previous state Uses write lock to ensure exclusive access to modifications Blocks any concurrent operations (Get, Set, Delete, Range) when executing

Set 插入新的键值对或更新现有键的值 替换现有值而不检查先前状态 使用写锁以确保修改期间的独占访问 执行期间阻塞所有其他操作(Get、Set、Delete、Range)

Directories

Path Synopsis
Package cachemap provides advanced thread-safe on-demand cache map implementation Enables concurrent value computation with fine-grained locking to skip redundant calculations Supports expensive operations through id-based locking instead of map-wide locks Caches both success outcomes and errors to skip repeated failed computations
Package cachemap provides advanced thread-safe on-demand cache map implementation Enables concurrent value computation with fine-grained locking to skip redundant calculations Supports expensive operations through id-based locking instead of map-wide locks Caches both success outcomes and errors to skip repeated failed computations
internal
demos/demo1x command
demos/demo2x command
utils
Package utils provides generic utilities and helper functions Supports common operations used across mutexmap implementations
Package utils provides generic utilities and helper functions Supports common operations used across mutexmap implementations

Jump to

Keyboard shortcuts

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