-
Notifications
You must be signed in to change notification settings - Fork 378
feat(api): Add native fs apis #351
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
其实,我觉得这个不好。用得不好,界面就卡住了。 |
native api 是为小文件读取避免 async 和需要回调的场景设计的(比如 SMTC Buttons 回调),在数据量大的情况下确实可能会导致渲染线程卡住。但是也不推荐在数据量大时使用 native api,可能会导致 ipc 通道阻塞和大量内存泄漏(cef 论坛上有汇报 cpp 端发送的数据不会被 gc 自动回收的情况,不清楚 ncm 用的 cef 版本是否有这个问题),相反,应该使用 http server api(如截图那块的 api),不过延迟就会相对大一些 |
new std::thread 在执行结束后最多会泄露 4 个字节,相比之下还是 native plugin 那边 string 参数漏的更多( |
|
(问题最大的还是网易云本身刷新后完全不会回收上一个页面的内存,这个漏的太多我还很难修) |
JSFunction 那个类必须要用值捕获才行,或者自行加锁/atomic。毕竟是发送到v8线程去执行的 |
|
没有注意到JSFunction这层封装。真复杂呀。实际运行是不是还是异步的post到v8线程的。 |
应该不会,std::thread 在执行完成后会自动释放 HANDLE |
你说的这个方案我没考虑是因为 JSFunction 可能会被多次调用…如果直接 delete 就会导致多次调用失败,而且外部会悬空指针。就是没想到一个好的方案最后还是决定摆了(想到能用的可能是在最后一次执行写一个 flag,但是这样就很不优雅 实际确实异步 post 到 v8 线程的。 |
简单写了一段程序。测试了一下。不会。 int main(int argc, const char** argv)
{
std::thread t = std::thread([]() {});
DWORD ret = WaitForSingleObject((HANDLE)t.native_handle(), INFINITE);
assert(ret == WAIT_OBJECT_0); //线程执行完了
HANDLE hh = t.native_handle();
ret = WaitForSingleObject(hh, INFINITE);
assert(ret == WAIT_OBJECT_0); //等待成功表示hh是个有效的线程句柄
//执行完之后,线程句柄并没有释放
t.join();
return 0;
} |
另外,你的整个代码用到了各种c++高级的功能。但是在这一块却完全没用std::shared_ptr(虽然我也没一下子想到应该怎么正确使用来解决当下的问题)。但是使用那么多new,不符合这个项目的风格。 |
此处使用 shared_ptr 来管理内存会导致对象在 v8 线程中执行前, task已经被post出去后被清理掉,等到需要在 v8 线程中执行时对象就已经没了 |
记得在哪看到过一次,可能是我记错了,回头看源码查证一下 |
busy和valid都是atomic var,可以保证在短时间内调用两次时会依次执行(好久以前写的了 应该是这样) |
|
(另外可以把自己写的东西放在 quote 外,差点没看到这段) |
不是的。你看这一段: const int operator()(Args... args) {
if (!this->valid)return -1;
//如果两个线程同时开始执行operator()
//然后等待busy变成false
while (this->busy);
//然后可能这2个线程同时等到busy变成了false,然后同时开始执行下面的代码
this->busy = true;
auto task = static_cast<cef_task_post_exec*>(calloc(1, sizeof(cef_task_post_exec)));
task->func = this;所以应该用一个InterlockedCompareExchange这样的api,来原子的执行 (引用的时候>符号那一行需要空一行才能脱离quote。有时候写的时候没注意看preview,就排版错了。) |
|
噢噢 你是这个意思 可能确实会有这个问题 我现在去改 |
|
std::atomic 是有 CAS 操作的 api 的,这里没用确实瓜了) |
https: //github.com//pull/351#issuecomment-1500210856 Co-Authored-By: heroboy <54468+heroboy@users.noreply.github.com>
|
我又思考了一下 std::thread([=](){
}).detach();我觉得你使用new的原因是, std::thread在析构的时候会报错,这是因为std::thread析构前必须先 另外,我一开始没有说应该用 当解决完 |
std::thread 中 lambda 捕获的变量有所有权转移,会在执行完成后释放,直接 detach 不会导致析构 closure 中捕获的变量(除非是指向局部变量的裸指针之类的)。 这里使用 new std::thread 和 std::thread{}.detach() 的区别只有八个 byte,不是很大,不过依然感谢你的提出。 new JSFunction 确实可以用类似 std::thread 的 detach 思路解决(也就是我前面说的写一个 flag,在执行结束后/当前没有执行任务时自己销毁),不过我感觉还是不是太优雅,我后面再想一下,这边先把这个 new std::thread 改掉先。 |
…, getLibraries)
readDirWithDetails: 获取目录下所有子文件/文件夹详细信息
getProperties: 获取文件属性
getDisks: 获取所有盘符
getLibraries: 获取 Windows 系统库路径
同时增加了 long, long long, std::map, std::variant 的 cef_v8value_t 转换