aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/vlib/context/deadline.v
diff options
context:
space:
mode:
Diffstat (limited to 'v_windows/v/vlib/context/deadline.v')
-rw-r--r--v_windows/v/vlib/context/deadline.v94
1 files changed, 94 insertions, 0 deletions
diff --git a/v_windows/v/vlib/context/deadline.v b/v_windows/v/vlib/context/deadline.v
new file mode 100644
index 0000000..43fd056
--- /dev/null
+++ b/v_windows/v/vlib/context/deadline.v
@@ -0,0 +1,94 @@
+// This module defines the Context type, which carries deadlines, cancellation signals,
+// and other request-scoped values across API boundaries and between processes.
+// Based off: https://github.com/golang/go/tree/master/src/context
+// Last commit: https://github.com/golang/go/commit/52bf14e0e8bdcd73f1ddfb0c4a1d0200097d3ba2
+module context
+
+import rand
+import time
+
+// A TimerContext carries a timer and a deadline. It embeds a CancelContext to
+// implement done and err. It implements cancel by stopping its timer then
+// delegating to CancelContext.cancel
+pub struct TimerContext {
+ id string
+mut:
+ cancel_ctx CancelContext
+ deadline time.Time
+}
+
+// with_deadline returns a copy of the parent context with the deadline adjusted
+// to be no later than d. If the parent's deadline is already earlier than d,
+// with_deadline(parent, d) is semantically equivalent to parent. The returned
+// context's Done channel is closed when the deadline expires, when the returned
+// cancel function is called, or when the parent context's Done channel is
+// closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+pub fn with_deadline(parent Context, d time.Time) Context {
+ id := rand.uuid_v4()
+ if cur := parent.deadline() {
+ if cur < d {
+ // The current deadline is already sooner than the new one.
+ return with_cancel(parent)
+ }
+ }
+ cancel_ctx := new_cancel_context(parent)
+ mut ctx := &TimerContext{
+ cancel_ctx: cancel_ctx
+ deadline: d
+ id: id
+ }
+ propagate_cancel(parent, mut ctx)
+ dur := d - time.now()
+ if dur.nanoseconds() <= 0 {
+ ctx.cancel(true, deadline_exceeded) // deadline has already passed
+ return Context(ctx)
+ }
+
+ if ctx.err() is none {
+ go fn (mut ctx TimerContext, dur time.Duration) {
+ time.sleep(dur)
+ ctx.cancel(true, deadline_exceeded)
+ }(mut ctx, dur)
+ }
+ return Context(ctx)
+}
+
+// with_timeout returns with_deadline(parent, time.now().add(timeout)).
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete
+pub fn with_timeout(parent Context, timeout time.Duration) Context {
+ return with_deadline(parent, time.now().add(timeout))
+}
+
+pub fn (ctx TimerContext) deadline() ?time.Time {
+ return ctx.deadline
+}
+
+pub fn (mut ctx TimerContext) done() chan int {
+ return ctx.cancel_ctx.done()
+}
+
+pub fn (mut ctx TimerContext) err() IError {
+ return ctx.cancel_ctx.err()
+}
+
+pub fn (ctx TimerContext) value(key string) ?voidptr {
+ return ctx.cancel_ctx.value(key)
+}
+
+pub fn (mut ctx TimerContext) cancel(remove_from_parent bool, err IError) {
+ ctx.cancel_ctx.cancel(false, err)
+ if remove_from_parent {
+ // Remove this TimerContext from its parent CancelContext's children.
+ remove_child(ctx.cancel_ctx.context, ctx)
+ }
+}
+
+pub fn (ctx TimerContext) str() string {
+ return context_name(ctx.cancel_ctx.context) + '.with_deadline(' + ctx.deadline.str() + ' [' +
+ (time.now() - ctx.deadline).str() + '])'
+}