mirror of https://github.com/golang/go.git
[dev.power64] all: merge default into dev.power64
LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/164110043
This commit is contained in:
commit
5a653089ef
|
|
@ -42,6 +42,10 @@ identical to Go 1.1. The GCC 4.8.2 release includes a complete Go
|
||||||
1.1.2 implementation.
|
1.1.2 implementation.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The GCC 4.9 releases include a complete Go 1.2 implementation.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2 id="Source_code">Source code</h2>
|
<h2 id="Source_code">Source code</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,10 @@ bufio: handling of empty tokens at EOF changed, may require scanner change (CL 1
|
||||||
compress/flate, compress/gzip, compress/zlib: Reset support (https://codereview.appspot.com/97140043)
|
compress/flate, compress/gzip, compress/zlib: Reset support (https://codereview.appspot.com/97140043)
|
||||||
crypto/tls: add support for ALPN (RFC 7301) (CL 108710046)
|
crypto/tls: add support for ALPN (RFC 7301) (CL 108710046)
|
||||||
crypto/tls: support programmatic selection of server certificates (CL 107400043)
|
crypto/tls: support programmatic selection of server certificates (CL 107400043)
|
||||||
|
encoding/asn1: optional elements with a default value will now only be omitted if they have that value (CL 86960045)
|
||||||
flag: it is now an error to set a flag multiple times (CL 156390043)
|
flag: it is now an error to set a flag multiple times (CL 156390043)
|
||||||
fmt: print type *map[T]T as &map[k:v] (CL 154870043)
|
fmt: print type *map[T]T as &map[k:v] (CL 154870043)
|
||||||
|
encoding/csv: do not quote empty strings, quote \. (CL 164760043)
|
||||||
encoding/gob: remove unsafe (CL 102680045)
|
encoding/gob: remove unsafe (CL 102680045)
|
||||||
misc: deleted editor support; refer to https://code.google.com/p/go-wiki/wiki/IDEsAndTextEditorPlugins instead (CL 105470043)
|
misc: deleted editor support; refer to https://code.google.com/p/go-wiki/wiki/IDEsAndTextEditorPlugins instead (CL 105470043)
|
||||||
net/http: add Request.BasicAuth method (CL 76540043)
|
net/http: add Request.BasicAuth method (CL 76540043)
|
||||||
|
|
@ -46,6 +48,6 @@ testing: add TestMain support (CL 148770043)
|
||||||
text/scanner: add IsIdentRune field of Scanner. (CL 108030044)
|
text/scanner: add IsIdentRune field of Scanner. (CL 108030044)
|
||||||
text/template: allow comparison of signed and unsigned integers (CL 149780043)
|
text/template: allow comparison of signed and unsigned integers (CL 149780043)
|
||||||
time: use the micro symbol (µ (U+00B5)) to print microsecond duration (CL 105030046)
|
time: use the micro symbol (µ (U+00B5)) to print microsecond duration (CL 105030046)
|
||||||
encoding/asn1: optional elements with a default value will now only be omitted if they have that value (CL 86960045)
|
unsafe: document the existing situation that unsafe programs are not go1-guaranteed (CL 162060043)
|
||||||
|
|
||||||
go.sys subrepo created: http://golang.org/s/go1.4-syscall
|
go.sys subrepo created: http://golang.org/s/go1.4-syscall
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,14 @@ outside of tests, and using it may cause a program to fail
|
||||||
to compile in future releases.
|
to compile in future releases.
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
Use of package <code>unsafe</code>. Packages that import
|
||||||
|
<a href="/pkg/unsafe/"><code>unsafe</code></a>
|
||||||
|
may depend on internal properties of the Go implementation.
|
||||||
|
We reserve the right to make changes to the implementation
|
||||||
|
that may break such programs.
|
||||||
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
||||||
|
|
@ -1115,7 +1115,7 @@ error but the situation can still be confusing, because sometimes a
|
||||||
<a href="#different_method_sets">pointer
|
<a href="#different_method_sets">pointer
|
||||||
is necessary to satisfy an interface</a>.
|
is necessary to satisfy an interface</a>.
|
||||||
The insight is that although a pointer to a concrete type can satisfy
|
The insight is that although a pointer to a concrete type can satisfy
|
||||||
an interface, with one exception <em>a pointer to an interface can never satisfy a interface</em>.
|
an interface, with one exception <em>a pointer to an interface can never satisfy an interface</em>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -1356,7 +1356,7 @@ to speed it up.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Go's goroutine scheduler is not as good as it needs to be. In future, it
|
Go's goroutine scheduler is not as good as it needs to be. In the future, it
|
||||||
should recognize such cases and optimize its use of OS threads. For now,
|
should recognize such cases and optimize its use of OS threads. For now,
|
||||||
<code>GOMAXPROCS</code> should be set on a per-application basis.
|
<code>GOMAXPROCS</code> should be set on a per-application basis.
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!--{
|
<!--{
|
||||||
"Title": "The Go Programming Language Specification",
|
"Title": "The Go Programming Language Specification",
|
||||||
"Subtitle": "Version of October 16, 2014",
|
"Subtitle": "Version of October 23, 2014",
|
||||||
"Path": "/ref/spec"
|
"Path": "/ref/spec"
|
||||||
}-->
|
}-->
|
||||||
|
|
||||||
|
|
@ -6207,8 +6207,8 @@ type Error interface {
|
||||||
The built-in package <code>unsafe</code>, known to the compiler,
|
The built-in package <code>unsafe</code>, known to the compiler,
|
||||||
provides facilities for low-level programming including operations
|
provides facilities for low-level programming including operations
|
||||||
that violate the type system. A package using <code>unsafe</code>
|
that violate the type system. A package using <code>unsafe</code>
|
||||||
must be vetted manually for type safety. The package provides the
|
must be vetted manually for type safety and may not be portable.
|
||||||
following interface:
|
The package provides the following interface:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre class="grammar">
|
<pre class="grammar">
|
||||||
|
|
@ -6223,10 +6223,11 @@ func Sizeof(variable ArbitraryType) uintptr
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be converted to
|
|
||||||
a <code>Pointer</code> type and vice versa.
|
|
||||||
A <code>Pointer</code> is a <a href="#Pointer_types">pointer type</a> but a <code>Pointer</code>
|
A <code>Pointer</code> is a <a href="#Pointer_types">pointer type</a> but a <code>Pointer</code>
|
||||||
value may not be <a href="#Address_operators">dereferenced</a>.
|
value may not be <a href="#Address_operators">dereferenced</a>.
|
||||||
|
Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be converted to
|
||||||
|
a <code>Pointer</code> type and vice versa.
|
||||||
|
The effect of converting between <code>Pointer</code> and <code>uintptr</code> is implementation-defined.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,9 @@
|
||||||
|
|
||||||
<Property Id="ARPCOMMENTS" Value="The Go programming language is a fast, statically typed, compiled language that feels like a dynamically typed, interpreted language." />
|
<Property Id="ARPCOMMENTS" Value="The Go programming language is a fast, statically typed, compiled language that feels like a dynamically typed, interpreted language." />
|
||||||
<Property Id="ARPCONTACT" Value="golang-nuts@googlegroups.com" />
|
<Property Id="ARPCONTACT" Value="golang-nuts@googlegroups.com" />
|
||||||
<Property Id="ARPHELPLINK" Value="golang.org/doc/community.html" />
|
<Property Id="ARPHELPLINK" Value="https://golang.org/help/" />
|
||||||
<Property Id="ARPREADME" Value="golang.org" />
|
<Property Id="ARPREADME" Value="https://golang.org" />
|
||||||
<Property Id="ARPURLINFOABOUT" Value="golang.org" />
|
<Property Id="ARPURLINFOABOUT" Value="https://golang.org" />
|
||||||
<Property Id="LicenseAccepted">1</Property>
|
<Property Id="LicenseAccepted">1</Property>
|
||||||
<Icon Id="gopher.ico" SourceFile="images\gopher.ico"/>
|
<Icon Id="gopher.ico" SourceFile="images\gopher.ico"/>
|
||||||
<Property Id="ARPPRODUCTICON" Value="gopher.ico" />
|
<Property Id="ARPPRODUCTICON" Value="gopher.ico" />
|
||||||
|
|
|
||||||
|
|
@ -614,7 +614,7 @@ walkexpr(Node **np, NodeList **init)
|
||||||
if(oaslit(n, init))
|
if(oaslit(n, init))
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
if(n->right == N)
|
if(n->right == N || iszero(n->right) && !flag_race)
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
switch(n->right->op) {
|
switch(n->right->op) {
|
||||||
|
|
@ -1390,12 +1390,6 @@ walkexpr(Node **np, NodeList **init)
|
||||||
case OMAPLIT:
|
case OMAPLIT:
|
||||||
case OSTRUCTLIT:
|
case OSTRUCTLIT:
|
||||||
case OPTRLIT:
|
case OPTRLIT:
|
||||||
// NOTE(rsc): Race detector cannot handle seeing
|
|
||||||
// a STRUCTLIT or ARRAYLIT representing a zero value,
|
|
||||||
// so make a temporary for those always in race mode.
|
|
||||||
// Otherwise, leave zero values in place.
|
|
||||||
if(iszero(n) && !flag_race)
|
|
||||||
goto ret;
|
|
||||||
var = temp(n->type);
|
var = temp(n->type);
|
||||||
anylit(0, n, var, init);
|
anylit(0, n, var, init);
|
||||||
n = var;
|
n = var;
|
||||||
|
|
|
||||||
|
|
@ -1945,6 +1945,7 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
|
||||||
}
|
}
|
||||||
ldflags = append(ldflags, afiles...)
|
ldflags = append(ldflags, afiles...)
|
||||||
ldflags = append(ldflags, cgoldflags...)
|
ldflags = append(ldflags, cgoldflags...)
|
||||||
|
ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...)
|
||||||
ldflags = append(ldflags, p.CgoLDFLAGS...)
|
ldflags = append(ldflags, p.CgoLDFLAGS...)
|
||||||
if usesCgo && goos == "linux" {
|
if usesCgo && goos == "linux" {
|
||||||
ldflags = append(ldflags, "-Wl,-E")
|
ldflags = append(ldflags, "-Wl,-E")
|
||||||
|
|
|
||||||
|
|
@ -272,8 +272,15 @@ func downloadPackage(p *Package) error {
|
||||||
dir := filepath.Join(p.build.SrcRoot, rootPath)
|
dir := filepath.Join(p.build.SrcRoot, rootPath)
|
||||||
if remote, err := vcs.remoteRepo(vcs, dir); err == nil {
|
if remote, err := vcs.remoteRepo(vcs, dir); err == nil {
|
||||||
if rr, err := repoRootForImportPath(p.ImportPath); err == nil {
|
if rr, err := repoRootForImportPath(p.ImportPath); err == nil {
|
||||||
if remote != rr.repo {
|
repo := rr.repo
|
||||||
return fmt.Errorf("%s is from %s, should be from %s", dir, remote, rr.repo)
|
if rr.vcs.resolveRepo != nil {
|
||||||
|
resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo)
|
||||||
|
if err == nil {
|
||||||
|
repo = resolved
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if remote != repo {
|
||||||
|
return fmt.Errorf("%s is from %s, should be from %s", dir, remote, repo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,8 @@ type vcsCmd struct {
|
||||||
scheme []string
|
scheme []string
|
||||||
pingCmd string
|
pingCmd string
|
||||||
|
|
||||||
remoteRepo func(v *vcsCmd, rootDir string) (remoteRepo string, err error)
|
remoteRepo func(v *vcsCmd, rootDir string) (remoteRepo string, err error)
|
||||||
|
resolveRepo func(v *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A tagCmd describes a command to list available tags
|
// A tagCmd describes a command to list available tags
|
||||||
|
|
@ -164,8 +165,51 @@ var vcsBzr = &vcsCmd{
|
||||||
tagSyncCmd: "update -r {tag}",
|
tagSyncCmd: "update -r {tag}",
|
||||||
tagSyncDefault: "update -r revno:-1",
|
tagSyncDefault: "update -r revno:-1",
|
||||||
|
|
||||||
scheme: []string{"https", "http", "bzr", "bzr+ssh"},
|
scheme: []string{"https", "http", "bzr", "bzr+ssh"},
|
||||||
pingCmd: "info {scheme}://{repo}",
|
pingCmd: "info {scheme}://{repo}",
|
||||||
|
remoteRepo: bzrRemoteRepo,
|
||||||
|
resolveRepo: bzrResolveRepo,
|
||||||
|
}
|
||||||
|
|
||||||
|
func bzrRemoteRepo(vcsBzr *vcsCmd, rootDir string) (remoteRepo string, err error) {
|
||||||
|
outb, err := vcsBzr.runOutput(rootDir, "config parent_location")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(string(outb)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func bzrResolveRepo(vcsBzr *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error) {
|
||||||
|
outb, err := vcsBzr.runOutput(rootDir, "info "+remoteRepo)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
out := string(outb)
|
||||||
|
|
||||||
|
// Expect:
|
||||||
|
// ...
|
||||||
|
// (branch root|repository branch): <URL>
|
||||||
|
// ...
|
||||||
|
|
||||||
|
found := false
|
||||||
|
for _, prefix := range []string{"\n branch root: ", "\n repository branch: "} {
|
||||||
|
i := strings.Index(out, prefix)
|
||||||
|
if i >= 0 {
|
||||||
|
out = out[i+len(prefix):]
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return "", fmt.Errorf("unable to parse output of bzr info")
|
||||||
|
}
|
||||||
|
|
||||||
|
i := strings.Index(out, "\n")
|
||||||
|
if i < 0 {
|
||||||
|
return "", fmt.Errorf("unable to parse output of bzr info")
|
||||||
|
}
|
||||||
|
out = out[:i]
|
||||||
|
return strings.TrimSpace(string(out)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// vcsSvn describes how to use Subversion.
|
// vcsSvn describes how to use Subversion.
|
||||||
|
|
|
||||||
|
|
@ -115,10 +115,22 @@ func (w *Writer) WriteAll(records [][]string) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// fieldNeedsQuotes returns true if our field must be enclosed in quotes.
|
// fieldNeedsQuotes returns true if our field must be enclosed in quotes.
|
||||||
// Empty fields, files with a Comma, fields with a quote or newline, and
|
// Fields with a Comma, fields with a quote or newline, and
|
||||||
// fields which start with a space must be enclosed in quotes.
|
// fields which start with a space must be enclosed in quotes.
|
||||||
|
// We used to quote empty strings, but we do not anymore (as of Go 1.4).
|
||||||
|
// The two representations should be equivalent, but Postgres distinguishes
|
||||||
|
// quoted vs non-quoted empty string during database imports, and it has
|
||||||
|
// an option to force the quoted behavior for non-quoted CSV but it has
|
||||||
|
// no option to force the non-quoted behavior for quoted CSV, making
|
||||||
|
// CSV with quoted empty strings strictly less useful.
|
||||||
|
// Not quoting the empty string also makes this package match the behavior
|
||||||
|
// of Microsoft Excel and Google Drive.
|
||||||
|
// For Postgres, quote the data termating string `\.`.
|
||||||
func (w *Writer) fieldNeedsQuotes(field string) bool {
|
func (w *Writer) fieldNeedsQuotes(field string) bool {
|
||||||
if len(field) == 0 || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 {
|
if field == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if field == `\.` || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,17 @@ var writeTests = []struct {
|
||||||
{Input: [][]string{{"abc\ndef"}}, Output: "\"abc\r\ndef\"\r\n", UseCRLF: true},
|
{Input: [][]string{{"abc\ndef"}}, Output: "\"abc\r\ndef\"\r\n", UseCRLF: true},
|
||||||
{Input: [][]string{{"abc\rdef"}}, Output: "\"abcdef\"\r\n", UseCRLF: true},
|
{Input: [][]string{{"abc\rdef"}}, Output: "\"abcdef\"\r\n", UseCRLF: true},
|
||||||
{Input: [][]string{{"abc\rdef"}}, Output: "\"abc\rdef\"\n", UseCRLF: false},
|
{Input: [][]string{{"abc\rdef"}}, Output: "\"abc\rdef\"\n", UseCRLF: false},
|
||||||
|
{Input: [][]string{{""}}, Output: "\n"},
|
||||||
|
{Input: [][]string{{"", ""}}, Output: ",\n"},
|
||||||
|
{Input: [][]string{{"", "", ""}}, Output: ",,\n"},
|
||||||
|
{Input: [][]string{{"", "", "a"}}, Output: ",,a\n"},
|
||||||
|
{Input: [][]string{{"", "a", ""}}, Output: ",a,\n"},
|
||||||
|
{Input: [][]string{{"", "a", "a"}}, Output: ",a,a\n"},
|
||||||
|
{Input: [][]string{{"a", "", ""}}, Output: "a,,\n"},
|
||||||
|
{Input: [][]string{{"a", "", "a"}}, Output: "a,,a\n"},
|
||||||
|
{Input: [][]string{{"a", "a", ""}}, Output: "a,a,\n"},
|
||||||
|
{Input: [][]string{{"a", "a", "a"}}, Output: "a,a,a\n"},
|
||||||
|
{Input: [][]string{{`\.`}}, Output: "\"\\.\"\n"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWrite(t *testing.T) {
|
func TestWrite(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,10 @@ func (name handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Fprintf(w, "Unknown profile: %s\n", name)
|
fmt.Fprintf(w, "Unknown profile: %s\n", name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
gc, _ := strconv.Atoi(r.FormValue("gc"))
|
||||||
|
if name == "heap" && gc > 0 {
|
||||||
|
runtime.GC()
|
||||||
|
}
|
||||||
p.WriteTo(w, debug)
|
p.WriteTo(w, debug)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,16 @@ func lookupIPMerge(host string) (addrs []IP, err error) {
|
||||||
addrsi, err, shared := lookupGroup.Do(host, func() (interface{}, error) {
|
addrsi, err, shared := lookupGroup.Do(host, func() (interface{}, error) {
|
||||||
return lookupIP(host)
|
return lookupIP(host)
|
||||||
})
|
})
|
||||||
|
return lookupIPReturn(addrsi, err, shared)
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookupIPReturn turns the return values from singleflight.Do into
|
||||||
|
// the return values from LookupIP.
|
||||||
|
func lookupIPReturn(addrsi interface{}, err error, shared bool) ([]IP, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
addrs = addrsi.([]IP)
|
addrs := addrsi.([]IP)
|
||||||
if shared {
|
if shared {
|
||||||
clone := make([]IP, len(addrs))
|
clone := make([]IP, len(addrs))
|
||||||
copy(clone, addrs)
|
copy(clone, addrs)
|
||||||
|
|
@ -52,41 +58,40 @@ func lookupIPMerge(host string) (addrs []IP, err error) {
|
||||||
return addrs, nil
|
return addrs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lookupIPDeadline looks up a hostname with a deadline.
|
||||||
func lookupIPDeadline(host string, deadline time.Time) (addrs []IP, err error) {
|
func lookupIPDeadline(host string, deadline time.Time) (addrs []IP, err error) {
|
||||||
if deadline.IsZero() {
|
if deadline.IsZero() {
|
||||||
return lookupIPMerge(host)
|
return lookupIPMerge(host)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bradfitz): consider pushing the deadline down into the
|
// We could push the deadline down into the name resolution
|
||||||
// name resolution functions. But that involves fixing it for
|
// functions. However, the most commonly used implementation
|
||||||
// the native Go resolver, cgo, Windows, etc.
|
// calls getaddrinfo, which has no timeout.
|
||||||
//
|
|
||||||
// In the meantime, just use a goroutine. Most users affected
|
|
||||||
// by http://golang.org/issue/2631 are due to TCP connections
|
|
||||||
// to unresponsive hosts, not DNS.
|
|
||||||
timeout := deadline.Sub(time.Now())
|
timeout := deadline.Sub(time.Now())
|
||||||
if timeout <= 0 {
|
if timeout <= 0 {
|
||||||
err = errTimeout
|
return nil, errTimeout
|
||||||
return
|
|
||||||
}
|
}
|
||||||
t := time.NewTimer(timeout)
|
t := time.NewTimer(timeout)
|
||||||
defer t.Stop()
|
defer t.Stop()
|
||||||
type res struct {
|
|
||||||
addrs []IP
|
ch := lookupGroup.DoChan(host, func() (interface{}, error) {
|
||||||
err error
|
return lookupIP(host)
|
||||||
}
|
})
|
||||||
resc := make(chan res, 1)
|
|
||||||
go func() {
|
|
||||||
a, err := lookupIPMerge(host)
|
|
||||||
resc <- res{a, err}
|
|
||||||
}()
|
|
||||||
select {
|
select {
|
||||||
case <-t.C:
|
case <-t.C:
|
||||||
err = errTimeout
|
// The DNS lookup timed out for some reason. Force
|
||||||
case r := <-resc:
|
// future requests to start the DNS lookup again
|
||||||
addrs, err = r.addrs, r.err
|
// rather than waiting for the current lookup to
|
||||||
|
// complete. See issue 8602.
|
||||||
|
lookupGroup.Forget(host)
|
||||||
|
|
||||||
|
return nil, errTimeout
|
||||||
|
|
||||||
|
case r := <-ch:
|
||||||
|
return lookupIPReturn(r.v, r.err, r.shared)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookupPort looks up the port for the given network and service.
|
// LookupPort looks up the port for the given network and service.
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,18 @@ import "sync"
|
||||||
|
|
||||||
// call is an in-flight or completed singleflight.Do call
|
// call is an in-flight or completed singleflight.Do call
|
||||||
type call struct {
|
type call struct {
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
val interface{}
|
|
||||||
err error
|
// These fields are written once before the WaitGroup is done
|
||||||
dups int
|
// and are only read after the WaitGroup is done.
|
||||||
|
val interface{}
|
||||||
|
err error
|
||||||
|
|
||||||
|
// These fields are read and written with the singleflight
|
||||||
|
// mutex held before the WaitGroup is done, and are read but
|
||||||
|
// not written after the WaitGroup is done.
|
||||||
|
dups int
|
||||||
|
chans []chan<- singleflightResult
|
||||||
}
|
}
|
||||||
|
|
||||||
// singleflight represents a class of work and forms a namespace in
|
// singleflight represents a class of work and forms a namespace in
|
||||||
|
|
@ -21,6 +29,14 @@ type singleflight struct {
|
||||||
m map[string]*call // lazily initialized
|
m map[string]*call // lazily initialized
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// singleflightResult holds the results of Do, so they can be passed
|
||||||
|
// on a channel.
|
||||||
|
type singleflightResult struct {
|
||||||
|
v interface{}
|
||||||
|
err error
|
||||||
|
shared bool
|
||||||
|
}
|
||||||
|
|
||||||
// Do executes and returns the results of the given function, making
|
// Do executes and returns the results of the given function, making
|
||||||
// sure that only one execution is in-flight for a given key at a
|
// sure that only one execution is in-flight for a given key at a
|
||||||
// time. If a duplicate comes in, the duplicate caller waits for the
|
// time. If a duplicate comes in, the duplicate caller waits for the
|
||||||
|
|
@ -42,12 +58,52 @@ func (g *singleflight) Do(key string, fn func() (interface{}, error)) (v interfa
|
||||||
g.m[key] = c
|
g.m[key] = c
|
||||||
g.mu.Unlock()
|
g.mu.Unlock()
|
||||||
|
|
||||||
|
g.doCall(c, key, fn)
|
||||||
|
return c.val, c.err, c.dups > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// DoChan is like Do but returns a channel that will receive the
|
||||||
|
// results when they are ready.
|
||||||
|
func (g *singleflight) DoChan(key string, fn func() (interface{}, error)) <-chan singleflightResult {
|
||||||
|
ch := make(chan singleflightResult, 1)
|
||||||
|
g.mu.Lock()
|
||||||
|
if g.m == nil {
|
||||||
|
g.m = make(map[string]*call)
|
||||||
|
}
|
||||||
|
if c, ok := g.m[key]; ok {
|
||||||
|
c.dups++
|
||||||
|
c.chans = append(c.chans, ch)
|
||||||
|
g.mu.Unlock()
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
c := &call{chans: []chan<- singleflightResult{ch}}
|
||||||
|
c.wg.Add(1)
|
||||||
|
g.m[key] = c
|
||||||
|
g.mu.Unlock()
|
||||||
|
|
||||||
|
go g.doCall(c, key, fn)
|
||||||
|
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
// doCall handles the single call for a key.
|
||||||
|
func (g *singleflight) doCall(c *call, key string, fn func() (interface{}, error)) {
|
||||||
c.val, c.err = fn()
|
c.val, c.err = fn()
|
||||||
c.wg.Done()
|
c.wg.Done()
|
||||||
|
|
||||||
|
g.mu.Lock()
|
||||||
|
delete(g.m, key)
|
||||||
|
for _, ch := range c.chans {
|
||||||
|
ch <- singleflightResult{c.val, c.err, c.dups > 0}
|
||||||
|
}
|
||||||
|
g.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forget tells the singleflight to forget about a key. Future calls
|
||||||
|
// to Do for this key will call the function rather than waiting for
|
||||||
|
// an earlier call to complete.
|
||||||
|
func (g *singleflight) Forget(key string) {
|
||||||
g.mu.Lock()
|
g.mu.Lock()
|
||||||
delete(g.m, key)
|
delete(g.m, key)
|
||||||
g.mu.Unlock()
|
g.mu.Unlock()
|
||||||
|
|
||||||
return c.val, c.err, c.dups > 0
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,10 +84,13 @@ func symtabinit() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// file table follows ftab.
|
// The ftab ends with a half functab consisting only of
|
||||||
|
// 'entry', followed by a uint32 giving the pcln-relative
|
||||||
|
// offset of the file table.
|
||||||
sp = (*sliceStruct)(unsafe.Pointer(&filetab))
|
sp = (*sliceStruct)(unsafe.Pointer(&filetab))
|
||||||
p = unsafe.Pointer(add(unsafe.Pointer(pcln), ftab[nftab].funcoff))
|
end := unsafe.Pointer(&ftab[nftab].funcoff) // just beyond ftab
|
||||||
sp.array = unsafe.Pointer(add(unsafe.Pointer(pcln), ftab[nftab].funcoff))
|
fileoffset := *(*uint32)(end)
|
||||||
|
sp.array = unsafe.Pointer(&pclntable[fileoffset])
|
||||||
// length is in first element of array.
|
// length is in first element of array.
|
||||||
// set len to 1 so we can get first element.
|
// set len to 1 so we can get first element.
|
||||||
sp.len = 1
|
sp.len = 1
|
||||||
|
|
@ -224,7 +227,7 @@ func funcline(f *_func, targetpc uintptr, file *string) int32 {
|
||||||
func funcspdelta(f *_func, targetpc uintptr) int32 {
|
func funcspdelta(f *_func, targetpc uintptr) int32 {
|
||||||
x := pcvalue(f, f.pcsp, targetpc, true)
|
x := pcvalue(f, f.pcsp, targetpc, true)
|
||||||
if x&(ptrSize-1) != 0 {
|
if x&(ptrSize-1) != 0 {
|
||||||
print("invalid spdelta ", f.pcsp, " ", x, "\n")
|
print("invalid spdelta ", hex(f.entry), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n")
|
||||||
}
|
}
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Package unsafe contains operations that step around the type safety of Go programs.
|
Package unsafe contains operations that step around the type safety of Go programs.
|
||||||
|
|
||||||
|
Packages that import unsafe may be non-portable and are not protected by the
|
||||||
|
Go 1 compatibility guidelines.
|
||||||
*/
|
*/
|
||||||
package unsafe
|
package unsafe
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
// run
|
||||||
|
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
// Some uses of zeroed constants in non-assignment
|
||||||
|
// expressions broke with our more aggressive zeroing
|
||||||
|
// of assignments (internal compiler errors).
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func f1() {
|
||||||
|
type T [2]int
|
||||||
|
p := T{0, 1}
|
||||||
|
switch p {
|
||||||
|
case T{0, 0}:
|
||||||
|
panic("wrong1")
|
||||||
|
case T{0, 1}:
|
||||||
|
// ok
|
||||||
|
default:
|
||||||
|
panic("wrong2")
|
||||||
|
}
|
||||||
|
|
||||||
|
if p == (T{0, 0}) {
|
||||||
|
panic("wrong3")
|
||||||
|
} else if p == (T{0, 1}) {
|
||||||
|
// ok
|
||||||
|
} else {
|
||||||
|
panic("wrong4")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
V int
|
||||||
|
}
|
||||||
|
|
||||||
|
var X = T{}.V
|
||||||
|
|
||||||
|
func f2() {
|
||||||
|
var x = T{}.V
|
||||||
|
if x != 0 {
|
||||||
|
panic("wrongx")
|
||||||
|
}
|
||||||
|
if X != 0 {
|
||||||
|
panic("wrongX")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f1()
|
||||||
|
f2()
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue