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

Ideate on implementing the Select case in Go. #7620

Closed
kavyasrinet opened this issue Jan 17, 2018 · 0 comments
Closed

Ideate on implementing the Select case in Go. #7620

kavyasrinet opened this issue Jan 17, 2018 · 0 comments

Comments

@kavyasrinet
Copy link

kavyasrinet commented Jan 17, 2018

The select case mechanism in Go Language is an important feature for concurrent programming.
I have tried to understand how the control flow works behind the scene, and adding the step by step execution trail here. I am still trying to understand it, so I will keep updating this as I know more.

There are various steps involved in executing a select block:

  1. Evaluate all the channels involved and all the values that will be sent, from top to bottom and then left to right.
  2. The orders of all the cases for polling are randomized, except for the default case. The default case branch is always put at the last position. It is possible that there are duplicate channels across the cases and orders.
  3. All the involved channels are sorted to avoid deadlock. The first N channels of the sorted result contains all distinct channels (no duplicates). N is the number of involved channels in the select block.
  4. All the channels involved are sorted by the sorted lock orders in the previous step.
  5. Each case in the select block is now polled using a randomized case order, and one of the following actions is taken:
    1. If the operation on the channel results into is sending a value to a closed channel, unlock all channels and panic. Finish.
    2. If the operation on the channel is not blocked:
      1. Perform the channel operation and unlock all channels.
      2. Execute the body of the case, as mentioned in the block. The channel operation might call a blocked go-routine. Finish.
    3. If the case is the default branch: unlock all the channels and execute the body fo default case. Finish.
  6. For each case : push the current go-routine along with the operation involved for that case into the receiving or sending go-routine queue of the involved channel. The current go-routine may be pushed into the queues of the same channel multiple times, in case there are different cases that involve the same channel.
  7. The current go-routine is blocked and all channels are unlocked in the sorted lock orders.
  8. The current go-routine is in blocked status waiting for any of the channel operations to unblock it.
  9. The current go-routine is woken up by a channel operation in another go-routine. The other operation could be one of the following:
    1. A channel close operation.
    2. A channel send/receive operation.
      If it is a channel send/receive operation there has to be a case defined in the select block associated with that operation. During the execution of this operation: the current go-routine will be dequeued from the send/receive go-routine queue of the channel.
  10. All involved channels are locked again according to the sorted lock orders.
  11. The current go-routine is dequeued from the send/receive go-routine queue of the involved channel in each case operation and of the following events happens:
    1. If the current go-routine is woken up by a channel close operation, go back to step 5. (I am not completely sure about this step, need to verify this further).
    2. If the current go-routine is woken up by a channel send/receive operation, the corresponding case of the appropriate send/receive operation has already been discovered in the dequeuing process, so now all the channels are unlocked in the sorted lock orders and the case body of the corresponding case is executed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants