Sane C++ Libraries
C++ Platform Abstraction Libraries
SC::AsyncFileRead Struct Reference

Starts a file read operation, reading bytes from a file (or pipe). More...

#include <Async.h>

Inheritance diagram for SC::AsyncFileRead:
SC::AsyncRequest

Classes

struct  CompletionData
 Completion data for AsyncFileRead. More...
 
struct  Result
 Callback result for AsyncFileRead. More...
 

Public Types

using Task = AsyncTaskOf< AsyncFileRead >
 
- Public Types inherited from SC::AsyncRequest
enum class  Type : uint8_t {
  LoopTimeout ,
  LoopWakeUp ,
  LoopWork ,
  ProcessExit ,
  SocketAccept ,
  SocketConnect ,
  SocketSend ,
  SocketReceive ,
  SocketClose ,
  FileRead ,
  FileWrite ,
  FileClose ,
  FilePoll
}
 Type of async request. More...
 

Public Member Functions

SC::Result start (AsyncEventLoop &eventLoop)
 Starts a file receive operation, that completes when data has been read from file / pipe. More...
 
uint64_t getOffset () const
 The file/pipe descriptor handle to read data from. More...
 
void setOffset (uint64_t fileOffset)
 Sets the offset in bytes at which start reading. More...
 
- Public Member Functions inherited from SC::AsyncRequest
void setDebugName (const char *newDebugName)
 
AsyncEventLoopgetEventLoop () const
 Get the event loop associated with this AsyncRequest. More...
 
void cacheInternalEventLoop (AsyncEventLoop &loop)
 Caches the event loop associated with this AsyncRequest. More...
 
Result setThreadPoolAndTask (ThreadPool &pool, AsyncTask &task)
 Sets the thread pool and task to use for this request. More...
 
void resetThreadPoolAndTask ()
 Resets anything previously set with setThreadPoolAndTask. More...
 
 AsyncRequest (Type type)
 Constructs a free async request of given type. More...
 
Result stop ()
 Stops the async operation. More...
 
bool isFree () const
 

Public Attributes

Function< void(Result &)> callback
 
Span< char > buffer
 Callback called when some data has been read from the file into the buffer. More...
 
FileDescriptor::Handle fileDescriptor
 The writeable span of memory where to data will be written. More...
 
- Public Attributes inherited from SC::AsyncRequest
AsyncRequestnext = nullptr
 
AsyncRequestprev = nullptr
 

Friends

struct AsyncEventLoop
 

Additional Inherited Members

- Protected Member Functions inherited from SC::AsyncRequest
Result validateAsync ()
 
void queueSubmission (AsyncEventLoop &eventLoop)
 
- Protected Attributes inherited from SC::AsyncRequest
AsyncEventLoopeventLoop = nullptr
 
AsyncTaskasyncTask = nullptr
 

Detailed Description

Starts a file read operation, reading bytes from a file (or pipe).

Callback will be called when the data read from the file (or pipe) is available.
Call AsyncRequest::setThreadPoolAndTask to set a thread pool if this is a buffered file and not a pipe. This is important on APIs with blocking behaviour on buffered file I/O (all apis with the exception of io_uring).

File library can be used to open the file and obtain a file (or pipe) descriptor handle.

Note
Pipes or files opened using Posix O_DIRECT or Windows FILE_FLAG_WRITE_THROUGH & FILE_FLAG_NO_BUFFERING should instead avoid using the Task parameter for best performance.

When not using the Task remember to:

Additional notes:

  • When reactivating the AsyncRequest, remember to increment the offset (SC::AsyncFileRead::offset)
  • SC::AsyncFileRead::CompletionData::endOfFile signals end of file reached
// Assuming an already created (and running) AsyncEventLoop named `eventLoop`
// ...
// Assuming an already created threadPool named `eventLoop
// ...
// Open the file
FileDescriptor fd;
FileDescriptor::OpenOptions options;
options.blocking = true; // AsyncFileRead::Task enables using regular blocking file descriptors
SC_TRY(fd.open("MyFile.txt", FileDescriptor::ReadOnly, options));
// Create the async file read request and async task
AsyncFileRead asyncReadFile;
asyncReadFile.callback = [&](AsyncFileRead::Result& res)
{
Span<char> readData;
if(res.get(readData))
{
if(res.completionData.endOfFile)
{
// Last callback invocation done when end of file has been reached
// - completionData.endOfFile is == true
// - readData.sizeInBytes() is == 0
console.print("End of file reached");
}
else
{
// readData is a slice of receivedData with the received bytes
console.print("Read {} bytes from file", readData.sizeInBytes());
// OPTIONAL: Update file offset to receive a different range of bytes
res.getAsync().setOffset(res.getAsync().getOffset() + readData.sizeInBytes());
// IMPORTANT: Reactivate the request to receive more data
res.reactivateRequest(true);
}
}
else
{
// Some error occurred, check res.returnCode
}
};
char buffer[100] = {0};
asyncReadFile.buffer = {buffer, sizeof(buffer)};
// Obtain file descriptor handle and associate it with event loop
SC_TRY(fd.get(asyncReadFile.fileDescriptor, Result::Error("Invalid handle")));
// Start the operation on a thread pool
AsyncFileRead::Task asyncFileTask;
SC_TRY(asyncReadFile.setThreadPoolAndTask(threadPool, asyncFileTask));
SC_TRY(asyncReadFile.start(eventLoop));
// Alternatively if the file is opened with blocking == false, AsyncFileRead can be omitted
// but the operation will not be fully async on regular (buffered) files, except on io_uring.
//
// SC_TRY(asyncReadFile.start(eventLoop));
#define SC_TRY(expression)
Checks the value of the given expression and if failed, returns this value to caller.
Definition: Result.h:48
Span< char > buffer
Callback called when some data has been read from the file into the buffer.
Definition: Async.h:749
@ ReadOnly
Opens in read-only mode.
Definition: FileDescriptor.h:62
static constexpr Result Error(const char(&msg)[numChars])
Constructs an Error from a pointer to an ASCII string literal.
Definition: Result.h:24

Member Function Documentation

◆ getOffset()

uint64_t SC::AsyncFileRead::getOffset ( ) const
inline

The file/pipe descriptor handle to read data from.

Use SC::FileDescriptor or SC::PipeDescriptor to open it.

Returns the last offset set with AsyncFileRead::setOffset

◆ setOffset()

void SC::AsyncFileRead::setOffset ( uint64_t  fileOffset)
inline

Sets the offset in bytes at which start reading.

Note
Setting file offset when reading is only possible on seekable files

◆ start()

SC::Result SC::AsyncFileRead::start ( AsyncEventLoop eventLoop)

Starts a file receive operation, that completes when data has been read from file / pipe.

Parameters
eventLoopThe EventLoop to run this operation on
Note
  • Use AsyncRequest::setThreadPoolAndTask to set a thread pool and task prior to start.
  • Only files opened for direct IO (O_DIRECT / FILE_FLAG_WRITE_THROUGH & FILE_FLAG_NO_BUFFERING) can be used in non-blocking mode (OpenOptions::blocking == false) without a thread pool and SC::AsyncEventLoop::associateExternallyCreatedFileDescriptor must have been called on the passed in handle.
  • io_uring backend will not use thread pool because that API allows proper async file read/writes.

Member Data Documentation

◆ buffer

Span<char> SC::AsyncFileRead::buffer

Callback called when some data has been read from the file into the buffer.

◆ fileDescriptor

FileDescriptor::Handle SC::AsyncFileRead::fileDescriptor

The writeable span of memory where to data will be written.


The documentation for this struct was generated from the following file: