feat: implement async file I/O with open/close/readBytes and scheduler error handling

Add foreign class File with static open, read, size methods and instance methods for close, size, readBytes. Implement async file operations using libuv callbacks that resume fibers on completion. Introduce schedulerResumeError and resumeError_ to propagate I/O errors as fiber errors. Add setExitCode to CLI vm for runtime error exit handling. Bump MAX_METHODS_PER_CLASS from 2 to 9 to accommodate new File methods.
This commit is contained in:
Bob Nystrom
2015-10-01 04:13:36 +00:00
parent af90291f6f
commit 8fd9449196
32 changed files with 475 additions and 44 deletions
+17 -3
View File
@@ -7,7 +7,14 @@
#include "scheduler.wren.inc"
#include "timer.wren.inc"
extern void fileStartSize(WrenVM* vm);
extern void fileAllocate(WrenVM* vm);
extern void fileFinalize(WrenVM* vm);
extern void fileOpen(WrenVM* vm);
extern void fileSizePath(WrenVM* vm);
extern void fileClose(WrenVM* vm);
extern void fileDescriptor(WrenVM* vm);
extern void fileReadBytes(WrenVM* vm);
extern void fileSize(WrenVM* vm);
extern void schedulerCaptureMethods(WrenVM* vm);
extern void timerStartTimer(WrenVM* vm);
@@ -19,7 +26,7 @@ extern void timerStartTimer(WrenVM* vm);
// If you add a new method to the longest class below, make sure to bump this.
// Note that it also includes an extra slot for the sentinel value indicating
// the end of the list.
#define MAX_METHODS_PER_CLASS 2
#define MAX_METHODS_PER_CLASS 9
// The maximum number of foreign classes a single built-in module defines.
//
@@ -75,7 +82,14 @@ static ModuleRegistry modules[] =
{
MODULE(io)
CLASS(File)
STATIC_METHOD("startSize_(_,_)", fileStartSize)
STATIC_METHOD("<allocate>", fileAllocate)
STATIC_METHOD("<finalize>", fileFinalize)
STATIC_METHOD("open_(_,_)", fileOpen)
STATIC_METHOD("sizePath_(_,_)", fileSizePath)
METHOD("close_(_)", fileClose)
METHOD("descriptor", fileDescriptor)
METHOD("readBytes_(_,_)", fileReadBytes)
METHOD("size_(_)", fileSize)
END_CLASS
END_MODULE
+10
View File
@@ -18,6 +18,9 @@ static uv_loop_t* loop;
static char const* rootDirectory = NULL;
// The exit code to use unless some other error overrides it.
int defaultExitCode = 0;
// Reads the contents of the file at [path] and returns it as a heap allocated
// string.
//
@@ -220,6 +223,8 @@ void runFile(const char* path)
// Exit with an error code if the script failed.
if (result == WREN_RESULT_COMPILE_ERROR) exit(65); // EX_DATAERR.
if (result == WREN_RESULT_RUNTIME_ERROR) exit(70); // EX_SOFTWARE.
if (defaultExitCode != 0) exit(defaultExitCode);
}
int runRepl()
@@ -262,6 +267,11 @@ uv_loop_t* getLoop()
return loop;
}
void setExitCode(int exitCode)
{
defaultExitCode = exitCode;
}
void setTestCallbacks(WrenBindForeignMethodFn bindMethod,
WrenBindForeignClassFn bindClass,
WrenForeignMethodFn afterLoad)
+3
View File
@@ -18,6 +18,9 @@ WrenVM* getVM();
// Gets the event loop the VM is using.
uv_loop_t* getLoop();
// Set the exit code the CLI should exit with when done.
void setExitCode(int exitCode);
// Adds additional callbacks to use when binding foreign members from Wren.
//
// Used by the API test executable to let it wire up its own foreign functions.