On Thu, Jul 5, 2012 at 4:55 AM, Paul Borman <
bor...@google.com> wrote:
>
>
> On Wed, Jul 4, 2012 at 8:09 PM, Jim Whitehead II <
jnwh...@gmail.com> wrote:
>>
>> A process should not need to know
>> anything about its environment or the details of the garbage
>> collector.
>
>
> No, that is not true. You do need to know what gets garbage collected and
> what doesn't (and why). Without doing this you will end up with memory
> leaks. For example, you don not have to close a channel if all references
> to it are garbage collected, the channel then also be garbage collected.
> However, if all references to an open file are garbage collected that file
> is not closed. Garbage collection is a fundamental part of Go and
> understanding that and what it does is important to writing Go programs.
I disagree with you, but we're probably just saying one thing in two
different ways. As a goroutine running in the world, I have links to
the outside world through channels. These channels have different
conventions and meanings, such as the 'quit' channels. I need to know
what my view of that channel is and whether or not I should plan to
wait for a signal on that channel, or broadcast to it when complete. I
don't need to know anything about the other processes that are running
in the system, I just need to know about the connections that I have
to them and the protocols for using those channels.
This can be seen trivially: I need to know whether to read or write on
a channel or I may introduce deadlock. This has to be baked into any
program that is using channels and doesn't require details of the rest
of the system (environment) in order for me to write my individual
goroutine procedure. Perhaps this is an oversimplification, but it's
how I view and write my programs.
> As for the environment, I can't possibly image what you mean by that. A
> program that has no connection to its environment has no I/O, by definition,
> and hence cannot report at all what it has done. Understanding the
> environment it runs in is often very critical to its function.
Ah, I see you haven't read the 1978 CSP paper, where Hoare introduces
the send and receive operations purposely to indicate I/O, or
connections with an environment. I am viewing the world through that
lens and that is how I write my programs.
When you create a function, you understand what the parameters and
return values are supposed to be. You might even indicate this to a
consumer of your program using documentation, comments, or other
conventions. I see concurrency as simply being an extension of that. I
give my channels good names, and talk about how they are being used.
"Read messages from the 'in' channel, producing a response on the
'out' channel for each before proceeding to the next one. If a message
is received on the 'quit' channel, then finish processing any
outstanding requests, but stop listening for messages on 'in'."
When I am designing this goroutine procedure, I can limit myself to
operating within the realms of this definition the same as if I was
writing a conventional function. I don't have to be concerned with the
fact that I'm not listening to ONE producer on a single channel, but
that I'm listening to TWO producers that share my input channel. I
just know my job and I do it.
Of course the person doing the programmer needs to understand the
connections between the processes-- they're the one who puts them
together. That's a consequence of the Go model that differs from the
CSP model, since we communicate over explicit first-class channels
rather than by addressing our messages to specific process names. I
can write my programs as simple sequential programs that communicate
using the resources they are given.
> The OP's suggestion is interesting and I can see some merit in it, however,
> only for garbage collecting when all writers have disappeared as collecting
> is akin to closing and there have been many discussions about the dark
> horrors of readers closing channel.
This is where I think it falls apart. It ruins the explicit nature of
Go by introducing behaviour that winds up being dangerously close to
"exceptional circumstances". But perhaps I just need to better
understand the use-case here. If we're talking about the channel end
being close()-ed when the other end is collected, then I don't know
that I would like those semantics.
> What would this code do?
>
> <- make(chan struct{})
That code to be indicates a deadlocked portion of code. It's a bug.
> I used to use that before I learned to use select{}.
>
> -Paul
I just happen to believe the explicit nature of the current system
fits well with the language and gives us both power and clarity. I
understand the OPs permise, but I don't believe the cost incurred is
worth losing that clarity.
- Jim