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

Generate all atomics automatically #77

Merged
merged 5 commits into from
May 15, 2020
Merged

Generate all atomics automatically #77

merged 5 commits into from
May 15, 2020

Conversation

abhinav
Copy link
Collaborator

@abhinav abhinav commented May 14, 2020

gen-valuewrapper is specialized to generating type-safe atomic
wrappers around atomic.Value. This limitation is unnecessary. Given
functions to convert an exposed type to the underlying type (referred to
as "packing" here) and back ("unpacking"), we can generate wrappers
around any backing atomic type.

This generalizes valuewrapper into an atomicwrapper implementing
said functionality, and adding opt-in support for generating CAS, Swap,
and JSON methods.

With this, we can automatically generate bool, float64, and
time.Duration atomic wrappers on top of Uint32, Uint64, and Int64
respectively, as well as their core functionality.


Commits should be reviewed individually.

@codecov
Copy link

codecov bot commented May 14, 2020

Codecov Report

Merging #77 into master will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##            master       #77   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            8        14    +6     
  Lines          232       239    +7     
=========================================
+ Hits           232       239    +7     
Impacted Files Coverage Δ
string_ext.go 100.00% <ø> (ø)
bool.go 100.00% <100.00%> (ø)
bool_ext.go 100.00% <100.00%> (ø)
duration.go 100.00% <100.00%> (ø)
duration_ext.go 100.00% <100.00%> (ø)
error.go 100.00% <100.00%> (ø)
error_ext.go 100.00% <100.00%> (ø)
float64.go 100.00% <100.00%> (ø)
float64_ext.go 100.00% <100.00%> (ø)
string.go 100.00% <100.00%> (ø)
... and 7 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ddc304d...b3957f7. Read the comment docs.

string.go Outdated
if v != "" {
x.Store(v)
}
x.Store(v)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a small behaviour change as it means NewString("") now will allocate.

we likely could use the same optimization here and in the error wrapper

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. Adding back the optimization.

@@ -23,29 +23,29 @@
package atomic

// String is an atomic type-safe wrapper for string values.
type String struct{ v Value }
type String struct {
nocmp // disallow non-atomic comparison
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intentional behaviour change? I don't mind it, we may want to call out that this is changing

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you referring to nocmp? This is the same behavior. Previously nocmp was added by Value. Now, it's added on all types by the generator.


sort.Strings([]string(opts.Imports))

data := struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(no action needed) these are all basically the options passed in, should we declare options as a struct, should we just pass that in?

we could add methods on the option struct to convert things like imports from a comma-separated list into []string too

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we can just pass the opts struct in instead of data. I was trying to keep templating and flag parsing separated but that's not necessary for this case I suppose.

@abhinav abhinav force-pushed the abg/generate-all branch 2 times, most recently from bd76b55 to f0da400 Compare May 15, 2020 22:21
@abhinav abhinav requested a review from prashantv May 15, 2020 22:22
@@ -252,7 +249,7 @@ func (x *{{ .Name }}) Load() {{ .Type }} {
{{ if .Unpack -}}
return {{ .Unpack }}(x.v.Load())
{{- else -}}
var o {{ .Type }}{{ with .Zero }} = {{ . }}{{ end}}
var o {{ .Type }}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't think we need this variable anymore, since we have the zero value

if v := [..]; v != nil {
  return v.(type)
}
return _zero{{ .Type }}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yeah good catch.

abhinav added 5 commits May 15, 2020 15:47
valuewrapper can be used only to generate atomic wrapper types for
types which are stored as atomic.Value. This isn't necessary because the
same logic can be applied to atomic wrappers built on other types like
Duration and Bool.

Generalize valuewrapper into atomicwrapper with support for optional
pack/unpack functions which handle conversion to/from `interface{}`.
This lets Error hook in and install the `storedError` struct (now called
`packedError`) to avoid panics from nil storage or value type change.
As in #73, separate each atomic type into its own file to ease review of
transition to generated code.

After moving every atomic to its own file, the atomic.go file serves
only as documentation, so rename it to doc.go.
Generate atomic.Bool with gen-valuewrapper by wrapping atomic.Uint32.
CAS, Swap, and JSON implementations are generated automatically.
Generate atomic.Float64 with gen-valuewrapper by wrapping atomic.Uint64,
using math.Float64bits and math.Float64frombits to pack and unpack
float64 to uint64.
Generate atomic.Duration with gen-valuewrapper by wrapping atomic.Int64.
Use type casts to int64 and time.Duration as pack and unpack.
@abhinav abhinav force-pushed the abg/generate-all branch from 3091b95 to b3957f7 Compare May 15, 2020 22:47
@abhinav abhinav merged commit 7ccfa79 into master May 15, 2020
@abhinav abhinav deleted the abg/generate-all branch May 15, 2020 22:50
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

Successfully merging this pull request may close these issues.

2 participants