V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  FrankHB  ›  全部回复第 18 页 / 共 92 页
回复总数  1830
1 ... 14  15  16  17  18  19  20  21  22  23 ... 92  
2022-05-07 21:03:30 +08:00
回复了 MiketsuSmasher 创建的主题 Linux 用了多年 Linux 和 Windows,发现还是喜欢 Arch
@Cooky 显然如果眼睛没残疾的话,应该能发现,我一开始可没兴趣给你专开一楼……

如果不是语文水平没问题,看来是因为半吊子言论恰好 100%被路人我摁死而发表不满,嗯?

@findex Gentoo 整体思路的问题是,名义上谁都可以自己整,但是实际用户就没几个有本事确保折腾的方向是明确会按预期走的,更别说保证效果了。
极端点的“压榨”的不可行性很显然,除非——比如说,作为压榨者,你至少知道什么时候-O3 会突然炸了但被容忍、-O3 炸了但是不能容忍以及-O2 甚至-O1 都实际上比-O3 实际真的能容易压榨性能的情况。
光考虑这点就实际能导致压榨全局不可行,因为 gcc/clang/……显然就不可能是一个人写的,炸了也不是随便哪一个人就能独自确保调优正确的(不说改 gcc 之类的 bug ,万一被 build 这包不是你自己写的,很可能就够呛了……)。
而更实际的困难是系统工程问题。你把包 A 定制好了,结果依赖这个包的 B 的运行性能差了,包 C 的运行性能好了,肿么办?更新了版本,regression 了,这个摁下去那个冒出来,打地鼠么?真实系统里的包显然不是那么点,就算你清楚地认清了自己的需求,这种决策路径实质上有无数种。
所以这导致大部分人想要压榨,空间是很大,但是真正实现了压榨的解空间相比之下就小得可怜了,实际效果还真未必有更专业的系统开发人员替你整好的整个系统二进制映像更靠谱。
技术角度说,Gentoo 真正顶用的目标用户是不差硬件资源,想要大批量折腾整个系统的系统原型研究用户。大部分 Gentoo 用户都落不到这个圈子内。而这样的用户也没必要拿 Gentoo 当主力系统,反而多备几个实例更容易收拾意外状况。
所以对现实的大部分用户,选择 Gentoo 与大多数其它发行版的区别,基本就是提升了碳排放而已……
2022-04-30 17:27:47 +08:00
回复了 MiketsuSmasher 创建的主题 Linux 用了多年 Linux 和 Windows,发现还是喜欢 Arch
@techstay 其实如果是开发者,原则上还是要鼓励一下以主力系统折腾 Linux 图形界面的。
微软在 Windows 11 继续喂屎这几年想必不会停,LTSB 钉子户也像是二等公民,要是最终受不了了,就算有能力自己开发个 DE ,替换掉 explorer 的代价也怕是比干掉不舒服的 Linux 上的 DE 大多了。

@yzbythesea A (Linux) kernel is just boring, by fighting with the shitty ABI stability among the distributed kernel in hacking various kernel modules... (And the stability of the source interface of system calls? Who cares? I don't write the damn't libc... plus ENOSYS...)
- Me
2022-04-30 17:11:10 +08:00
回复了 holmes1412 创建的主题 C 分享新思路:一个逻辑完备的线程池
@holmes1412 那么我认为有必要说明,就 C/C++的传统,“允许在线程任务里发起下一个任务”的所谓任务,是确切有限制的。
只是让“逻辑完整”而放松接口限制并不是很有说服力的理由,反而容易隐藏使用错误的 bug 。

C/C++没有 GC 这样的全局所有者,所以一切 housekeeping 根本上都需要调用侧的用户自觉配合。维护所有权,避免双重释放或者和引入环这样的逻辑错误(尽管语言层次上并不是同等未定义的),是下游开发者的分内事。(至少你救不了拿到一个自动对象强行 free(&xxx)的。)
在“下一个任务”的负载(这里是线程函数)里,也不能违反这类假定。
这类假定在接口意义上按 C++的说法叫 narrow contract ,原则上是可以静态确定的,但没有在类型系统上体现也没静态检查所以显得不安全罢了。而 C/C++用户日常工作之一就是对付这种不安全的接口使之符合业务目的。
相对地,在接口内部添加的检查是 wide contract 。现代 C++明确拒绝随意 widen contract 替代不安全接口而实现所谓的防御性编程,因为这削减了下游用户正确使用接口的义务,反而让会遵守接口规范的用户受到了损害(调用侧一般无法消除实现内部的冗余检查)。

有的时候,为了允许减少接口的不可用限制,在库的实现中添加(而不是替代)新的包含分支检查的接口使不同分支都合法(而不是 wide contract 这种内部处理逻辑错误)而适配不同情形(如果把 narrow contract 改成类型检查强制,这样修改本质上就是一种类型擦除),也是合理的设计。这种合理性主要体现在没有更好的替代做法实现需求。
在并发同步的场景,这种做法的典例之一是在一般的非递归锁以外,并行地提供递归锁:因为确实存在设计时无法确保不重入临界区的合理需求,例如 API 设计者向其他 API 使用者暴露一段锁的保护范围且允许递归重入地占用临界资源。
(当然,现实还可能是因为底层系统直接分别提供了递归锁和非递归锁的 API 所以就直接映射过去了,但它们自身内部的设计仍有这方面考虑。)

只要不侵入调度逻辑,线程函数当然不应该知道线程池的内部状态,但为什么知道或者不知道线程池是否正在销毁会成为问题?
根本上,“在线程池销毁期间也允许另一个线程任务里提交任务”是伪需求,或者至少是不符合常规 C/C++接口用户默认对资源管理职责的假定的需求。
逻辑上,销毁一旦开始,对象的生存期就已经结束(特别地,参见 C++的生存期关于析构函数的定义),状态的完整性也不被确保。一整个线程池能用,不是整个的线程池可没义务保持能用。
如果你要强行能用,那么你的设计实质上就不是个单纯的线程池,而是包含更复杂阶段的支持资源迁移的执行引擎。(从你命名上似乎也想这样做。)
但真这样,你一个 in_pool 就显得很局促了,做得不到位。

可以确定,这种支持一定会比线程池更复杂。至于原因……先回到“下一个任务”的话题。
不限制下一个任务和 C/C++水土不服,因为 C/C++函数默认都是子例程而不支持捕获续延。
子例程在 C/C++中的一个重要规则是其中创建的局部对象的生存期不超过调用的活动记录(对一般实现,就是栈帧)的生存期。
线程函数也不例外。真要取消“下一个任务”中线程函数创建资源关于子例程机制的限制,至少还需要提供把资源搬运出来的保活机制——这需要魔改语言实现提供扩展,用库别指望有兼容实现。
退而求其次,就是在外部提供跳板(trampoline)函数进行变通。但这部分传统上超出了线程池的范畴,我也没在你的设计中看到(根本上是异步框架,还可能涉及主动切换调度策略)。
这种不限制下一个任务的模型是一种 CPS 的变体,它隐含了外部所有者的假定,其实是可以不违反任何 contract 而合理的,但是实现相对 C/C++子例程总是有附加开销,这种代价在单纯需要线程池的场合往往完全冗余乃至不可接受的。
资源销毁在此还有另外的特殊性,就是生存期不能被任意延长,否则可能有非预期的泄露。
当然你的设计只用了一个 in_pool ,这里倒不会有特别麻烦的问题。
然而也就因为只是一个 in_pool ,能多做的也就比较鸡肋了,很难跳出为了把不经意的不合理设计洗白的窠臼。
真正的并发执行引擎,其实逻辑上就不依赖线程池。用没用线程池对用户都是实现细节(要侵入调度改配置给参数就行,不用知道有个池),更不说暴露线程池的销毁状态了。
2022-04-30 16:07:05 +08:00
回复了 MiketsuSmasher 创建的主题 Linux 用了多年 Linux 和 Windows,发现还是喜欢 Arch
然而,首先,systemd 就是个文明用语。(我倒不是特别在意放置不用的,不过没法和 WSL1 的 init 兼容就是个问题。即便根源是后者显然更欠扁。)
技术角度来说,除了 nix 和 guix ,剩下的所有发行版在“发行”的意义上都是弟弟,因为连个基本系统内部版本管理都做不好,动不动就依赖冲突。(当然弟弟之间参差不齐,Gentoo 这种显然有瞎折腾碳排放的问题,别的发行版就不一定存在。)但是 nix 和 guix 自身又过于依赖系统机制,源又渣,一时也是没救。
技术上来说,makepkg 是比较弱鸡的;但是如此弱鸡的东西居然可用性相对还行,也说明各大发行版的拉胯现状。
alpm 这个机制只用在 AUR 上太浪费了。其实 MSYS2 和 devkitPro 这样已经使用了 pacman 的环境理论上也应该可以用(几年前 MSYS2 我是动手移植过,yaourt 没问题,不过后来 libalpm 的 API 改了不好搞),没铺开来大概只是流行不够。
另一方面和不愿意出 WSL 官方发行版一样,显示了 Arch 官方的小家子气。(没把握做好就不做或者明确兴趣做要另请高明都没有什么不对,但对用户来讲显然不理想。)
我用 SB2 ,字体渲染差异感知不大。不过低分屏明显 Win32 吊打绝大多数其它环境(你不可能指望应用开发者都是会折腾好 FreeType 的专家)。
性能问题大部分反倒是没感知的。Windows 慢很大程度是使用的工具链保守,其次是 ABI 拉胯。但是基于 SysV ABI 很多时候更加拉胯(比如默认 std::unique_ptr 都没法传寄存器)。另一方面,很多有全局性能影响的改动其实一般用户自己都没什么感知,比如-fstack-proctector -D_FORTIFY_SOURCE=2 ,真计较的话其实不应该那么容易忽略。

@CharlesGray 你引用的这个还真有点一言难尽……

> ‘FreeBSD’、‘freeBSD’、‘Freebsd’、‘freebsd’这些字应该记着。
正确使用大小写本来就是常识。比如专名,像 FreeBSD 基金会的名称和作为商标。小写是明确被允许的,比如官方源码库的名称,所以自然也不算错。真正应该迷惑的是“https://www.FreeBSD.org/”这种大写并没什么卵用的场合(这个是官方在用)。另外 freeBSD 和 Freebsd 我还真没见过。

> 用自己的要求规范别人。
那么用别人自己隐含的规范要求一致性应该不算问题吧。但是这文章“用 WP 手机的用户是否也是苦难哲学的受害者”的“WP”后面少了空格( V2EX 发出来会自作聪明调整,看不出来)和原文其它的位置格格不入,我觉得更容易逼死强迫症一点……
(既然别的地方还会刻意加空格,不一致应该不是故意的。)

> 一些人非要在 Linux 下学习 C 语言,说什么更清楚的了解 IDE 的工作方法,说什么预处理编译汇编链接在 IDE 下不直观,非要折腾自己用什么 GCC ,GCC 好用吗?对于初学者来说有什么用?那些是编译原理课程所需要的,而不是 C 语言。
这就是明确的误导。
首先说反了,是 IDE 对学 C 语言没什么用才对。至于如何使用 GCC ,那是 shell 语言课程的内容(悲)。
另外,编译原理也用不到这些。作者应该相当不明白编译原理在这里并没什么卵用的程度和这个事实的作用原理。
不懂得正确使用还原论,混淆 IDE 的莫须有用途,是迈向这个方向稀里糊涂的重要一步。

> 用 GPL 协议捆绑用户也是一种苦难哲学。
苦难哲学 ×
政治哲学 √

> 我觉得这破坏了语言的纯洁性。
这明显是孔乙己双标嘛。大小写起码还有文法要求,都能不管,构词还能不纯洁了?
真要说的话,这文章里上面有个“造轮子”后面用半角括号不符合《标点符号用法》(中华人民共和国国家标准),这明显更不纯洁嘛。

> 显然不是,有谁记得和乔布斯同月去世的丹尼斯·里奇呢?
虽然但是……这里毫无说服力。至今我都会时不时拖出 DMR 的历史言论来批判他在 C 里面的垃圾设计,不过也不是很频繁——就同辈来说,至少 Ken Thompson 明显比他烂多了。
相比之下,Jobs 的烂得“毫无设计”差不多成了常识。毕竟他没本事发明什么管道信号量之类的东西,对吧?(时不时得科普一代 iPhone 基本被当时 WM 设备吊打和强行吹捧小屏机被翻案这么 low 的黑历史,我也很无奈啊。)

> 这个东西首行缩进的设置都够呛,都是厘米以单位的
这个有点莫名其妙,不以厘米为单位,难道还用英寸或者数空格数?

> 也就是说收费开源是被允许的。
虽然结论没错,这论证过程倒真有些像“许多开源小将不懂何为开源却大谈开源”。
去看看 OSD 第一条,禁止收费直接被踢出开源,就不用下文那么弱鸡的解释了。

> 这个文件系统的稳定性远远超过所谓的什么 xfs ext ,更不要 btrfs 了
虽然但是,要不要跟 ntfs-3g 比比?
zhuanlan.zhihu.com/p/28828826
这究竟是在说文件系统还是实现的设计,暂且蒙在鼓里。微软的实现我审计不了,不过 NTFS 掉数据的经验我是丰富多了。另外,考虑到垫底货 exFAT (某一段时间遇到某些存储卡上必掉数据),微软的信誉就别太指望了。

> 2021 年代的 Windows 11 ,甚至还可以运行 26 年前 windows 95 程序,而且更甚至地是不需要重新编译源码。
毕竟能编译就赢麻了吧。
说实话,我刚刚教育完小朋友(用 github.com/FrankHB/pl-docs/blob/master/zh-CN/criticisms-on-UTF-8-everywhere-manifesto.md ),真的很想干死几个滥用 Win32 A API 的废物祭天。

> 这是任何一个 Linux 系统都做不到的,他们甚至连几天前的程序都不能够兼容。
> 他们的程序会依赖特定的 C 库,依赖特定的内核版本。

建议去咬 Linus Torvalds 的系统调用 ABI 政策。

> 不要提及 Macos ,那是苹果战略性的不兼容
OS X 、macOS ,谢谢。

> 开源软件根本上就是违反软件工程的,因为其第一步就没有进行用户需求设计……
开源本身就是个许可证箩筐,其实不在乎什么工程不工程。
反过来,软件工程在很多情况下则根本是反人性的。
例如,明明我同时能作为用户和工程师完成一人项目,按软件工程的方法却强迫我先要精分才能沟通。而就是这种低效使用户需求的反馈无条件地被降低了,即便我同时是某个领域最专业的用户和工程师也无法挽救。正常起见,只有先把软件工程打死再说了。

@Cooky 本质?我选择 WSL1 ,因为我用不到 Linux kernel (
1. 这个你得看下游自觉。比如 fcitx 这种,你确定你有本事找到及时更新的准确的非 GUI 配置方法么?(你要是维护者,当我没说。)
2. 滚的问题是不保证隔一段时间突然滚就不挂。虽然对目标用户来说恢复不是什么难事,最近一些难也罕有案例,但是没保证就是没保证。无论是被强迫定时及时滚还是滚之前必须自觉去看公告这个都挺不咋地,除了默认爱用用不用润以外就差没说“你们用户的时间就是不值钱了”。(拜托,我审计更新什么包也是得花精力的好不……)
3. 莫名其妙程度有差么。
倒是某些官方开发者认为-git 包就应该获得完整历史记录( bugs.archlinux.org/task/34677 )、反复拒绝 makepkg 支持 shallow clone 这个要可笑的多了。
这里的荒谬性在于只有 makepkg 这个层次最适合加这个功能,如果硬是不支持(不说是否有碍于功能完整性),用户又想要,逻辑上差不多就是让用户自己实现个 makepkg 替代。然而 Arch 官方又没本事把剩余部分写得足够模块化到用户想替代就替代,要重写就是要重写一整坨的……这就实在简洁不起来了。

@makelove “私货”例子。↑

@Buges 一个 pacman 用舒服是一般是不可能的,AUR manager 你不用么。
极端点说,pacman.conf 还不是要手动编辑( yay 倒是能自己直接命令行改配置)?
另外要充分发挥简单,自己打包,pacman 也没打算代替 makepkg 吧?
命令行参数风格这个姑且算是统一了,但是“多种”这个还是跑不掉的。
系统干净……你有把握打死所有认为 systemd 不干净的么……
2022-04-27 12:58:36 +08:00
回复了 zhanggg 创建的主题 Linux 求推荐个 Linux 桌面发行版
你先试试关掉管理员权限。
Linux 表面上看上去不那么容易坏,关键理由除了流氓软件自身适配的原因,就是普通用户不那么(很)容(难)易成功被引导会怎么装上他们没想清楚要的软件。(要会 root 就比 Windows 权力还大了,起码一般 Windows 用户搞不到 System 权限也不知道怎么干死 TrustedInstaller 。)不给管理员权限的 Windows 还真没那么容易坏,系统关键位置的完整性勉强还是有的。
2022-04-27 12:49:00 +08:00
回复了 holmes1412 创建的主题 C 分享新思路:一个逻辑完备的线程池
@holmes1412 “销毁线程池”是你提出来的。
正常来讲,语言中代表线程的一等对象(线程句柄之类)就是线程池所有的对象,作为线程池的负载的用户代码根本不关心这个对象背后蕴含的线程资源自身的生存期——因为说白了,线程池就是为了能放松对线程创建销毁的时机提出的优化。
销毁线程池,正常理解就是把线程池作为对象销毁,这应该是在所有并发执行区间以外不和任何线程池并发的管理任务中集中处理的,而不需要在线程池内部考虑。这同时也是 fork-join 并行的标准处理方法(如果姑且不算纠结哪个算主线程的问题,但这种非对称模型你这里看来也不关心)。
换句话说,创建和销毁线程池都不用关心和负载任务之间的并发。若硬是想套娃线程池,线程池自己就是普通的对象,是不同层次的东西。
于是,涉及线程池中非负载特定的资源的销毁之间的同步也就两类:
线程池负载的任务启动和终止需要同步,因为会共享线程对象本身作为临界资源;
所有线程的生存期结束早于(happens before) 线程池的销毁结束。

另一方面,线程池被销毁时不保证可以正常同步,也意味着不需要允许提交任务,这能简化实现减小开销。否则,逻辑上必须搬运出一个独立于线程池自身的并行的所有者代替线程池才能继续保存共享状态。
在有全局 GC 的语言中,GC 就是默认的所有者,资源往 GC 上一扔就可以装作没区别(开销也是平摊到 GC 上了),但这在 C 和 C++行不通。
在 C 和 C++这种一般的一等对象不可追溯所有者的语言里,destroy 这种行为原则上不可能对等;如果做到了表面上的对等,就说明必然存在一个其它对象来维护 destroy 不破坏资源对象生存的不变量。原则上只有平凡(trivial)的无状态的纯量(scalar)才可以无视不变量,你依赖的 pthread 就不行。
这在 C 可能不太明显,在 C++更加强调:析构函数对每一个活的对象只能重入一次,对象生存期结束之后不能随意复活。
你的实现中,pthread_setspecific 设置 key 依赖 TLS 就是隐含的每线程对象中的内部资源。而并行所有者体现在 thrdpool_destroy 中的 in_pool (然后在 pthread_key_delete 调用后最终可以根据仍然生存的 in_pool 来 free )。虽然只有一个 int 这么个纯量,看上去很聪明,但根本上相比上面说的正常设计仍然是冗余开销;而实际实现中,更该关心的问题是 pthread_key*往往很不便宜。
在我说的正常的不需要考虑内部同步的实现中,用户程序保证 destroy 不可能在任务内部提交,所以整个 TLS 访问和 in_pool 的分支就是多余的。
在 C++中,这种保证都不需要用户自己编码,析构函数直接就能隐含(正常用户不会没事自己显式调用析构); C 就更依赖用户自觉了,所以才容易更没自觉。
2022-04-26 18:46:56 +08:00
回复了 holmes1412 创建的主题 C 分享新思路:一个逻辑完备的线程池
销毁线程池是什么需求?没事制造循环所有权引用?正常不那么用的不吃你这 in_pool 亏?
不考虑销毁这个不就是个 notify all+一轮 join 么,还要纠结什么 id 么……
2022-04-26 03:25:02 +08:00
回复了 Skeleies 创建的主题 程序员 聊天软件端对端加密疑问
@jones2000 除非一次一密,再牛逼的加密都能爆破,无非资源问题,这不废话么。
2022-04-26 03:19:15 +08:00
回复了 liuidetmks 创建的主题 程序员 国密标准推行不太顺利的样子?
@ixcode 显然破烂到处有,国产还是弟弟。
比如数学上的加法不会溢出,然后你每天不知道多少活是缩水版野鸡加法替你干了……
2022-04-26 02:51:42 +08:00
回复了 qwerzl 创建的主题 Linux 分享一个挺有趣的 Linux 发行版 Bedrock Linux
有本事把 WSL 和 Hurd 缝合起来(
……其实能把 WSL1 的内核缝个像样的版本出来就不错了。。。嗯,或者退而求其次,缝个能用 systemd 的 init……?
2022-04-25 21:50:54 +08:00
回复了 Lighthughjiajin 创建的主题 程序员 关于 smaba 和 nfs 的区别?
@eason1874 实现是 samba 。SMB 是 Server Message Block ,也是一种协议。SMB 的一个早期版本又叫 CIFS(Common Internet File System),也是“文件系统”。Linux 内核的 SMB 实现也直接叫 cifs 。
2022-04-25 21:37:01 +08:00
回复了 fawdlstty 创建的主题 C++ libfv:基于 C++20 的异步 HTTP 库
@ysc3839 真说性能,其实状态机一般用途上还是比较快的,伺候好 cache 的话。现代 CPU 的 jmp 多少能投机,没以前那么坑了;反倒 call 还是那么麻烦。
一般这类命令式语言中用的 IR 也对保留一整坨函数进行分析更不友好,扩大了偏好的影响。所以某种意义上,首选编译成状态机算是各家心照不宣的常识了。
相比之下,stackful 的东西得搞 activation record ,即便有 CPU 的 stack engine 加成也是得在 key path 上多吃 cycle 的,极端性能就没法打了(虽然场景其实不大公平)。
然而 C 艹现在这样的设计还是有损失性能的地方,就是一些东西扔 heap 这个投降得太早了,明摆着打不过 segmented stack+shared stack record 之类的。只不过现在的 C 艹也基本没法在这里走回头路。想在没搞定更基本的缺少怎么 reify the stack 的情况下还想折腾 ABI ,那基本就是找死。
2022-04-25 20:56:38 +08:00
回复了 fawdlstty 创建的主题 C++ libfv:基于 C++20 的异步 HTTP 库
@fawdlstty 我能理解 async/await 有一些能好用的地方,所以大约能理解你的动机。
除此之外,如果你的目的是简化使用,照理来说应该赞扬,不过我不觉得能乐观。因为这方面不管是特性难产还是碎片化,很大程度来自 C++已有的设计,而频繁发版则在现实应用加速暴露了这些问题。

你说 u8string 之类的难用的可以不用,如果就是库,确实不难做到。然而这里更多是核心语言特性的设计缺乏前瞻性和可组合性的问题,特别是 await 更改的本质上是相当底层的东西( control effects )却极少有人预料到缺乏一个靠谱的全局设计的风险,未来什么时候跳出来会咬你一口,还真不好说。
只能到时候希望你能坚持初心。祝你好运。

@hez2010 我不得不跑点题(虽然跟之前说的也有关)。
async/await 在一些特定的场合是可用的方案,但距离通用差远了。
光是之前提到过的一些用户抱怨的关于 async 的传染性问题,就是不把 async/await 改掉不再 async ,就不可能解决的(原因下面说)。
另一方面,要是这个通用,这里按理根本就不用 stackful 的重量级玩意儿了(虽然这些东西能解决的问题比区区一个异步更广)。但现实呢?

现实的异步编程的一个关键问题就是怎么用看上去表面同步的 direct style 去干掉显式 CPS 。其中的一个重要场景是,已有 direct style 的大量源代码,怎么在尽量少的改动下引入异步,允许异步的好处。
直接 callback hell 显然不行。async/await 相对这种显然好,但还有明显的缺陷——要改的仍然太多了。具体来讲,async 和非 async 的部分原则上没法直接复用,这直接在逻辑上引入不必要的冗余。
为什么 async 需要被传染,即便“异步”自身的逻辑上不必要?因为这种方案根本上要求改变 direct style 函数的返回类型。通过函数签名上附加标记,实现才能通过 syntactic transformation 的方式直接魔改代码生成(比如你说的状态机)糊上不同 style 之间的 semantic gap 。
不过很遗憾,这就不是通用的需求:几乎所有现实异步编程的需求都不需要在乎返回类型和原先不同或者在乎生成的代码是否使用状态机(要是关心生成的代码,直接需求基本也就要开销小,尽量快);反倒是修改类型签名阻碍复用的作用暴露到对象语言用户面前,妥妥地绕不过(总不能逼用户自己糊状态机 8 )。所以这是一种具体实现造成的抽象泄露,断然不可能通用。

进一步地,钦定类型签名的变化实质上是在代码添加静态信息(即便被关键字掩盖了)。而现代 C++的传统并不买 type richer = better 的账,所以强推 async 实际是不大自然的。
例如,C++会强调 exception neutrality ,而和 Java 那种 checked exception 或者 Rust 的 Result 之类的机制(本质上都是庸俗的 union type )划清界限(即便有 expect ,也不会取代 exception ),因为不是所有情形都能对污染类型签名和 happy path 在现实中引起的修改的代价无所谓。
反过来,在不愿意影响类型签名的问题上,要让代码更 C 艹-ish ,就意味着允许用户自行把多余非预期类型擦掉(即便有一些开销)。对对象类型,擦除是相对容易的( any ),但是对隐藏在 async 这样的关键字下的类型,这里的修改开销现实缺乏可行性。
这意味着现实代码一旦引入 async 这样的特性,很可能在生命周期结束之前都没法甩掉,更加坐实了现实不可复用的缺陷。换句话说,要用了 async/await ,想要写语义上(而不只是表面的语法上)真正兼容同步和异步的代码,基本就不用想了。这又是一个不通用的例证。
考虑到 dynamic exception specification 这样非签名侵入式的特性都是这般下场,我实在无法看好 async 真被滥用之后的景观。(虽然或许不过直接分裂用户群体成会接受 async 和不接受 async 的就好了……)

最后,上面说的不可复用其实隐含了一点:不考虑就是否存在 async 实现 ad-hoc polymorphism 的扩展特性。
实际上,对类型系统加以魔改,引入类似 Haskell 的 levity polymorphism ,理论上是可以直接解决复用问题的。
但是,在此我旗帜鲜明地站在这种设计的对立面上,因为:
它解决的问题和背后的复杂性不成比例实在过于离谱;
C 艹的 value category 自带 subtyping ,直觉上就比 Haskell 的那几坨 kind 破烂难搞多了,瞎折腾就得寄,更别说做编译器的能理解了;
会把 C 艹程序的不(可)可(读)理(性)喻(垃)程(圾)度连跳几级,推高到船新的阶段;
async/await 说穿了也就是在以相当 syntactic 的方式实现区区那么一种 control effect ,甚至都没一般的 concurrency 排面,有什么脸占那么大核心语言特性演化资源?
这种复杂度已经失控的边缘的设计再下去是不是甭想扩展了?

最后的最后这点是我刻意要提到其它异步实现方式的直接理由;相对地,编程习惯的问题解决起来就小儿科多了。
2022-04-24 16:54:24 +08:00
回复了 fawdlstty 创建的主题 C++ libfv:基于 C++20 的异步 HTTP 库
@fawdlstty 我说 C++硬塞半成品进去不针对 co_xxx ,而是适用于这些年来各种已有的主要特性的迭代升级。
(从 C++20 开始这坑特别集中。)
比如 lambda ,C++20 调过 this 的 capture 还加了 deprecation ,于是一些 capture 不写全永远别想兼容 C++11 onwards ,要么#ifdef ,默认 capture 这功能约等于没有。
再如 char8_t ,变更了类型直接搞得想要兼容的 u8 string literal 没法写。
就算只用最新版本的嘛……有些可预见的东西是残的。比如 strcuctrual binding 还缺 nested match 。是不是会顺便在补全功能的同时进来一丢 breaking compatibility 的东西进来,到时候还真没底。
这种不会一步到位倒是也挺符合微软特色的(都不限于 C 艹,e.g. v2ex/t/845526#r_11546877 ;硬点的话,WG21 浮躁的“敏捷”发半吊子版的歪风一部分就得归功于微软)。
结果……这不就是等等党永不为奴么。(就算 C++98 太残太恶心了,C++11/14 大多数用户还是能凑数的。)

C++23 的 co_xxx 补充主要是 std 内部的东西,你既然都能积极从头造库的轮子了,和这里的关系反而不大。我说的 co_xxxx 的半吊子,主要是指 xxxx 本身理论上就有的局限性,而不是 C++里 co_这样的具体语法设计。
如果你看懂了我提到的一些文献就不应该容易有这个理解偏差。不过如果你只是用过“工业语言”特别是 async 类似物,因为糊 IO 库的主力确实也就是这些圈子在倒腾,那我倒是可以理解你这样想的原因(不过俺寻思 Lua 也不咋学术啊……)。

至于 asio ,你更该关心的是为什么推了那么多年还没进去,半路杀出来的 executor 又难产了。(当然这主要还 WG21 的原因。)既然 chriskohlhoff 那么高效热脸怼冷屁股的作风都推不大动,就更别指望别人了。
另外,基于 asio 的 http 库这题材实在不新鲜了。虽然我没怎么关心,比如 beast 这种,没在这里跟进么?
考虑这点,想要用你的库,就得长个心眼关心作为作者你和这些更大众得项目的维护持续性的差距了,这也是你要推广时需要考虑的点(当然开源嘛,基调都是爱用用不用润,所以不关心这个也无妨)。虽然这根本上不是技术问题,很遗憾,大多数用户现实能体验到的差异就是在这里。
2022-04-24 16:38:25 +08:00
回复了 tlerbao 创建的主题 git git reset --hard 求救哈
@ElmerZhang hg mq 一点都不 nb ,只不过 hg CLI 的一些基础设计真没 git CLI 设计得那么傻缺,拿过来开箱即用而体现出日用体验优势了。
要干掉也是 hg 整个干掉 git ,不过 GitHub dssq 呗……(这种 SO/YC 之类的一搜一大把就不具体引用了。)要我说就是绝大多数日常用户甚至都还没到用出差别的水平(除了 hg 存小文件效率和 git 断点续传更欠扁的个别问题),用哪个基本就是随大流,git 更网红所以更常见罢了。
另外现在 mq 是 hg 官方都不建议用了( www.mercurial-scm.org/wiki/MqExtension )。毕竟 mq 不是为了体现竞品傻缺发明出来的,而是为了替代早年 hg 没有 rebase 。这又是因为 hg 早年排斥修改历史的传统。然后这里 hg 还是怂了,于是有了 strip 有了 histedit 有了 rebase ,所以修改历史这个最主要的目的就用不上 mq 了。mq 仍然有用,主要适合专业对付 patch series 的 maintainer ,而 git 核心用户一开始也强调对了这个需求,并且设计得并不傻缺——直接开 branch ( hg 对应 git branch 的 bookmark 也不是一开始有的),处理 patch queue 时跟 hg mq 的实际日常用法大同小异;种种因素使 git 中一直有(不严格)对应的功能,但具体用法反而没那么大存在感(间接增长了类似 OP 这里的问题)。
这里鼓励 git 多 commit 也不可能是一个 branch 上蹲点(这里也有不少人表示新开 branch 算是常识了),所以核心用法跟 mq 差不多(只不过不强调是 patch )。
2022-04-24 06:31:34 +08:00
回复了 Features 创建的主题 程序员 今天用 winscp+root 去改配置文件,被挂在群里吊。。。
@gps949 你要到下个世纪才抓到那就肯定不会好了。
2022-04-24 06:14:17 +08:00
回复了 movq 创建的主题 C++ C++ for 循环终止条件里面如果写一个数组的 size,会不会优化呢?
这算是很常见的优化,但说到底都不保证。

@ipwx 就这里的例子第一步是内联肯定是错的。
对 GCC (比如-O1 以上),至少要先做 IPA pure/const 分析,拆了函数分析多此一举。而这又得依赖事先知道是不是会内联,所以在此之前要求有 IPA fnsummary ,以确保局部状态一致。
IPA inline 的两个 pass ( einline 和 inline )在 fnsummary 和 pure/const 之间,而真正干活的 tree inline 还远着。
如果 pure 分析结果能确定内部只依赖参数或者有__attribute__((pure))之类,标记 DECL_PURE_P 。在这些函数的调用表达式上会标记 ECF_PURE ,进而影响 gimple_has_side_effects 的结果,在 tree SSA 循环不变量移动 pass 中提出来。
只要能分析出 xxx 没改 nums ,这里就很明确不需要进一步内联。

@111qqz __builtin_strlen 和靠谱的库函数 strlen 都应该标记为 pure 。
说起来 GCC 甚至还有单独的 tree SSA strlen 优化……
2022-04-24 04:14:44 +08:00
回复了 fawdlstty 创建的主题 C++ libfv:基于 C++20 的异步 HTTP 库
@fawdlstty 硬塞半成品进去就是拖到下一版本擦屁股,结果升级火葬场。实现碎片化一地:VS 支持的特性 GCC 没有,GCC 有的 Clang 又没,这样朝三暮四几年实现才勉强能用,然后又赶上新的版本出来了。估计接下来几年现实一点就是 C++11 直接跳到 C++26 ,中间版本别看了。
至于 async 这种说白了也是半成品,况且传染起来可一点不比 callback 含糊。js 用户都有不爽的:blog.logrocket.com/async-await-is-the-wrong-abstraction
同样是半成品,怎么看都不如这种:
open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0534r3.pdf
其实都挺过气的,co_备胎到处都是。
legacy.cs.indiana.edu/~sabry/papers/yield.pdf
http://www.inf.puc-rio.br/~roberto/docs/MCC15-04.pdf
2022-04-24 03:59:47 +08:00
回复了 tlerbao 创建的主题 git git reset --hard 求救哈
如果说的是 staging area ,这货就不配叫暂存区,特么根本就没存内容。
这个多此一举模拟 GUI 的 checkbox list 的二缺设计……算了不浪费口水了,还是多 commit 吧。。。
硬要模拟 index 也是被 hg mq 吊打,人还能不止一个……
2022-04-24 03:50:19 +08:00
回复了 tlerbao 创建的主题 git git reset --hard 求救哈
没事整什么 stash ,又低效又难用。同样没备份,hg mq 不知高哪去了。
不用 stash ,老实多 commit ,直球 reset 也无所谓,反正能 reflog 。
1 ... 14  15  16  17  18  19  20  21  22  23 ... 92  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2280 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 37ms · UTC 12:32 · PVG 20:32 · LAX 05:32 · JFK 08:32
Developed with CodeLauncher
♥ Do have faith in what you're doing.