On Wed, Jan 12, 2022 at 3:01 AM E Z <legend...@gmail.com> wrote:

> Thank you very much.
>
> I understand that we can use context.Context to resolve the network
> blocking problem in long-running function if the network library support
> passing a context parameter.
>
> But for the CPU-bound code,  Is the following implementation mentioned by
> axel the only way to make a function exit earlier?
>

It's not the only way, but it's the way I'd generally recommend.
Universally using `context.Context` to signal cancellation solves exactly
the problem you where having. Specifically,

> The above code is executing in a goroutine, if I want to cancel this
goroutine, I can send a signal to task.channel, but the signal only can be
retrieved after the task.task.Run is finished, it may be a long time, such
as 5 mins.

If `task.task.Run` takes a `context.Context`, it can exit sooner than after
5 minutes. If it takes that long because it does remote requests, it can
propagate the Context itself. If it is CPU-bound, it can check if the
Context was cancelled, say, every 1000 iterations (or whatever. What's a
reasonable number depends heavily on what it's doing).

But, yes, for such a CPU-bound task, actively checking if it was cancelled
via a mechanism like a Context is the only way to be aborted.

For example, goroutine is executing a task to update a DNS record and then
> wait some time until the DNS record takes effect in some name servers.  It
> may take some seconds even minutes to make the DNS record take effect in
> the name server.
>

To be clear, this is not a CPU-bound process. Updating the DNS record is
either a network request/IPC. The waiting is then a loop like

for {
    select {
    case <-ctx.Done():
        return ctx.Err()
    case <-time.After(time.Second()): // simplistic, you'd likely want some
jitter and/or exponential backoff here
        if recordHasChanged(ctx) { // network request to check if the DNS
record has changed - takes a Context, as it's a network request
            return nil
        }
    }
}

This will spend most of its time sleeping.

A CPU-bound task is something like a diff-operation, which is just an
algorithm that can be very slow for large inputs, just because it has a lot
of work to churn through.

In this case, seems I can't cancel the running goroutine except that we add
> the above select at every for loop or wait timer, or  I change the design
> to split these time-consuming operations into different goroutine. Both
> seem not so good.
>

I don't understand why you think this is not good. It seems perfectly
reasonable code. But yes, it's what you have to do. Go has no way to
asynchronously stop code, you need to manually cancel. And context.Context
gives a universal mechanism to do that, which I would recommend using for
that.


>
> On Tuesday, January 11, 2022 at 1:04:15 PM UTC-8 Ian Lance Taylor wrote:
>
>> On Tue, Jan 11, 2022 at 12:15 PM 'Axel Wagner' via golang-nuts
>> <golan...@googlegroups.com> wrote:
>> >
>> > The best way to do this is to plumb a context.Context through all
>> long-running functions - in particular, anything talking to the network.
>> > Most RPC and network frameworks provide a way to pass a Context, so
>> consistently doing this will more or less transparently cancel your
>> business logic ASAP.
>> > For purely CPU bound code, this is a bit more awkward, because you
>> indeed have to intersperse code like
>> > select {
>> > case <-ctx.Done():
>> > return ctx.Err()
>> > default:
>> > }
>> > to make the code return early. But that should be relatively rare.
>>
>> Yes. See also https://go.dev/blog/context .
>>
>> Ian
>>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/d1898f67-d1e0-4276-af92-016b82866de4n%40googlegroups.com
> <https://groups.google.com/d/msgid/golang-nuts/d1898f67-d1e0-4276-af92-016b82866de4n%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAEkBMfG-ucbuosT25i%2Bbpd81EQp-mj_wksgHumgQxbgRfrgsfQ%40mail.gmail.com.

Reply via email to