Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(128)

Delta Between Two Patch Sets: src/pkg/reflect/value.go

Issue 6498078: code review 6498078: reflect: add Select (Closed)
Left Patch Set: diff -r e3fce06291ec https://code.google.com/p/go/ Created 11 years, 6 months ago
Right Patch Set: diff -r 6cfab3a0935e https://go.googlecode.com/hg/ Created 11 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/reflect/type.go ('k') | src/pkg/runtime/chan.c » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package reflect 5 package reflect
6 6
7 import ( 7 import (
8 "math" 8 "math"
9 "runtime" 9 "runtime"
10 "strconv" 10 "strconv"
(...skipping 1603 matching lines...) Expand 10 before | Expand all | Expand 10 after
1614 } else { 1614 } else {
1615 sa = unsafe.Pointer((*SliceHeader)(src.val).Data) 1615 sa = unsafe.Pointer((*SliceHeader)(src.val).Data)
1616 } 1616 }
1617 memmove(da, sa, uintptr(n)*de.Size()) 1617 memmove(da, sa, uintptr(n)*de.Size())
1618 return n 1618 return n
1619 } 1619 }
1620 1620
1621 // A runtimeSelect is a single case passed to rselect. 1621 // A runtimeSelect is a single case passed to rselect.
1622 // This must match ../runtime/chan.c:/runtimeSelect 1622 // This must match ../runtime/chan.c:/runtimeSelect
1623 type runtimeSelect struct { 1623 type runtimeSelect struct {
1624 » dir uintptr // 0, SendDir, or RecvDir 1624 » dir uintptr // 0, SendDir, or RecvDir
1625 » typ *chanType // channel type 1625 » typ *runtimeType // channel type
1626 » ch iword // interface word for channel 1626 » ch iword // interface word for channel
1627 » val iword // interface word for value (for SendDir) 1627 » val iword // interface word for value (for SendDir)
1628 } 1628 }
1629 1629
1630 // rselect runs a select. It returns the index of the chosen case, 1630 // rselect runs a select. It returns the index of the chosen case,
1631 // and if the case was a receive, the interface word of the received 1631 // and if the case was a receive, the interface word of the received
1632 // value and the conventional OK bool to indicate whether the receive 1632 // value and the conventional OK bool to indicate whether the receive
1633 // corresponds to a sent value. 1633 // corresponds to a sent value.
1634 func rselect([]runtimeSelect) (chosen int, recv iword, recvOK bool) 1634 func rselect([]runtimeSelect) (chosen int, recv iword, recvOK bool)
1635 1635
1636 // A SelectDir describes the communication direction of a select case. 1636 // A SelectDir describes the communication direction of a select case.
1637 type SelectDir int 1637 type SelectDir int
1638 1638
1639 // NOTE: These values must match ../runtime/chan.c:/SelectDir. 1639 // NOTE: These values must match ../runtime/chan.c:/SelectDir.
1640 1640
1641 const ( 1641 const (
1642 _ SelectDir = iota 1642 _ SelectDir = iota
1643 SelectSend // case Chan <- Send 1643 SelectSend // case Chan <- Send
1644 SelectRecv // case <-Chan: 1644 SelectRecv // case <-Chan:
rog 2012/09/14 07:27:04 nit: if there's a ":" here, it should be on the ot
1645 SelectDefault // default 1645 SelectDefault // default
1646 ) 1646 )
1647 1647
1648 // A SelectCase describes a single case in a select operation. 1648 // A SelectCase describes a single case in a select operation.
1649 // The kind of case depends on Dir, the communication direction. 1649 // The kind of case depends on Dir, the communication direction.
1650 // 1650 //
1651 // If Dir is SelectDefault, the case represents a default case. 1651 // If Dir is SelectDefault, the case represents a default case.
1652 // Chan and Send must be zero Values. 1652 // Chan and Send must be zero Values.
1653 // 1653 //
1654 // If Dir is SelectSend, the case represents a send operation. 1654 // If Dir is SelectSend, the case represents a send operation.
1655 // Normally Chan's underlying value must be a channel, and Send's underlying val ue must be 1655 // Normally Chan's underlying value must be a channel, and Send's underlying val ue must be
1656 // assignable to the channel's element type. As a special case, if Chan is a zer o Value, 1656 // assignable to the channel's element type. As a special case, if Chan is a zer o Value,
1657 // then the case is ignored, and the field Send will also be ignored and may be either zero 1657 // then the case is ignored, and the field Send will also be ignored and may be either zero
rog 2012/09/14 07:27:04 s/the field // ?
1658 // or non-zero. 1658 // or non-zero.
1659 // 1659 //
1660 // If Dir is SelectRecv, the case represents a receive operation. 1660 // If Dir is SelectRecv, the case represents a receive operation.
1661 // Normally Chan's underlying value must be a channel and Send must be a zero Va lue. 1661 // Normally Chan's underlying value must be a channel and Send must be a zero Va lue.
1662 // If Chan is a zero Value, then the case is ignored, but Send must still be a z ero Value. 1662 // If Chan is a zero Value, then the case is ignored, but Send must still be a z ero Value.
1663 // When a receive operation is selected, the received Value is returned by Selec t. 1663 // When a receive operation is selected, the received Value is returned by Selec t.
1664 // 1664 //
1665 type SelectCase struct { 1665 type SelectCase struct {
1666 Dir SelectDir // direction of case 1666 Dir SelectDir // direction of case
1667 Chan Value // channel to use (for send or receive) 1667 Chan Value // channel to use (for send or receive)
1668 Send Value // value to send (for send) 1668 Send Value // value to send (for send)
1669 } 1669 }
1670 1670
1671 // Select executes a select operation described by the list of cases. 1671 // Select executes a select operation described by the list of cases.
1672 // Like the Go select statement, it blocks until one of the cases can 1672 // Like the Go select statement, it blocks until one of the cases can
1673 // proceed and then executes that case. It returns the index of the chosen case 1673 // proceed and then executes that case. It returns the index of the chosen case
1674 // and, if that case was a receive operation, the value received and a 1674 // and, if that case was a receive operation, the value received and a
1675 // boolean indicating whether the value corresponds to a send on the channel 1675 // boolean indicating whether the value corresponds to a send on the channel
1676 // (as opposed to a zero value received because the channel is closed). 1676 // (as opposed to a zero value received because the channel is closed).
1677 func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) { 1677 func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
1678 // NOTE: Do not trust that caller is not modifying cases data underfoot. 1678 // NOTE: Do not trust that caller is not modifying cases data underfoot.
1679 // The range is safe because the caller cannot modify our copy of the le n 1679 // The range is safe because the caller cannot modify our copy of the le n
1680 // and each iteration makes its own copy of the value c. 1680 // and each iteration makes its own copy of the value c.
1681 runcases := make([]runtimeSelect, len(cases)) 1681 runcases := make([]runtimeSelect, len(cases))
1682 haveDefault := false 1682 haveDefault := false
1683 for i, c := range cases { 1683 for i, c := range cases {
1684 rc := &runcases[i] 1684 rc := &runcases[i]
1685 rc.dir = uintptr(c.Dir) 1685 rc.dir = uintptr(c.Dir)
1686 switch c.Dir { 1686 switch c.Dir {
1687 default: 1687 default:
rog 2012/09/14 07:27:04 i still have a soft spot for the idea that the zer
1688 panic("reflect.Select: invalid Dir") 1688 panic("reflect.Select: invalid Dir")
1689 1689
1690 case SelectDefault: // default·· 1690 case SelectDefault: // default··
1691 if haveDefault { 1691 if haveDefault {
1692 panic("reflect.Select: multiple default cases") 1692 panic("reflect.Select: multiple default cases")
1693 } 1693 }
1694 haveDefault = true 1694 haveDefault = true
1695 if c.Chan.IsValid() { 1695 if c.Chan.IsValid() {
1696 panic("reflect.Select: default case has Chan val ue") 1696 panic("reflect.Select: default case has Chan val ue")
1697 } 1697 }
1698 if c.Send.IsValid() { 1698 if c.Send.IsValid() {
1699 panic("reflect.Select: default case has Send val ue") 1699 panic("reflect.Select: default case has Send val ue")
1700 } 1700 }
1701 1701
1702 case SelectSend: 1702 case SelectSend:
1703 ch := c.Chan 1703 ch := c.Chan
1704 if !ch.IsValid() { 1704 if !ch.IsValid() {
1705 break 1705 break
1706 } 1706 }
1707 ch.mustBe(Chan)
1707 ch.mustBeExported() 1708 ch.mustBeExported()
1708 tt := (*chanType)(unsafe.Pointer(ch.typ)) 1709 tt := (*chanType)(unsafe.Pointer(ch.typ))
1709 if ChanDir(tt.dir)&SendDir == 0 { 1710 if ChanDir(tt.dir)&SendDir == 0 {
1710 panic("reflect.Select: SendDir case using recv-o nly channel") 1711 panic("reflect.Select: SendDir case using recv-o nly channel")
1711 } 1712 }
1712 rc.ch = ch.iword() 1713 rc.ch = ch.iword()
1713 » » » rc.typ = tt 1714 » » » rc.typ = tt.runtimeType()
1714 v := c.Send 1715 v := c.Send
1715 if !v.IsValid() { 1716 if !v.IsValid() {
1716 panic("reflect.Select: SendDir case missing Send value") 1717 panic("reflect.Select: SendDir case missing Send value")
1717 } 1718 }
1718 v.mustBeExported() 1719 v.mustBeExported()
1719 v = v.assignTo("reflect.Select", toCommonType(tt.elem), nil) 1720 v = v.assignTo("reflect.Select", toCommonType(tt.elem), nil)
1720 rc.val = v.iword() 1721 rc.val = v.iword()
1721 1722
1722 case SelectRecv: 1723 case SelectRecv:
1723 if c.Send.IsValid() { 1724 if c.Send.IsValid() {
1724 panic("reflect.Select: RecvDir case has Send val ue") 1725 panic("reflect.Select: RecvDir case has Send val ue")
1725 } 1726 }
1726 ch := c.Chan 1727 ch := c.Chan
1727 if !ch.IsValid() { 1728 if !ch.IsValid() {
1728 break 1729 break
1729 } 1730 }
1731 ch.mustBe(Chan)
1730 ch.mustBeExported() 1732 ch.mustBeExported()
1731 tt := (*chanType)(unsafe.Pointer(ch.typ)) 1733 tt := (*chanType)(unsafe.Pointer(ch.typ))
1732 » » » rc.typ = tt 1734 » » » rc.typ = tt.runtimeType()
1733 if ChanDir(tt.dir)&RecvDir == 0 { 1735 if ChanDir(tt.dir)&RecvDir == 0 {
1734 panic("reflect.Select: RecvDir case using send-o nly channel") 1736 panic("reflect.Select: RecvDir case using send-o nly channel")
1735 } 1737 }
1736 rc.ch = ch.iword() 1738 rc.ch = ch.iword()
1737 } 1739 }
1738 } 1740 }
1739 1741
1740 chosen, word, recvOK := rselect(runcases) 1742 chosen, word, recvOK := rselect(runcases)
1741 if runcases[chosen].dir == uintptr(SelectRecv) { 1743 if runcases[chosen].dir == uintptr(SelectRecv) {
1742 » » typ := toCommonType(runcases[chosen].typ.elem) 1744 » » tt := (*chanType)(unsafe.Pointer(toCommonType(runcases[chosen].t yp)))
1745 » » typ := toCommonType(tt.elem)
1743 fl := flag(typ.Kind()) << flagKindShift 1746 fl := flag(typ.Kind()) << flagKindShift
1744 if typ.size > ptrSize { 1747 if typ.size > ptrSize {
1745 fl |= flagIndir 1748 fl |= flagIndir
1746 } 1749 }
1747 recv = Value{typ, unsafe.Pointer(word), fl} 1750 recv = Value{typ, unsafe.Pointer(word), fl}
1748 } 1751 }
1749 return chosen, recv, recvOK 1752 return chosen, recv, recvOK
1750 } 1753 }
1751 1754
1752 /* 1755 /*
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
1938 func escapes(x interface{}) { 1941 func escapes(x interface{}) {
1939 if dummy.b { 1942 if dummy.b {
1940 dummy.x = x 1943 dummy.x = x
1941 } 1944 }
1942 } 1945 }
1943 1946
1944 var dummy struct { 1947 var dummy struct {
1945 b bool 1948 b bool
1946 x interface{} 1949 x interface{}
1947 } 1950 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b