在Hack中将Awaitables的集合转换为按时间排序的AsyncGenerator

时间:2016-12-30 23:16:11

标签: asynchronous async-await generator hacklang

我正在尝试使用Hack异步实现Rx流/可观察的合并,并且标题描述了核心步骤。此步骤的代码版本如下所示:

#include <stdio.h>
#include <math.h>
#include <stdint.h>

#ifndef DBL_EPSILON
#define DBL_EPSILON 2.2204460492503131e-16
#endif

float power(float a, float b)
{
    int isNegative = b < 0.0;


    float res = 1;

    for (int i = 0; i < fabs(b); ++i)
    {
        res *= a;
    }

    return isNegative ? 1 / res : res;
}

double root(int n, double x)
{
    double d, r = 1;
    if (!x)
    {
        return 0;
    }

    if (n < 1 || (x < 0 && !(n&1)))
    {
        return 0.0 / 0.0;
    }

    do
    {
        d = (x / power(r, n - 1) - r) / n;
        r += d;
    } while (d >= DBL_EPSILON * 10 || d <= -DBL_EPSILON * 10);

    return r;
}


long gcd(long a, long b)
{
    return b == 0 ? a : gcd(b, a % b);
}

void frac(float value, long* numerator, long* denominator)
{
    double integral = floor(value);
    double frac = value - integral;
    const long precision = 1000000;

    long commonDenominator = gcd(round(frac * precision), precision);
    *numerator = round(frac * precision) / commonDenominator;
    *denominator = precision / commonDenominator;

    *numerator = *numerator + (integral * *denominator);
}

int main() {

    float base = 2;
    float exp = 2.5;


    printf("FIRST: %f\n", pow(base, exp));

    //OR

    //A ^ (B/C) is the same as CthRoot(A ^ B)
    long num = 0;
    long den = 0;
    frac(exp, &num, &den);

    printf("SECOND: %f\n", root(den, power(base, num)));


    base = 3;
    exp = 2.7;

    printf("THIRD: %f\n", pow(base, exp));

    //OR:

    num = 0;
    den = 0;
    frac(exp, &num, &den);

    printf("FOURTH: %f\n", root(den, power(base, num)));

    return 0;
}

然而,在仔细研究之后,我认为我无法编写已加星标的<?hh // strict async function foo(Awaitable<Iterable<T>> $collection): Awaitable<void> { $ordered_generator = async_collection_to_gen($collection) // (**) foreach($ordered_generator await as $v) { // do something with each awaited value in the time-order they are resolved } } 函数。我发现在某些时候,我尝试过的实现需要类似于JS (**)的功能,它在Promises解析/拒绝的第一个集合时解析。但是,所有Hack's Awaitable collection helpers都会创建一个等待完全已解决的集合。此外,Hack不允许Promise.race来自await的{​​{1}}异步调用,我也认为这是必要的。

对任何人的知识都有可能吗?

1 个答案:

答案 0 :(得分:0)

这实际上是可能的!我挖了一下,偶然发现了a fork of asio-utilities @jano实施string MyVariable_grabbed_previously = "version:15.3, Date:2016/12/10"; bool Version_variable = true; wstring UserAgent; ... if (Version_variable) { UserAgent = s2ws("my custom UA & " + MyVariable_grabbed_previously); } else { UserAgent = L"my custom UA"; } /* Alternatively: UserAgent = L"my custom UA"; if (Version_variable) { UserAgent += (L" & " + s2ws(MyVariable_grabbed_previously)); } */ hSession = WinHttpOpen(UserAgent.c_str(), WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); 课程。 See PR for usage.完全按照我的意愿行事。

事实证明,有一个名为AsyncPoll的{​​{1}} AwaitableConditionWaitHandle种方法*可由任何上下文调用so long as the underlying WaitHandle hasn't expired yet) ,强制succeed解析传递的值。

我对代码进行了严格的审视,并且在其下面,它通过fail允许的连续ConditionWaitHandle种族来运作。更具体地说,Awaitable的集合通过ConditionWaitHandle(又名Awaitable)进行压缩,其解析速度与最慢的AwaitAllWaitHandles一样慢,然后嵌套在\HH\Asio\v中。等待Awaitable的每个ConditionWaitHandle触发公共Awaitable,结束比赛。重复此过程,直到async function全部解决。

这是使用相同理念的比赛的更紧凑的实现:

ConditionWaitHandle

非常优雅的解决方案,谢谢@jano!

* (承诺/延迟的表象加剧)

我很好奇如何通过Awaitable过早完成与all Awaitables should run to completion的哲学相结合。