Skip to content

Commit

Permalink
sumdb: client and server protocol for checksum database
Browse files Browse the repository at this point in the history
Copied from golang.org/x/exp/sumdb/internal/sumweb
with types cleaned up:

	Conn -> Client
	Client -> ClientOps
	Handler -> Server
	Server -> ServerOps

For golang/go#31761.

Change-Id: If0e004e6c9cab69c82de428810d67aba074aa843
Reviewed-on: https://go-review.googlesource.com/c/mod/+/176466
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
  • Loading branch information
rsc committed May 31, 2019
1 parent 4bf6d31 commit a1091b6
Show file tree
Hide file tree
Showing 5 changed files with 1,499 additions and 0 deletions.
59 changes: 59 additions & 0 deletions sumdb/cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Parallel cache.
// This file is copied from cmd/go/internal/par.

package sumdb

import (
"sync"
"sync/atomic"
)

// parCache runs an action once per key and caches the result.
type parCache struct {
m sync.Map
}

type cacheEntry struct {
done uint32
mu sync.Mutex
result interface{}
}

// Do calls the function f if and only if Do is being called for the first time with this key.
// No call to Do with a given key returns until the one call to f returns.
// Do returns the value returned by the one call to f.
func (c *parCache) Do(key interface{}, f func() interface{}) interface{} {
entryIface, ok := c.m.Load(key)
if !ok {
entryIface, _ = c.m.LoadOrStore(key, new(cacheEntry))
}
e := entryIface.(*cacheEntry)
if atomic.LoadUint32(&e.done) == 0 {
e.mu.Lock()
if atomic.LoadUint32(&e.done) == 0 {
e.result = f()
atomic.StoreUint32(&e.done, 1)
}
e.mu.Unlock()
}
return e.result
}

// Get returns the cached result associated with key.
// It returns nil if there is no such result.
// If the result for key is being computed, Get does not wait for the computation to finish.
func (c *parCache) Get(key interface{}) interface{} {
entryIface, ok := c.m.Load(key)
if !ok {
return nil
}
e := entryIface.(*cacheEntry)
if atomic.LoadUint32(&e.done) == 0 {
return nil
}
return e.result
}
Loading

0 comments on commit a1091b6

Please sign in to comment.