-
Notifications
You must be signed in to change notification settings - Fork 103
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
Conversation
Codecov Report
@@ Coverage Diff @@
## master #77 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 8 14 +6
Lines 232 239 +7
=========================================
+ Hits 232 239 +7
Continue to review full report at Codecov.
|
string.go
Outdated
if v != "" { | ||
x.Store(v) | ||
} | ||
x.Store(v) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
internal/gen-atomicwrapper/main.go
Outdated
|
||
sort.Strings([]string(opts.Imports)) | ||
|
||
data := struct { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
bd76b55
to
f0da400
Compare
internal/gen-atomicwrapper/main.go
Outdated
@@ -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 }} |
There was a problem hiding this comment.
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 }}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yeah good catch.
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.
gen-valuewrapper
is specialized to generating type-safe atomicwrappers around
atomic.Value
. This limitation is unnecessary. Givenfunctions 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 anatomicwrapper
implementingsaid 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.