mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-12 06:38:45 +01:00
Add module for Scheduler.
Also reorganizes some code to make it easier to add more modules.
This commit is contained in:
@ -8,6 +8,11 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
2901D7641B74F4050083A2C8 /* timer.c in Sources */ = {isa = PBXBuildFile; fileRef = 2901D7621B74F4050083A2C8 /* timer.c */; };
|
||||
291647C41BA5EA45006142EE /* scheduler.c in Sources */ = {isa = PBXBuildFile; fileRef = 291647C21BA5EA45006142EE /* scheduler.c */; };
|
||||
291647C71BA5EC5E006142EE /* modules.c in Sources */ = {isa = PBXBuildFile; fileRef = 291647C51BA5EC5E006142EE /* modules.c */; };
|
||||
291647C81BA5EC5E006142EE /* modules.c in Sources */ = {isa = PBXBuildFile; fileRef = 291647C51BA5EC5E006142EE /* modules.c */; };
|
||||
291647D01BA5ED26006142EE /* scheduler.wren.inc in Sources */ = {isa = PBXBuildFile; fileRef = 291647CD1BA5ED26006142EE /* scheduler.wren.inc */; };
|
||||
291647D21BA5ED26006142EE /* timer.wren.inc in Sources */ = {isa = PBXBuildFile; fileRef = 291647CE1BA5ED26006142EE /* timer.wren.inc */; };
|
||||
29205C8F1AB4E5C90073018D /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C8E1AB4E5C90073018D /* main.c */; };
|
||||
29205C991AB4E6430073018D /* wren_compiler.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C921AB4E6430073018D /* wren_compiler.c */; };
|
||||
29205C9A1AB4E6430073018D /* wren_core.c in Sources */ = {isa = PBXBuildFile; fileRef = 29205C931AB4E6430073018D /* wren_core.c */; };
|
||||
@ -48,6 +53,12 @@
|
||||
/* Begin PBXFileReference section */
|
||||
2901D7621B74F4050083A2C8 /* timer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = timer.c; path = ../../src/module/timer.c; sourceTree = "<group>"; };
|
||||
2901D7631B74F4050083A2C8 /* timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = timer.h; path = ../../src/module/timer.h; sourceTree = "<group>"; };
|
||||
291647C21BA5EA45006142EE /* scheduler.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = scheduler.c; path = ../../src/module/scheduler.c; sourceTree = "<group>"; };
|
||||
291647C31BA5EA45006142EE /* scheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = scheduler.h; path = ../../src/module/scheduler.h; sourceTree = "<group>"; };
|
||||
291647C51BA5EC5E006142EE /* modules.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = modules.c; path = ../../src/cli/modules.c; sourceTree = "<group>"; };
|
||||
291647C61BA5EC5E006142EE /* modules.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = modules.h; path = ../../src/cli/modules.h; sourceTree = "<group>"; };
|
||||
291647CD1BA5ED26006142EE /* scheduler.wren.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = scheduler.wren.inc; path = ../../src/module/scheduler.wren.inc; sourceTree = "<group>"; };
|
||||
291647CE1BA5ED26006142EE /* timer.wren.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = timer.wren.inc; path = ../../src/module/timer.wren.inc; sourceTree = "<group>"; };
|
||||
29205C8E1AB4E5C90073018D /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = main.c; path = ../../src/cli/main.c; sourceTree = "<group>"; };
|
||||
29205C901AB4E62B0073018D /* wren.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = wren.h; path = ../../src/include/wren.h; sourceTree = "<group>"; };
|
||||
29205C921AB4E6430073018D /* wren_compiler.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = wren_compiler.c; path = ../../src/vm/wren_compiler.c; sourceTree = "<group>"; };
|
||||
@ -109,8 +120,12 @@
|
||||
2901D7611B74F3E20083A2C8 /* module */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
291647C31BA5EA45006142EE /* scheduler.h */,
|
||||
291647C21BA5EA45006142EE /* scheduler.c */,
|
||||
291647CD1BA5ED26006142EE /* scheduler.wren.inc */,
|
||||
2901D7631B74F4050083A2C8 /* timer.h */,
|
||||
2901D7621B74F4050083A2C8 /* timer.c */,
|
||||
291647CE1BA5ED26006142EE /* timer.wren.inc */,
|
||||
);
|
||||
name = module;
|
||||
sourceTree = "<group>";
|
||||
@ -148,6 +163,8 @@
|
||||
29C8A9301AB71C3300DEC81D /* io.h */,
|
||||
29C8A92E1AB71C1C00DEC81D /* io.c */,
|
||||
29205C8E1AB4E5C90073018D /* main.c */,
|
||||
291647C61BA5EC5E006142EE /* modules.h */,
|
||||
291647C51BA5EC5E006142EE /* modules.c */,
|
||||
29C8A9321AB71FFF00DEC81D /* vm.h */,
|
||||
29C8A9311AB71FFF00DEC81D /* vm.c */,
|
||||
);
|
||||
@ -274,9 +291,11 @@
|
||||
files = (
|
||||
29205C991AB4E6430073018D /* wren_compiler.c in Sources */,
|
||||
2986F6D71ACF93BA00BCE26C /* wren_primitive.c in Sources */,
|
||||
291647C71BA5EC5E006142EE /* modules.c in Sources */,
|
||||
29205C9A1AB4E6430073018D /* wren_core.c in Sources */,
|
||||
2901D7641B74F4050083A2C8 /* timer.c in Sources */,
|
||||
29C8A9331AB71FFF00DEC81D /* vm.c in Sources */,
|
||||
291647C41BA5EA45006142EE /* scheduler.c in Sources */,
|
||||
29205C9B1AB4E6430073018D /* wren_debug.c in Sources */,
|
||||
29205C9C1AB4E6430073018D /* wren_io.c in Sources */,
|
||||
29205C9D1AB4E6430073018D /* wren_utils.c in Sources */,
|
||||
@ -292,6 +311,9 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
291647C81BA5EC5E006142EE /* modules.c in Sources */,
|
||||
291647D21BA5ED26006142EE /* timer.wren.inc in Sources */,
|
||||
291647D01BA5ED26006142EE /* scheduler.wren.inc in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -379,7 +401,7 @@
|
||||
GCC_WARN_PEDANTIC = NO;
|
||||
LIBRARY_SEARCH_PATHS = ../../build;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
USER_HEADER_SEARCH_PATHS = ../../deps/libuv/include;
|
||||
USER_HEADER_SEARCH_PATHS = "../../deps/libuv/include ../../src/module";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@ -392,7 +414,7 @@
|
||||
GCC_WARN_PEDANTIC = NO;
|
||||
LIBRARY_SEARCH_PATHS = ../../build;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
USER_HEADER_SEARCH_PATHS = ../../deps/libuv/include;
|
||||
USER_HEADER_SEARCH_PATHS = "../../deps/libuv/include ../../src/module";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@ -416,7 +438,7 @@
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
USER_HEADER_SEARCH_PATHS = ../../deps/libuv/include;
|
||||
USER_HEADER_SEARCH_PATHS = "../../deps/libuv/include ../../src/module";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@ -436,7 +458,7 @@
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
USER_HEADER_SEARCH_PATHS = ../../deps/libuv/include;
|
||||
USER_HEADER_SEARCH_PATHS = "../../deps/libuv/include ../../src/module";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
@ -153,7 +153,8 @@ lib/lib$(WREN).$(SHARED_EXT): $(VM_OBJECTS)
|
||||
|
||||
# Test executable.
|
||||
$(BUILD_DIR)/test/$(WREN): $(TEST_OBJECTS) $(MODULE_OBJECTS) $(VM_OBJECTS) \
|
||||
$(BUILD_DIR)/cli/io.o $(BUILD_DIR)/cli/vm.o $(LIBUV)
|
||||
$(BUILD_DIR)/cli/io.o $(BUILD_DIR)/cli/modules.o $(BUILD_DIR)/cli/vm.o \
|
||||
$(LIBUV)
|
||||
@ printf "%10s %-30s %s\n" $(CC) $@ "$(C_OPTIONS)"
|
||||
@ mkdir -p $(BUILD_DIR)/test
|
||||
@ $(CC) $(CFLAGS) $^ -o $@ -lm $(LIBUV_LIBS)
|
||||
|
||||
@ -3,8 +3,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "io.h"
|
||||
|
||||
#include "timer.h"
|
||||
#include "modules.h"
|
||||
|
||||
char const* rootDirectory = NULL;
|
||||
|
||||
@ -73,7 +72,8 @@ char* wrenFilePath(const char* name)
|
||||
|
||||
char* readModule(WrenVM* vm, const char* module)
|
||||
{
|
||||
if (strcmp(module, "timer") == 0) return timerGetSource();
|
||||
char* source = readBuiltInModule(module);
|
||||
if (source != NULL) return source;
|
||||
|
||||
// First try to load the module with a ".wren" extension.
|
||||
char* modulePath = wrenFilePath(module);
|
||||
|
||||
83
src/cli/modules.c
Normal file
83
src/cli/modules.c
Normal file
@ -0,0 +1,83 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "modules.h"
|
||||
|
||||
#include "scheduler.wren.inc"
|
||||
#include "timer.wren.inc"
|
||||
|
||||
#include "scheduler.h"
|
||||
#include "timer.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// The name of the module.
|
||||
const char* name;
|
||||
|
||||
// Pointer to the string containing the source code of the module. We use a
|
||||
// pointer here because the string variable itself is not a constant
|
||||
// expression so can't be used in the initializer below.
|
||||
const char **source;
|
||||
|
||||
// The function that binds foreign methods in this module.
|
||||
WrenForeignMethodFn (*bindMethodFn)(WrenVM* vm, const char* className,
|
||||
bool isStatic, const char* signature);
|
||||
|
||||
// The function that binds foreign classes in this module.
|
||||
WrenForeignClassMethods (*bindClassFn)(WrenVM* vm, const char* className);
|
||||
} BuiltInModule;
|
||||
|
||||
// The array of built-in modules.
|
||||
static BuiltInModule modules[] =
|
||||
{
|
||||
{"scheduler", &schedulerModuleSource, schedulerBindForeign, NULL},
|
||||
{"timer", &timerModuleSource, timerBindForeign, NULL},
|
||||
|
||||
// Sentinel marking the end of the list.
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
// Looks for a built-in module with [name].
|
||||
//
|
||||
// Returns the BuildInModule for it or NULL if not found.
|
||||
static BuiltInModule* findModule(const char* name)
|
||||
{
|
||||
for (int i = 0; modules[i].name != NULL; i++)
|
||||
{
|
||||
if (strcmp(name, modules[i].name) == 0) return &modules[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* readBuiltInModule(const char* name)
|
||||
{
|
||||
BuiltInModule* module = findModule(name);
|
||||
if (module == NULL) return NULL;
|
||||
|
||||
size_t length = strlen(*module->source);
|
||||
char* copy = (char*)malloc(length + 1);
|
||||
strncpy(copy, *module->source, length + 1);
|
||||
return copy;
|
||||
}
|
||||
|
||||
WrenForeignMethodFn bindBuiltInForeignMethod(
|
||||
WrenVM* vm, const char* moduleName, const char* className, bool isStatic,
|
||||
const char* signature)
|
||||
{
|
||||
BuiltInModule* module = findModule(moduleName);
|
||||
if (module == NULL) return NULL;
|
||||
|
||||
return module->bindMethodFn(vm, className, isStatic, signature);
|
||||
}
|
||||
|
||||
WrenForeignClassMethods bindBuiltInForeignClass(
|
||||
WrenVM* vm, const char* moduleName, const char* className)
|
||||
{
|
||||
WrenForeignClassMethods methods = { NULL, NULL };
|
||||
|
||||
BuiltInModule* module = findModule(moduleName);
|
||||
if (module == NULL) return methods;
|
||||
|
||||
return module->bindClassFn(vm, className);
|
||||
}
|
||||
19
src/cli/modules.h
Normal file
19
src/cli/modules.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef modules_h
|
||||
#define modules_h
|
||||
|
||||
#include "wren.h"
|
||||
|
||||
char* readBuiltInModule(const char* module);
|
||||
|
||||
// Looks up a foreign method in a built-in module.
|
||||
//
|
||||
// Returns `NULL` if [moduleName] is not a built-in module.
|
||||
WrenForeignMethodFn bindBuiltInForeignMethod(
|
||||
WrenVM* vm, const char* moduleName, const char* className, bool isStatic,
|
||||
const char* signature);
|
||||
|
||||
// Binds foreign classes declared in a built-in modules.
|
||||
WrenForeignClassMethods bindBuiltInForeignClass(
|
||||
WrenVM* vm, const char* moduleName, const char* className);
|
||||
|
||||
#endif
|
||||
28
src/cli/vm.c
28
src/cli/vm.c
@ -2,8 +2,9 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "io.h"
|
||||
#include "modules.h"
|
||||
#include "vm.h"
|
||||
#include "timer.h"
|
||||
#include "scheduler.h"
|
||||
|
||||
#define MAX_LINE_LENGTH 1024 // TODO: Something less arbitrary.
|
||||
|
||||
@ -15,16 +16,15 @@ static WrenBindForeignClassFn bindClassFn = NULL;
|
||||
|
||||
uv_loop_t* loop;
|
||||
|
||||
/// Binds foreign methods declared in either built in modules, or the injected
|
||||
/// API test modules.
|
||||
// Binds foreign methods declared in either built in modules, or the injected
|
||||
// API test modules.
|
||||
static WrenForeignMethodFn bindForeignMethod(WrenVM* vm, const char* module,
|
||||
const char* className, bool isStatic, const char* signature)
|
||||
{
|
||||
if (strcmp(module, "timer") == 0)
|
||||
{
|
||||
return timerBindForeign(vm, className, isStatic, signature);
|
||||
}
|
||||
|
||||
WrenForeignMethodFn method = bindBuiltInForeignMethod(vm, module, className,
|
||||
isStatic, signature);
|
||||
if (method != NULL) return method;
|
||||
|
||||
if (bindMethodFn != NULL)
|
||||
{
|
||||
return bindMethodFn(vm, module, className, isStatic, signature);
|
||||
@ -33,14 +33,14 @@ static WrenForeignMethodFn bindForeignMethod(WrenVM* vm, const char* module,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Binds foreign classes declared in either built in modules, or the injected
|
||||
/// API test modules.
|
||||
// Binds foreign classes declared in either built in modules, or the injected
|
||||
// API test modules.
|
||||
static WrenForeignClassMethods bindForeignClass(
|
||||
WrenVM* vm, const char* module, const char* className)
|
||||
{
|
||||
WrenForeignClassMethods methods = { NULL, NULL };
|
||||
|
||||
// TODO: Bind classes for built-in modules here.
|
||||
WrenForeignClassMethods methods = bindBuiltInForeignClass(vm, module,
|
||||
className);
|
||||
if (methods.allocate != NULL) return methods;
|
||||
|
||||
if (bindClassFn != NULL)
|
||||
{
|
||||
@ -70,7 +70,7 @@ static void initVM()
|
||||
|
||||
static void freeVM()
|
||||
{
|
||||
timerReleaseMethods();
|
||||
schedulerReleaseMethods();
|
||||
|
||||
uv_loop_close(loop);
|
||||
free(loop);
|
||||
|
||||
42
src/module/scheduler.c
Normal file
42
src/module/scheduler.c
Normal file
@ -0,0 +1,42 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "uv.h"
|
||||
|
||||
#include "scheduler.h"
|
||||
#include "wren.h"
|
||||
#include "vm.h"
|
||||
|
||||
// This method resumes a fiber that is suspended waiting on an asynchronous
|
||||
// operation. The first resumes it with zero arguments, and the second passes
|
||||
// one.
|
||||
static WrenValue* resume;
|
||||
static WrenValue* resumeWithArg;
|
||||
|
||||
static void captureMethods(WrenVM* vm)
|
||||
{
|
||||
resume = wrenGetMethod(vm, "scheduler", "Scheduler", "resume_(_)");
|
||||
resumeWithArg = wrenGetMethod(vm, "scheduler", "Scheduler", "resume_(_,_)");
|
||||
}
|
||||
|
||||
WrenForeignMethodFn schedulerBindForeign(
|
||||
WrenVM* vm, const char* className, bool isStatic, const char* signature)
|
||||
{
|
||||
if (strcmp(className, "Scheduler") != 0) return NULL;
|
||||
|
||||
if (isStatic && strcmp(signature, "captureMethods_()") == 0) return captureMethods;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void schedulerResume(WrenValue* fiber)
|
||||
{
|
||||
wrenCall(getVM(), resume, NULL, "v", fiber);
|
||||
wrenReleaseValue(getVM(), fiber);
|
||||
}
|
||||
|
||||
void schedulerReleaseMethods()
|
||||
{
|
||||
if (resume != NULL) wrenReleaseValue(getVM(), resume);
|
||||
if (resumeWithArg != NULL) wrenReleaseValue(getVM(), resumeWithArg);
|
||||
}
|
||||
13
src/module/scheduler.h
Normal file
13
src/module/scheduler.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef scheduler_h
|
||||
#define scheduler_h
|
||||
|
||||
#include "wren.h"
|
||||
|
||||
WrenForeignMethodFn schedulerBindForeign(
|
||||
WrenVM* vm, const char* className, bool isStatic, const char* signature);
|
||||
|
||||
void schedulerResume(WrenValue* fiber);
|
||||
|
||||
void schedulerReleaseMethods();
|
||||
|
||||
#endif
|
||||
26
src/module/scheduler.wren
Normal file
26
src/module/scheduler.wren
Normal file
@ -0,0 +1,26 @@
|
||||
class Scheduler {
|
||||
static add(callable) {
|
||||
if (__scheduled == null) __scheduled = []
|
||||
|
||||
__scheduled.add(Fiber.new {
|
||||
callable.call()
|
||||
runNextScheduled_()
|
||||
})
|
||||
}
|
||||
|
||||
// Called by native code.
|
||||
static resume_(fiber) { fiber.transfer() }
|
||||
static resume_(fiber, arg) { fiber.transfer(arg) }
|
||||
|
||||
static runNextScheduled_() {
|
||||
if (__scheduled == null || __scheduled.isEmpty) {
|
||||
return Fiber.suspend()
|
||||
} else {
|
||||
return __scheduled.removeAt(0).transfer()
|
||||
}
|
||||
}
|
||||
|
||||
foreign static captureMethods_()
|
||||
}
|
||||
|
||||
Scheduler.captureMethods_()
|
||||
28
src/module/scheduler.wren.inc
Normal file
28
src/module/scheduler.wren.inc
Normal file
@ -0,0 +1,28 @@
|
||||
// Generated automatically from src/module/scheduler.wren. Do not edit.
|
||||
static const char* schedulerModuleSource =
|
||||
"class Scheduler {\n"
|
||||
" static add(callable) {\n"
|
||||
" if (__scheduled == null) __scheduled = []\n"
|
||||
"\n"
|
||||
" __scheduled.add(Fiber.new {\n"
|
||||
" callable.call()\n"
|
||||
" runNextScheduled_()\n"
|
||||
" })\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // Called by native code.\n"
|
||||
" static resume_(fiber) { fiber.transfer() }\n"
|
||||
" static resume_(fiber, arg) { fiber.transfer(arg) }\n"
|
||||
"\n"
|
||||
" static runNextScheduled_() {\n"
|
||||
" if (__scheduled == null || __scheduled.isEmpty) {\n"
|
||||
" return Fiber.suspend()\n"
|
||||
" } else {\n"
|
||||
" return __scheduled.removeAt(0).transfer()\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" foreign static captureMethods_()\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"Scheduler.captureMethods_()\n";
|
||||
@ -3,14 +3,10 @@
|
||||
|
||||
#include "uv.h"
|
||||
|
||||
#include "scheduler.h"
|
||||
#include "timer.h"
|
||||
#include "wren.h"
|
||||
#include "vm.h"
|
||||
|
||||
#include "timer.wren.inc"
|
||||
|
||||
// The Wren method to call when a timer has completed.
|
||||
static WrenValue* resumeTimer;
|
||||
#include "wren.h"
|
||||
|
||||
// Called by libuv when the timer finished closing.
|
||||
static void timerCloseCallback(uv_handle_t* handle)
|
||||
@ -27,18 +23,11 @@ static void timerCallback(uv_timer_t* handle)
|
||||
uv_close((uv_handle_t*)handle, timerCloseCallback);
|
||||
|
||||
// Run the fiber that was sleeping.
|
||||
wrenCall(getVM(), resumeTimer, NULL, "v", fiber);
|
||||
wrenReleaseValue(getVM(), fiber);
|
||||
schedulerResume(fiber);
|
||||
}
|
||||
|
||||
static void startTimer(WrenVM* vm)
|
||||
{
|
||||
// If we haven't looked up the resume method yet, grab it now.
|
||||
if (resumeTimer == NULL)
|
||||
{
|
||||
resumeTimer = wrenGetMethod(vm, "timer", "Timer", "resumeTimer_(_)");
|
||||
}
|
||||
|
||||
int milliseconds = (int)wrenGetArgumentDouble(vm, 1);
|
||||
WrenValue* fiber = wrenGetArgumentValue(vm, 2);
|
||||
|
||||
@ -50,15 +39,6 @@ static void startTimer(WrenVM* vm)
|
||||
uv_timer_start(handle, timerCallback, milliseconds, 0);
|
||||
}
|
||||
|
||||
char* timerGetSource()
|
||||
{
|
||||
size_t length = strlen(timerModuleSource);
|
||||
char* copy = (char*)malloc(length + 1);
|
||||
strncpy(copy, timerModuleSource, length + 1);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
WrenForeignMethodFn timerBindForeign(
|
||||
WrenVM* vm, const char* className, bool isStatic, const char* signature)
|
||||
{
|
||||
@ -68,8 +48,3 @@ WrenForeignMethodFn timerBindForeign(
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void timerReleaseMethods()
|
||||
{
|
||||
if (resumeTimer != NULL) wrenReleaseValue(getVM(), resumeTimer);
|
||||
}
|
||||
|
||||
@ -3,11 +3,7 @@
|
||||
|
||||
#include "wren.h"
|
||||
|
||||
char* timerGetSource();
|
||||
|
||||
WrenForeignMethodFn timerBindForeign(
|
||||
WrenVM* vm, const char* className, bool isStatic, const char* signature);
|
||||
|
||||
void timerReleaseMethods();
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,34 +1,13 @@
|
||||
import "scheduler" for Scheduler
|
||||
|
||||
class Timer {
|
||||
static sleep(milliseconds) {
|
||||
if (!(milliseconds is Num)) Fiber.abort("Milliseconds must be a number.")
|
||||
if (milliseconds < 0) Fiber.abort("Milliseconds cannot be negative.")
|
||||
|
||||
startTimer_(milliseconds, Fiber.current)
|
||||
|
||||
runNextScheduled_()
|
||||
}
|
||||
|
||||
// TODO: Once the CLI modules are more fleshed out, find a better place to
|
||||
// put this.
|
||||
static schedule(callable) {
|
||||
if (__scheduled == null) __scheduled = []
|
||||
__scheduled.add(Fiber.new {
|
||||
callable.call()
|
||||
runNextScheduled_()
|
||||
})
|
||||
Scheduler.runNextScheduled_()
|
||||
}
|
||||
|
||||
foreign static startTimer_(milliseconds, fiber)
|
||||
|
||||
// Called by native code.
|
||||
static resumeTimer_(fiber) {
|
||||
fiber.transfer()
|
||||
}
|
||||
|
||||
static runNextScheduled_() {
|
||||
if (__scheduled == null || __scheduled.isEmpty) {
|
||||
Fiber.suspend()
|
||||
} else {
|
||||
__scheduled.removeAt(0).transfer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,36 +1,15 @@
|
||||
// Generated automatically from src/module/timer.wren. Do not edit.
|
||||
static const char* timerModuleSource =
|
||||
"import \"scheduler\" for Scheduler\n"
|
||||
"\n"
|
||||
"class Timer {\n"
|
||||
" static sleep(milliseconds) {\n"
|
||||
" if (!(milliseconds is Num)) Fiber.abort(\"Milliseconds must be a number.\")\n"
|
||||
" if (milliseconds < 0) Fiber.abort(\"Milliseconds cannot be negative.\")\n"
|
||||
"\n"
|
||||
" startTimer_(milliseconds, Fiber.current)\n"
|
||||
"\n"
|
||||
" runNextScheduled_()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // TODO: Once the CLI modules are more fleshed out, find a better place to\n"
|
||||
" // put this.\n"
|
||||
" static schedule(callable) {\n"
|
||||
" if (__scheduled == null) __scheduled = []\n"
|
||||
" __scheduled.add(Fiber.new {\n"
|
||||
" callable.call()\n"
|
||||
" runNextScheduled_()\n"
|
||||
" })\n"
|
||||
" Scheduler.runNextScheduled_()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" foreign static startTimer_(milliseconds, fiber)\n"
|
||||
"\n"
|
||||
" // Called by native code.\n"
|
||||
" static resumeTimer_(fiber) {\n"
|
||||
" fiber.transfer()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static runNextScheduled_() {\n"
|
||||
" if (__scheduled == null || __scheduled.isEmpty) {\n"
|
||||
" Fiber.suspend()\n"
|
||||
" } else {\n"
|
||||
" __scheduled.removeAt(0).transfer()\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
15
test/scheduler/add.wren
Normal file
15
test/scheduler/add.wren
Normal file
@ -0,0 +1,15 @@
|
||||
import "scheduler" for Scheduler
|
||||
import "timer" for Timer
|
||||
|
||||
var run = false
|
||||
Scheduler.add {
|
||||
run = true
|
||||
}
|
||||
|
||||
// Does not run immediately.
|
||||
IO.print(run) // expect: false
|
||||
|
||||
Timer.sleep(0)
|
||||
|
||||
// Runs when the main fiber suspends on IO.
|
||||
IO.print(run) // expect: true
|
||||
@ -1,11 +1,12 @@
|
||||
import "scheduler" for Scheduler
|
||||
import "timer" for Timer
|
||||
|
||||
Timer.schedule {
|
||||
Scheduler.add {
|
||||
Timer.sleep(2)
|
||||
IO.print("a")
|
||||
}
|
||||
|
||||
Timer.schedule {
|
||||
Scheduler.add {
|
||||
Timer.sleep(1)
|
||||
IO.print("b")
|
||||
}
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import "scheduler" for Scheduler
|
||||
import "timer" for Timer
|
||||
|
||||
// These are both rounded to 1, so "a" should complete first.
|
||||
Timer.schedule {
|
||||
Scheduler.add {
|
||||
Timer.sleep(1.5)
|
||||
IO.print("a")
|
||||
}
|
||||
|
||||
Timer.schedule {
|
||||
Scheduler.add {
|
||||
Timer.sleep(1.3)
|
||||
IO.print("b")
|
||||
}
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import "scheduler" for Scheduler
|
||||
import "timer" for Timer
|
||||
|
||||
Timer.schedule {
|
||||
Scheduler.add {
|
||||
IO.print("a before")
|
||||
Timer.sleep(0)
|
||||
IO.print("a after")
|
||||
}
|
||||
|
||||
Timer.schedule {
|
||||
Scheduler.add {
|
||||
IO.print("b before")
|
||||
Timer.sleep(0)
|
||||
IO.print("b after")
|
||||
|
||||
Reference in New Issue
Block a user