153 lines
6.3 KiB
Nim
153 lines
6.3 KiB
Nim
## Compile-time configuration options for chronos that control the availability
|
|
## of various strictness and debuggability options. In general, debug helpers
|
|
## are enabled when `debug` is defined while strictness options are introduced
|
|
## in transition periods leading up to a breaking release that starts enforcing
|
|
## them and removes the option.
|
|
##
|
|
## `chronosPreviewV4` is a preview flag to enable v4 semantics - in particular,
|
|
## it enables strict exception checking and disables parts of the deprecated
|
|
## API and other changes being prepared for the upcoming release
|
|
##
|
|
## `chronosDebug` can be defined to enable several debugging helpers that come
|
|
## with a runtime cost - it is recommeneded to not enable these in production
|
|
## code.
|
|
##
|
|
## In this file we also declare feature flags starting with `chronosHas...` -
|
|
## these constants are declared when a feature exists in a particular release -
|
|
## each flag is declared as an integer starting at 0 during experimental
|
|
## development, 1 when feature complete and higher numbers when significant
|
|
## functionality has been added. If a feature ends up being removed (or changed
|
|
## in a backwards-incompatible way), the feature flag will be removed or renamed
|
|
## also - you can use `when declared(chronosHasXxx): when chronosHasXxx >= N:`
|
|
## to require a particular version.
|
|
const
|
|
chronosHandleException* {.booldefine.}: bool = false
|
|
## Remap `Exception` to `AsyncExceptionError` for all `async` functions.
|
|
##
|
|
## This modes provides backwards compatibility when using functions with
|
|
## inaccurate `{.raises.}` effects such as unannotated forward declarations,
|
|
## methods and `proc` types - it is recommened to annotate such code
|
|
## explicitly as the `Exception` handling mode may introduce surprising
|
|
## behavior in exception handlers, should `Exception` actually be raised.
|
|
##
|
|
## The setting provides the default for the per-function-based
|
|
## `handleException` parameter which has precedence over this global setting.
|
|
##
|
|
## `Exception` handling may be removed in future chronos versions.
|
|
|
|
chronosStrictFutureAccess* {.booldefine.}: bool = defined(chronosPreviewV4)
|
|
|
|
chronosStackTrace* {.booldefine.}: bool = defined(chronosDebug)
|
|
## Include stack traces in futures for creation and completion points
|
|
|
|
chronosFutureId* {.booldefine.}: bool = defined(chronosDebug)
|
|
## Generate a unique `id` for every future - when disabled, the address of
|
|
## the future will be used instead
|
|
|
|
chronosFutureTracking* {.booldefine.}: bool = defined(chronosDebug)
|
|
## Keep track of all pending futures and allow iterating over them -
|
|
## useful for detecting hung tasks
|
|
|
|
chronosDumpAsync* {.booldefine.}: bool = defined(nimDumpAsync)
|
|
## Print code generated by {.async.} transformation
|
|
|
|
chronosProcShell* {.strdefine.}: string =
|
|
when defined(windows):
|
|
"cmd.exe"
|
|
else:
|
|
when defined(android):
|
|
"/system/bin/sh"
|
|
else:
|
|
"/bin/sh"
|
|
## Default shell binary path.
|
|
##
|
|
## The shell is used as command for command line when process started
|
|
## using `AsyncProcessOption.EvalCommand` and API calls such as
|
|
## ``execCommand(command)`` and ``execCommandEx(command)``.
|
|
|
|
chronosEventsCount* {.intdefine.} = 64
|
|
## Number of OS poll events retrieved by syscall (epoll, kqueue, poll).
|
|
|
|
chronosInitialSize* {.intdefine.} = 64
|
|
## Initial size of Selector[T]'s array of file descriptors.
|
|
|
|
chronosEventEngine* {.strdefine.}: string =
|
|
when defined(nimdoc):
|
|
""
|
|
elif defined(linux) and not(defined(android) or defined(emscripten)):
|
|
"epoll"
|
|
elif defined(macosx) or defined(macos) or defined(ios) or
|
|
defined(freebsd) or defined(netbsd) or defined(openbsd) or
|
|
defined(dragonfly):
|
|
"kqueue"
|
|
elif defined(android) or defined(emscripten):
|
|
"poll"
|
|
elif defined(posix):
|
|
"poll"
|
|
else:
|
|
""
|
|
## OS polling engine type which is going to be used by chronos.
|
|
|
|
chronosHasRaises* = 0
|
|
## raises effect support via `async: (raises: [])`
|
|
|
|
when defined(chronosStrictException):
|
|
{.warning: "-d:chronosStrictException has been deprecated in favor of handleException".}
|
|
# In chronos v3, this setting was used as the opposite of
|
|
# `chronosHandleException` - the setting is deprecated to encourage
|
|
# migration to the new mode.
|
|
|
|
when defined(debug) or defined(chronosConfig):
|
|
import std/macros
|
|
|
|
static:
|
|
hint("Chronos configuration:")
|
|
template printOption(name: string, value: untyped) =
|
|
hint(name & ": " & $value)
|
|
printOption("chronosHandleException", chronosHandleException)
|
|
printOption("chronosStackTrace", chronosStackTrace)
|
|
printOption("chronosFutureId", chronosFutureId)
|
|
printOption("chronosFutureTracking", chronosFutureTracking)
|
|
printOption("chronosDumpAsync", chronosDumpAsync)
|
|
printOption("chronosProcShell", chronosProcShell)
|
|
printOption("chronosEventEngine", chronosEventEngine)
|
|
printOption("chronosEventsCount", chronosEventsCount)
|
|
printOption("chronosInitialSize", chronosInitialSize)
|
|
|
|
|
|
# In nim 1.6, `sink` + local variable + `move` generates the best code for
|
|
# moving a proc parameter into a closure - this only works for closure
|
|
# procedures however - in closure iterators, the parameter is always copied
|
|
# into the closure (!) meaning that non-raw `{.async.}` functions always carry
|
|
# this overhead, sink or no. See usages of chronosMoveSink for examples.
|
|
# In addition, we need to work around https://github.com/nim-lang/Nim/issues/22175
|
|
# which has not been backported to 1.6.
|
|
# Long story short, the workaround is not needed in non-raw {.async.} because
|
|
# a copy of the literal is always made.
|
|
# TODO review the above for 2.0 / 2.0+refc
|
|
type
|
|
SeqHeader = object
|
|
length, reserved: int
|
|
|
|
proc isLiteral(s: string): bool {.inline.} =
|
|
when defined(gcOrc) or defined(gcArc):
|
|
false
|
|
else:
|
|
s.len > 0 and (cast[ptr SeqHeader](s).reserved and (1 shl (sizeof(int) * 8 - 2))) != 0
|
|
|
|
proc isLiteral[T](s: seq[T]): bool {.inline.} =
|
|
when defined(gcOrc) or defined(gcArc):
|
|
false
|
|
else:
|
|
s.len > 0 and (cast[ptr SeqHeader](s).reserved and (1 shl (sizeof(int) * 8 - 2))) != 0
|
|
|
|
template chronosMoveSink*(val: auto): untyped =
|
|
bind isLiteral
|
|
when not (defined(gcOrc) or defined(gcArc)) and val is seq|string:
|
|
if isLiteral(val):
|
|
val
|
|
else:
|
|
move(val)
|
|
else:
|
|
move(val)
|