小编Dej*_*avu的帖子

C++ 1z协同线程上下文和协同调度

根据这个最新的C++ TS:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4628.pdf,基于对C#async/await语言支持的理解,我是想知道什么是C++协同程序的"执行上下文"(从C#借来的术语)?

我在Visual C++ 2017 RC中的简单测试代码表明,协同程序似乎总是在线程池线程上执行,并且很少控制应用程序开发人员可以执行协同程序的线程上下文 - 例如,应用程序是否可以强制执行所有协同程序(用编译器生成的状态机代码)只在主线程上执行,而不涉及任何线程池线程?

在C#中,SynchronizationContext是一种指定"上下文"的方法,其中所有协程"一半"(编译器生成的状态机代码)将被发布并执行,如以下文章所示:https://blogs.msdn.microsoft.com/pfxteam/2012/01/20/await-synchronizationcontext-and-console-apps /,而Visual C++ 2017 RC中的当前协程实现似乎总是依赖于并发运行时,它默认执行生成的状态机代码线程池线程.是否有类似的同步上下文概念,用户应用程序可以使用它来将协同程序执行绑定到特定的线程?

另外,在Visual C++ 2017 RC中实现的协同程序的当前默认"调度程序"行为是什么?即1)如何准确指定等待条件?2)当满足等待条件时,谁调用暂停的协程的"下半部分"?

关于C#中任务调度的我(天真)猜测是C#"完全"通过任务继续"实现"等待条件 - 等待条件由TaskCompletionSource拥有的任务合成,并且任何需要等待的代码逻辑将被链接为继续因此,如果满足等待条件,例如,如果从低级网络处理程序接收到完整消息,则它执行TaskCompletionSource.SetValue,它将基础任务转换为已完成状态,从而有效地允许链式连续逻辑开始执行(将任务从先前创建的状态置于就绪状态/列表中) - 在C++协程中,我推测std :: future和std :: promise将被用作类似的机制(std :: future是任务,而std :: promise是TaskCompletionSource,用法也非常相似!) - C++协同调度程序(如果有的话)依赖于某种类似的机制来执行行为吗?

[编辑]:在做了一些进一步的研究后,我能够编写一个非常简单但非常强大的抽象代码,称为awaitable,支持单线程和协作式多任务处理,并具有一个简单的基于thread_local的调度程序,它可以在协同程序的线程上执行协同程序开始了.代码可以在这个github repo中找到:https://github.com/llint/Awaitable

等待是可组合的,它在嵌套级别维护正确的调用排序,并且它具有原始的让步,定时等待和从其他地方设置就绪,并且可以从中导出非常复杂的使用模式(例如只有无限循环协程当某些事件发生时被唤醒),编程模型紧跟C#Task async/await模式.请随时提供反馈.

c++ multithreading coroutine async-await c++-coroutine

12
推荐指数
1
解决办法
2949
查看次数

C++函数类型模板参数推导规则

使用时构建以下代码

clang -Wall main.cpp -o main.o
Run Code Online (Sandbox Code Playgroud)

生成以下诊断(在代码之后):

template <typename F>
void fun(const F& f)
{

}

template <typename F>
void fun(F f)
{

}

double Test(double d) { return d; }

int main(int argc, const char * argv[])
{
    fun(Test);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

诊断:

main.cpp:17:5: error: call to 'fun' is ambiguous
    fun(Test);
    ^~~
main.cpp:2:6: note: candidate function [with F = double (double)]
void fun(const F& f)
     ^
main.cpp:8:6: note: candidate function [with F = double (*)(double)]
void fun(F f)
     ^ …
Run Code Online (Sandbox Code Playgroud)

c++ templates function-pointers

10
推荐指数
2
解决办法
1511
查看次数

为什么std :: reference_wrapper不能默认构造?

我觉得防止std::reference_wrapper<T>默认构造使得它更难使用,即使使用默认构造的reference_wrapper会导致运行时异常.

但是,a reference_wrapper是完全可复制的,因此它的值总是可以更改,那么为什么要阻止它默认使用 null引用呢?它使许多使用案例变得更加简单,使用它,observer_ptr不再需要提议- 为什么需要冗余?默认的可构造性reference_wrapper将统治它们!

思考?

c++ reference wrapper c++11

10
推荐指数
1
解决办法
2330
查看次数

推导出类型"auto it = unordered_map.find(key)"?

随着C++ 11的出现,我们有unordered_map.cbegin/cend来专门返回const_iterator的值.所以在表达式"auto it = unordered_map.cbegin()"中推导出的'it'类型是const_iterator.

但是,当谈到unordered_map.find(key)函数时,我认为可能缺少一个"cfind()"对应物,它特意返回一个const_iterator.

有人说我们可以使用"const auto it = unordered_map.find(key)"来获取"const迭代器",但我强烈怀疑"const iterator"是相同的"const_iterator",其中"const iterator"的限制改变迭代器本身的能力,而"const_iterator"限制了改变迭代器引用的内容的能力.

所以,真的,如果我们想充分利用"自动"类型演绎(了解混淆或"自动"类型演绎的变化 - auto,auto&,const auto等),我怎么能有unordered_map .find(key)返回一个"const_iterator"而不必我明确指定"const_iterator" - 这就是auto的所有最佳用例之后!

下面是一个演示编译器行为的简单示例代码:

#include "stdafx.h"
#include <unordered_map>

int _tmain(int argc, _TCHAR* argv[])
{
    typedef std::unordered_map<int, int> umiit;
    umiit umii;

    auto it0 = umii.find(0);
    it0->second = 42;
    const auto it1 = umii.find(0);
    it1->second = 42;
    umiit::const_iterator it2 = umii.find(0);
    it2->second = 42; // expected compiler error: assigning to const

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

const-iterator c++11

6
推荐指数
1
解决办法
694
查看次数

Redis Lua 脚本 redis.call('get', 'nonexisting') 返回值

似乎以下 Redis Lua 脚本返回false而不是nil,这与文档所说的相矛盾:

> eval "local r = redis.call('get', 'none'); if r==nil then return 42 end" 0
(nil)
> eval "local r = redis.call('get', 'none'); if r==false then return 42 end" 0
(integer) 42
> eval "local r = redis.call('get', 'none'); if not r then return 42 end" 0
(integer) 42
Run Code Online (Sandbox Code Playgroud)

第一个eval在条件下失败r==nil,第二个eval似乎证明返回值是false

似乎 usingnot r是我手头最安全的选项,但此处的文档说该GET命令将返回nil

这是其他人都观察到并依赖的事实,即检查返回的命令的最安全的 Redis Lua 脚本nil是使用 …

lua eval redis

2
推荐指数
1
解决办法
2419
查看次数

是否有可能让C#异步方法返回类型不是Task <T>或void?

似乎GetAwaiter可以等待任何实现需求的对象,Task<>类型只是满足此要求的众多可能类型之一.但是,似乎一种async方法只能返回Task<>void据我所知.是否有可能挂钩我的自定义任务等待类型,所以我可以指定我的自定义等待类型作为异步返回类型,然后当然我可以随后await链接通常的调用链.像:(伪代码)

async MyAwaitable MyAwaitableMethod()
{
    await myAwaitable;
}

async Task MyTask()
{
    await MyAwaitableMethod();
}
Run Code Online (Sandbox Code Playgroud)

背景信息:整个想法实际上源于C++ 1z/2x协程提案,它基本上具有相同的基本模型,但它允许更多控制来定义promise_type从协程返回嵌入的任何类型(因此的co_await).

[编辑]

除了答案中提供的链接之外,我还在以下链接中找到了更多信息,似乎确实有一些关于这个主题的热门讨论:

  1. https://github.com/dotnet/roslyn/issues/7169
  2. https://github.com/dotnet/roslyn/issues/10902
  3. https://github.com/ljw1004/roslyn/blob/features/async-return/docs/specs/feature%20-%20arbitrary%20async%20returns%20-%20discussion.md

[EDIT2]

令人惊讶的是,在进一步挖掘之后,这实际上是C#7.0的一个预期功能:http://intellitect.com/generalized-async-return-types/

c# async-await

1
推荐指数
1
解决办法
1316
查看次数