Left: | ||
Right: |
LEFT | RIGHT |
---|---|
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 Loading... | |
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 Loading... | |
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 } |
LEFT | RIGHT |