在C++ Workflow中有五种基础任务:通讯、计算、文件IO、定时器、计数器,在coke项目中也分别对应着一组基础组件。其中计数器通常用来实现功能更复杂的复合组件,coke中暂时不会有一个通用的计数器基础组件,因此本文要介绍的文件IO应当是基础组件中的最后一个了。
与C++ Workflow
一样,coke
提供了一组类似于pread
、pwrite
的文件IO接口,具体如下
FileAwaiter pread(int fd, void *buf, size_t count, off_t offset);
FileAwaiter pwrite(int fd, const void *buf, size_t count, off_t offset);
相比于其他异步任务,作者在实际工作中很少遇到异步文件IO相关的场景,因此在设计更易用的接口时遇到了瓶颈,若读者有相关的场景或好的设计想法,欢迎到项目ISSUE中讨论。此处先给出上述接口的具体使用方法
#include <iostream>
#include <cstring>
#include <cerrno>
#include <unistd.h>
#include <fcntl.h>
#include "coke/coke.h"
coke::Task<> write_file(int fd) {
const char *str = "Hello world!\n";
std::size_t len = std::strlen(str);
off_t offset = 0;
coke::FileResult res;
for (int i = 0; i < 3; i++) {
// 将字符序列[str, str + len)写入到文件的[offset, offset + len)位置
res = co_await coke::pwrite(fd, str, len, offset);
if (res.state != coke::STATE_SUCCESS) {
// 文件操作发生错误,其中res.error与Linux errno一致
std::cout << coke::get_error_string(res.state, res.error) << std::endl;
co_return;
}
else if (res.nbytes != static_cast<long>(len)) {
// 当写入字符数量与传入的len不一致时,需要再次通过coke::pwrite
// 将[str + nbytes, str + len)中的内容写入,此处略去了
std::cout << "Partially Success " << res.nbytes << "/" << len << "\n";
}
else {
// 全部写入成功
std::cout << "Write success\n";
}
// 将偏移量移动到下次写入的位置
offset += res.nbytes;
}
}
coke::Task<> read_file(int fd) {
constexpr std::size_t MAX_READ = 4096;
char buf[MAX_READ+1];
coke::FileResult res;
// 从偏移量0读取至多MAX_READ个字符到buf中
res = co_await coke::pread(fd, buf, MAX_READ, 0);
if (res.state == coke::STATE_SUCCESS) {
// 若读取成功,则res.nbytes表示成功读取的字符数
buf[res.nbytes] = '\0';
std::cout << "Read " << res.nbytes << " bytes. File content:\n";
std::cout << buf;
}
else {
std::cout << coke::get_error_string(res.state, res.error) << std::endl;
}
}
int main() {
const char *tmpfile = "test_fileio.tmp";
int fd = open(tmpfile, O_RDWR|O_CREAT, 0644);
if (fd < 0) {
std::cout << "OpenFailed file:" << tmpfile << " errno:" << errno << std::endl;
return -1;
}
coke::sync_wait(write_file(fd));
coke::sync_wait(read_file(fd));
close(fd);
return 0;
}
有了这些基础组件,原则上就可以实现与之相关的所有功能了,但这还远远不够。本项目将会从实际场景出发,思考并设计一些通用的复合组件,让代码写起来更加顺畅。这些会需要更多的灵感和业余时间,所以不会很快就搞出来。
本系列文章同步发布于个人网站和知乎专栏,转载请注明来源,以便读者及时获取最新内容及勘误。
本文由kedixa发表于个人博客,
转载请注明作者及出处。
本文链接:https://blog.kedixa.top/2023/coke-fileio/