changeset 140:c14698c512f1

Untested addition of Pause/Resume
author Mike Pavone <pavone@retrodev.com>
date Sat, 20 Nov 2010 20:03:25 +0000
parents a68e6828d896
children f2cb85c53ced
files cbackend_c.rhope nworker_c.rhope runtime/builtin.c runtime/builtin.h runtime/context.c runtime/context.h runtime/func.h testpauseresume.rhope
diffstat 8 files changed, 201 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/cbackend_c.rhope	Fri Nov 19 04:04:14 2010 -0500
+++ b/cbackend_c.rhope	Sat Nov 20 20:03:25 2010 +0000
@@ -1509,14 +1509,14 @@
 {
 	out <- [[[[["typedef enum {\n"
 		]Append[Fold[_Dispatch Enum[?], 
-			[Fold[_Dispatch Enum Methods[[program]Escape Pattern >>,?], "", all methods]]Append["\tFUNC_Build,\n\tFUNC_BlueprintSP_Of,\n\tFUNC_ID,\n\tFUNC_BlueprintSP_FromSP_ID,\n"], 
+			[Fold[_Dispatch Enum Methods[[program]Escape Pattern >>,?], "", all methods]]Append["\tFUNC_Build,\n\tFUNC_BlueprintSP_Of,\n\tFUNC_ID,\n\tFUNC_BlueprintSP_FromSP_ID,\n\tFUNC_Pause,\n\tRES_1_Pause,\n\tFUNC_Resume,\n\tFUNC_CallSP_Async,\n"], 
 			[program]Functions >>]]
-		]Append["\tEND\n} funcids;\n\n"]
+		]Append["\tEND,\n\tEND_THREAD\n} funcids;\n\n"]
 		]Append["#define DispatchEntries \\\n"] 
 		]Append[Fold[_Dispatch Switch[?], 
-			[Fold[_Dispatch Switch Methods[[program]Escape Pattern >>,?], "", all methods]]Append["\tDispatchEntry(Build)\\\n\tDispatchEntry(BlueprintSP_Of)\\\n\tDispatchEntry(ID)\\\n\tDispatchEntry(BlueprintSP_FromSP_ID)\\\n"], 
+			[Fold[_Dispatch Switch Methods[[program]Escape Pattern >>,?], "", all methods]]Append["\tDispatchEntry(Build)\\\n\tDispatchEntry(BlueprintSP_Of)\\\n\tDispatchEntry(ID)\\\n\tDispatchEntry(BlueprintSP_FromSP_ID)\\\n\tDispatchEntry(Pause)\\\n\tResumeEntry(1,Pause)\\\n\tDispatchEntry(Resume)\\\n\tDispatchEntry(CallSP_Async)\\\n"], 
 			[program]Functions >>]]
-		]Append["\tEndEntry\n\n"]
+		]Append["\tEndEntry\n\tEndThreadEntry\n\n"]
 }
 
 Not Native[func:out]
@@ -1633,14 +1633,17 @@
 	struct timeval time;
 #endif
 	uint16_t resume,idx, vcparam_offset, last_vcparam;
-	context * ct;
+	context *ct,*temp_ct;
 	void *tmp;
 	calldata * cdata, *temp_cdata, *my_cdata;
 	DispatchVar
 	FuncDef(Build)
 	FuncDef(BlueprintSP_Of)
 	FuncDef(ID)
-	FuncDef(BlueprintSP_FromSP_ID)\n"]
+	FuncDef(BlueprintSP_FromSP_ID)
+	FuncDef(Pause)
+	FuncDef(Resume)
+	FuncDef(CallSP_Async)\n"]
 		]Append[Fold[Local Pointers[?], "", [program]Functions >>]]
 		]Append["
 	ct = new_context();
@@ -1702,6 +1705,89 @@
 	}
 	
 EndFunc(BlueprintSP_FromSP_ID)
+DISPATCH
+
+FuncNoLocals(Pause, NumParams 1)
+	Param(0, TYPE_WORKER)
+
+	ct->resume_cdata = my_cdata;
+	ct->resumeable = 1;
+	temp_ct = ct;
+	ct = new_context();
+	VCPrepCall(my_cdata->params[0], 1)
+	VCSetParam(my_cdata->params[0], 0, make_Context(temp_ct))
+	ValCall(my_cdata->params[0], 1, 1, Pause)
+	release_ref(my_cdata->params[0]);
+	DISPATCH
+	ValCallPostlude(1, Pause)
+	for(idx = 0; idx < cdata->num_params; ++idx)
+	{
+		release_ref(cdata->params[idx]);
+	}
+	free_context(ct);
+	ct = get_cqueue();
+	if (!ct) goto NOTHING_TO_DO;
+	cdata = ct->resume_cdata;
+	ct->resume_data = NULL;	
+	if(ct->start_func >= 0)
+	{
+		func = ct->start_func;
+		ct->start_func = -1;
+		DISPATCH
+	}
+EndFuncNoLocals(Pause)
+DISPATCH
+
+FuncNoLocals(Resume, NumParams 2)
+	Param(0, TYPE_CONTEXT)
+
+	temp_ct = ((t_Context *)my_cdata->params[0])->ct;
+	release_ref(my_cdata->params[0]);
+	if(temp_ct->resumeable && temp_ct->resume_cdata)
+	{
+		temp_ct->resumeable = 0;
+		temp_ct->resume_cdata->params[0] = add_ref(my_cdata-params[1]);
+		my_cdata->params[0] = my_cdata->params[1];
+		my_cdata->params[1] = NULL;
+		if(!put_cqueue(temp_ct))
+		{
+			ct->resume_cdata = my_cdata;
+			temp_ct->runafter = ct;
+			ct = temp_ct;
+			cdata = ct->resume_cdata;
+			ct->resume_cdata = NULL;
+		}
+	} else {
+		my_cdata->params[0] = NULL;
+	}
+EndFuncNoLocals(Resume)
+DISPATCH
+
+FuncNoLocals(CallSP_Async, NumParams 1)
+	Param(0, TYPE_WORKER)
+
+	temp_ct = new_context();
+	cdata = alloc_cdata(temp_ct, NULL, ((t_Worker *)my_cdata->params[0])->payload.Size);
+	cdata->func = END_THREAD;
+	for(idx = 0; idx < ((t_Worker *)my_cdata->params[0])->payload.Size; ++idx)
+	{
+		cdata->params[idx] = add_ref(((object **)(((t_Worker *)my_cdata->params[0])+1))[idx]);
+	}
+	temp_ct->start_func = ((t_Worker *)my_cdata->params[0])->payload.Index;
+	temp_ct->resume_cdata = cdata;
+	if(put_cqueue(temp_ct))
+	{
+		cdata = my_cdata;
+	} else {
+		ct->resume_cdata = my_cdata;
+		temp_ct->runafter = ct;
+		ct = temp_ct;
+		ct->resume_cdata = NULL;
+		func = ct->start_func;
+		ct->start_func = -1;
+		DISPATCH
+	}
+EndFuncNoLocals(CallSP_Async)
 DISPATCH\n"]
 		]Append[Fold[_Text C Program[?, ?, [program]Type Registry >>], "", Filter[[program]Functions >>, Native[?]]]]
 		]Append["
@@ -1711,9 +1797,34 @@
 	free_context(ct);
 	return cdata->num_params;
 
+DO_END_THREAD:
+	for(idx = 0; idx < cdata->num_params; ++idx)
+	{ release_ref(cdata->params[idx]); }
+	if(ct->runafter)
+	{
+		temp_ct = ct;
+		ct = ct->runafter;
+		free_context(temp_ct);
+		cdata = ct->resume_cdata;
+		func = cdata->func;
+		DISPATCH
+	}
+	free_context(ct);
+	if(ct = get_cqueue())
+	{
+		cdata = ct->resume_cdata;
+		if(ct->start_func >= 0)
+			func = ct->start_func;
+		else
+			func = cdata->func;
+		DISPATCH
+	}
+NOTHING_TO_DO:
+	return 0;
+
 _exception:
 	puts(\"Exception! Trace follows:\");
-	while(cdata && cdata->func != END)
+	while(cdata && cdata->func < END)
 	{
 		printf(\"%d\\n\", cdata->func);
 		cdata = cdata->lastframe;
--- a/nworker_c.rhope	Fri Nov 19 04:04:14 2010 -0500
+++ b/nworker_c.rhope	Sat Nov 20 20:03:25 2010 +0000
@@ -1601,13 +1601,16 @@
 
 Register Builtins@NProgram[prog:out]
 {
-	registered <- [[[[[[[[prog]Register Worker["Print", "rhope", 1, 1]
+	registered <- [[[[[[[[[[[prog]Register Worker["Print", "rhope", 1, 1]
 	]Register Worker["If@Boolean", "rhope", 1, 2]
 	]Register Worker["Build", "rhope", 1, 1]
 	]Register Worker["Blueprint Of", "rhope", 1, 1]
 	]Register Worker["Call@Worker", "rhope", 1, 2] //We're using 2 because we need to assume that the outputs are conditional
 	]Register Worker["ID", "rhope", 1, 1]
 	]Register Worker["Blueprint From ID", "rhope", 1, 2]
+	]Register Worker["Pause", "rhope", 1, 1]
+	]Register Worker["Resume", "rhope", 2, 2]
+	]Register Worker["Call Async", "rhope", 1, 1]
 	]Register Number Methods
 	
 	out <- [[[[[[[registered]Bind Worker["If@Boolean",
--- a/runtime/builtin.c	Fri Nov 19 04:04:14 2010 -0500
+++ b/runtime/builtin.c	Sat Nov 20 20:03:25 2010 +0000
@@ -17,6 +17,8 @@
 	case TYPE_BLUEPRINT:
 		bp = register_type_byid(TYPE_BLUEPRINT, sizeof(blueprint *), NULL, NULL, NULL);
 		break;
+	case TYPE_CONTEXT:
+		register_type_byid(TYPE_CONTEXT, sizeof(context *), NULL, NULL, NULL);
 	}
 }
 
--- a/runtime/builtin.h	Fri Nov 19 04:04:14 2010 -0500
+++ b/runtime/builtin.h	Sat Nov 20 20:03:25 2010 +0000
@@ -26,6 +26,7 @@
 	TYPE_FIELDMISSINGEXCEPTION,
 	TYPE_WRONGTYPEEXCEPTION,
 	TYPE_MUTABLEGLOBAL,
+	TYPE_CONTEXT,
 	TYPE_FIRST_USER //Insert new builtin types before this one
 };
 
--- a/runtime/context.c	Fri Nov 19 04:04:14 2010 -0500
+++ b/runtime/context.c	Sat Nov 20 20:03:25 2010 +0000
@@ -1,9 +1,49 @@
 #include "context.h"
 #include "object.h"
+#include "thread.h"
 #include <stdlib.h>
 #include <stddef.h>
 #include <stdio.h>
 
+context * contextqueue[32];
+int32_t cq_readloc=0;
+int32_t cq_writeloc=0;
+rh_mutex(cq_lock)
+
+void cqueue_init()
+{
+	rh_mutex_init(cq_lock);
+}
+
+context * get_cqueue()
+{
+	context * ret;
+	rh_lock(cq_lock);
+		if (cq_readloc == cq_writeloc)
+		{
+			rh_unlock(cq_lock);
+			return NULL;
+		}
+		ret = contextqueue[cq_readloc++];
+		if (cq_readloc == 32)
+			cq_readloc = 0;
+	rh_unlock(cq_lock);
+	return ret;
+}
+
+int32_t put_cqueue(context * ct)
+{
+	rh_lock(cq_lock);
+		if ((cq_writeloc+1)&31 == cq_readloc)
+		{
+			rh_unlock(cq_lock);
+			return 0;
+		}
+		contextqueue[cq_writeloc++] = ct;
+	rh_unlock(cq_lock);
+	return 1;
+}
+
 stackchunk * new_stack()
 {
 	stackchunk * st = malloc(sizeof(stackchunk));
@@ -18,7 +58,9 @@
 	context * c = malloc(sizeof(context));
 	c->stack_begin = new_stack();
 	c->current_stack = c->stack_begin;
-	c->transaction = NULL;
+	c->resume_cdata = c->runafter = c->transaction = NULL;	
+	c->resumeable = 0;
+	c->start_func = -1;
 	return c;
 }
 
--- a/runtime/context.h	Fri Nov 19 04:04:14 2010 -0500
+++ b/runtime/context.h	Sat Nov 20 20:03:25 2010 +0000
@@ -16,15 +16,23 @@
 } stackchunk;
 
 typedef struct context {
-	stackchunk   *stack_begin;
-	stackchunk   *current_stack;
-	transaction  *transaction;
+	stackchunk     *stack_begin;
+	stackchunk     *current_stack;
+	transaction    *transaction;
+	struct context *runafter;
+	calldata       *resume_cdata;
+	int32_t        resumeable;
+	int32_t        start_func;
 } context;
 
+Box(context *,ct,Context);
 stackchunk * new_stack();
 context * new_context();
 void * alloc_stack(context * ct, uint32_t size);
 calldata * alloc_cdata(context * ct, calldata * lastframe, uint32_t num_params);
 void free_stack(context * ct, void * data);
 void free_context(context * c);
+void cqueue_init();
+context * get_cqueue();
+int32_t put_cqueue(context * ct);
 #endif //_CONTEXT_H_
--- a/runtime/func.h	Fri Nov 19 04:04:14 2010 -0500
+++ b/runtime/func.h	Sat Nov 20 20:03:25 2010 +0000
@@ -22,12 +22,14 @@
 #define DispatchVar
 #define DISPATCH switch(func) { DispatchEntries }
 #define EndEntry case END: goto DO_END;
+#define EndThreadEntry case END_THREAD: goto DO_END_THREAD;
 #else
 #define DispatchEntry(name) &&f_##name,
 #define ResumeEntry(num,name) &&r##num##_##name,
 #define DispatchVar void * funcs[] = { DispatchEntries };
 #define DISPATCH goto *funcs[func];
 #define EndEntry &&DO_END
+#define EndThreadEntry &&DO_END_THREAD;
 #endif
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testpauseresume.rhope	Sat Nov 20 20:03:25 2010 +0000
@@ -0,0 +1,20 @@
+
+Yield[:out]
+{
+	out <- Pause[Resume[?,0]]
+}
+
+Foo[:out]
+{
+	Print["Foo!"]
+}
+
+Main[:out]
+{
+	Call Async[Foo[?]]
+	{ Call Async[Foo[?]]
+	{ Call Async[Foo[?]]
+	{ Get Char[]
+	{ out <- Yield[] }
+}
+