Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Map function (Read/Replace) in single lock #118

Open
tarqd opened this issue Feb 20, 2020 · 1 comment
Open

Add Map function (Read/Replace) in single lock #118

tarqd opened this issue Feb 20, 2020 · 1 comment

Comments

@tarqd
Copy link

tarqd commented Feb 20, 2020

Imagine you have a cache containing items that are themselves maps or objects that are passed by reference.

If you want to modify one of the entries/elements in the cached object, you need to Get the item, copy it, and then Set to avoid modifying the shared reference returned by Get.

Adding a way to read/modify an entry within the same lock would help with this use-case:

cache.Map("key", func(result (interface{}, bool)) interface{} {
    // do stuff with item and return it 
  }, cache.DefaultExpiration);

Implementation example (I apologize if the syntax is wrong):

func (c *cache) Map(k string, mapFn func(item (interface{}, bool)) interface{} , d time.Duration) {
	// "Inlining" of set
	var e int64
        
	if d == DefaultExpiration {
		d = c.defaultExpiration
	}
	if d > 0 {
		e = time.Now().Add(d).UnixNano()
	}
	c.mu.Lock()
        
	c.items[k] = Item{
		Object:     mapFn(c.get(k)),
		Expiration: e,
	}
	// TODO: Calls to mu.Unlock are currently not deferred because defer
	// adds ~200 ns (as of go1.)
	c.mu.Unlock()
}

So now we have an easy way to Read and Replace a complex object using only one lock and not risking accidental mutation of a shared reference.

Alternatively, exporting Lock/Unlock functions for consumers of this library would make it easier to write functions that perform bulk modifications to cache without as much locking.

@Yonhoo
Copy link

Yonhoo commented Jul 23, 2020

I also thought of this, and I also think there is a safer method like this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants