Commit e5687f2f authored by Kirill Smelkov's avatar Kirill Smelkov

context: Don't hardcode that contexts are always done with canceled error

We'll need to mark contexts that miss their deadline with
deadlineExceeded error in a follow-up patch.

In this patch: transform _BaseCtx._cancel to accept an error with which
a context has to be canceled, but for now always use canceled in places
where _cancel is called.
parent 58ba1765
...@@ -71,7 +71,7 @@ deadlineExceeded = RuntimeError("deadline exceeded") ...@@ -71,7 +71,7 @@ deadlineExceeded = RuntimeError("deadline exceeded")
# the context is no longer needed. # the context is no longer needed.
def with_cancel(parent): # -> ctx, cancel def with_cancel(parent): # -> ctx, cancel
ctx = _CancelCtx(parent) ctx = _CancelCtx(parent)
return ctx, ctx._cancel return ctx, lambda: ctx._cancel(canceled)
# with_value creates new context with key=value. # with_value creates new context with key=value.
# #
...@@ -95,7 +95,7 @@ def with_value(parent, key, value): # -> ctx ...@@ -95,7 +95,7 @@ def with_value(parent, key, value): # -> ctx
# https://godoc.org/lab.nexedi.com/kirr/go123/xcontext#hdr-Merging_contexts # https://godoc.org/lab.nexedi.com/kirr/go123/xcontext#hdr-Merging_contexts
def merge(parent1, parent2): # -> ctx, cancel def merge(parent1, parent2): # -> ctx, cancel
ctx = _CancelCtx(parent1, parent2) ctx = _CancelCtx(parent1, parent2)
return ctx, ctx._cancel return ctx, lambda: ctx._cancel(canceled)
# -------- # --------
...@@ -150,17 +150,17 @@ class _BaseCtx(object): ...@@ -150,17 +150,17 @@ class _BaseCtx(object):
return None return None
# _cancel cancels ctx and its children. # _cancel cancels ctx and its children.
def _cancel(ctx): def _cancel(ctx, err):
return ctx._cancelFrom(None) return ctx._cancelFrom(None, err)
# _cancelFrom cancels ctx and its children. # _cancelFrom cancels ctx and its children.
# if cancelFrom != None it indicates which ctx parent cancellation was the cause for ctx cancel. # if cancelFrom != None it indicates which ctx parent cancellation was the cause for ctx cancel.
def _cancelFrom(ctx, cancelFrom): def _cancelFrom(ctx, cancelFrom, err):
with ctx._mu: with ctx._mu:
if ctx._err is not None: if ctx._err is not None:
return # already canceled return # already canceled
ctx._err = canceled ctx._err = err
children = ctx._children; ctx._children = set() children = ctx._children; ctx._children = set()
if ctx._done is not None: if ctx._done is not None:
...@@ -177,13 +177,13 @@ class _BaseCtx(object): ...@@ -177,13 +177,13 @@ class _BaseCtx(object):
# propagate cancel to children # propagate cancel to children
for child in children: for child in children:
child._cancelFrom(ctx) child._cancelFrom(ctx, err)
# propagateCancel establishes setup so that whenever a parent is canceled, # propagateCancel establishes setup so that whenever a parent is canceled,
# ctx and its children are canceled too. # ctx and its children are canceled too.
def _propagateCancel(ctx): def _propagateCancel(ctx):
pdonev = [] # !nilchan .done() for foreign contexts pforeignv = [] # parents with !nilchan .done() for foreign contexts
for parent in ctx._parentv: for parent in ctx._parentv:
# if parent can never be canceled (e.g. it is background) - we # if parent can never be canceled (e.g. it is background) - we
# don't need to propagate cancel from it. # don't need to propagate cancel from it.
...@@ -195,27 +195,27 @@ class _BaseCtx(object): ...@@ -195,27 +195,27 @@ class _BaseCtx(object):
if isinstance(parent, _BaseCtx): if isinstance(parent, _BaseCtx):
with parent._mu: with parent._mu:
if parent._err is not None: if parent._err is not None:
ctx._cancel() ctx._cancel(parent._err)
else: else:
parent._children.add(ctx) parent._children.add(ctx)
else: else:
if _ready(pdone): if _ready(pdone):
ctx._cancel() ctx._cancel(parent.err())
else: else:
pdonev.append(pdone) pforeignv.append(parent)
if len(pdonev) == 0: if len(pforeignv) == 0:
return return
# there are some foreign contexts to propagate cancel from # there are some foreign contexts to propagate cancel from
def _(): def _():
_, _rx = select( _, _rx = select(
ctx._done.recv, # 0 ctx._done.recv, # 0
*[_.recv for _ in pdonev] # 1 + ... *[_.done().recv for _ in pforeignv] # 1 + ...
) )
# 0. nothing - already canceled # 0. nothing - already canceled
if _ > 0: if _ > 0:
ctx._cancel() ctx._cancel(pforeignv[_-1].err())
go(_) go(_)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment