mirror of
				https://github.com/sammy-ette/Hilbish
				synced 2025-08-10 02:52:03 +00:00 
			
		
		
		
	refactor!: use userdata for job object instead of table
this might or might not bring lower ram usage there is now only 1 single reference to a lua job object since it's stored in the job struct breaking change since methods need to be called with a colon instead of dot
This commit is contained in:
		
							parent
							
								
									9d385efbfc
								
							
						
					
					
						commit
						b93d6ef551
					
				
							
								
								
									
										144
									
								
								job.go
									
									
									
									
									
								
							
							
						
						
									
										144
									
								
								job.go
									
									
									
									
									
								
							| @ -3,6 +3,7 @@ package main | |||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"errors" | 	"errors" | ||||||
|  | 	"fmt" | ||||||
| 	"io" | 	"io" | ||||||
| 	"os" | 	"os" | ||||||
| 	"os/exec" | 	"os/exec" | ||||||
| @ -15,6 +16,7 @@ import ( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var jobs *jobHandler | var jobs *jobHandler | ||||||
|  | var jobMetaKey = rt.StringValue("hshjob") | ||||||
| 
 | 
 | ||||||
| type job struct { | type job struct { | ||||||
| 	cmd string | 	cmd string | ||||||
| @ -32,6 +34,7 @@ type job struct { | |||||||
| 	cmderr io.Writer | 	cmderr io.Writer | ||||||
| 	stdout *bytes.Buffer | 	stdout *bytes.Buffer | ||||||
| 	stderr *bytes.Buffer | 	stderr *bytes.Buffer | ||||||
|  | 	ud *rt.UserData | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (j *job) start() error { | func (j *job) start() error { | ||||||
| @ -64,7 +67,7 @@ func (j *job) start() error { | |||||||
| 	j.pid = proc.Pid | 	j.pid = proc.Pid | ||||||
| 	j.running = true | 	j.running = true | ||||||
| 
 | 
 | ||||||
| 	hooks.Em.Emit("job.start", j.lua()) | 	hooks.Em.Emit("job.start", rt.UserDataValue(j.ud)) | ||||||
| 
 | 
 | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
| @ -79,7 +82,7 @@ func (j *job) stop() { | |||||||
| 
 | 
 | ||||||
| func (j *job) finish() { | func (j *job) finish() { | ||||||
| 	j.running = false | 	j.running = false | ||||||
| 	hooks.Em.Emit("job.done", j.lua()) | 	hooks.Em.Emit("job.done", j.ud) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (j *job) wait() { | func (j *job) wait() { | ||||||
| @ -107,28 +110,16 @@ func (j *job) getProc() *os.Process { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (j *job) lua() rt.Value { | func luaStartJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | ||||||
| 	jobFuncs := map[string]util.LuaExport{ | 	if err := c.Check1Arg(); err != nil { | ||||||
| 		"stop": {j.luaStop, 0, false}, | 		return nil, err | ||||||
| 		"start": {j.luaStart, 0, false}, |  | ||||||
| 		"foreground": {j.luaForeground, 0, false}, |  | ||||||
| 		"background": {j.luaBackground, 0, false}, |  | ||||||
| 	} | 	} | ||||||
| 	luaJob := rt.NewTable() |  | ||||||
| 	util.SetExports(l, luaJob, jobFuncs) |  | ||||||
| 
 | 
 | ||||||
| 	luaJob.Set(rt.StringValue("cmd"), rt.StringValue(j.cmd)) | 	j, err := jobArg(c, 0) | ||||||
| 	luaJob.Set(rt.StringValue("running"), rt.BoolValue(j.running)) | 	if err != nil { | ||||||
| 	luaJob.Set(rt.StringValue("id"), rt.IntValue(int64(j.id))) | 		return nil, err | ||||||
| 	luaJob.Set(rt.StringValue("pid"), rt.IntValue(int64(j.pid))) | 	} | ||||||
| 	luaJob.Set(rt.StringValue("exitCode"), rt.IntValue(int64(j.exitCode))) |  | ||||||
| 	luaJob.Set(rt.StringValue("stdout"), rt.StringValue(string(j.stdout.Bytes()))) |  | ||||||
| 	luaJob.Set(rt.StringValue("stderr"), rt.StringValue(string(j.stderr.Bytes()))) |  | ||||||
| 
 | 
 | ||||||
| 	return rt.TableValue(luaJob) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (j *job) luaStart(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { |  | ||||||
| 	if !j.running { | 	if !j.running { | ||||||
| 		err := j.start() | 		err := j.start() | ||||||
| 		exit := handleExecErr(err) | 		exit := handleExecErr(err) | ||||||
| @ -139,7 +130,16 @@ func (j *job) luaStart(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | |||||||
| 	return c.Next(), nil | 	return c.Next(), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (j *job) luaStop(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | func luaStopJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | ||||||
|  | 	if err := c.Check1Arg(); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	j, err := jobArg(c, 0) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if j.running { | 	if j.running { | ||||||
| 		j.stop() | 		j.stop() | ||||||
| 		j.finish() | 		j.finish() | ||||||
| @ -148,7 +148,16 @@ func (j *job) luaStop(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | |||||||
| 	return c.Next(), nil | 	return c.Next(), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (j *job) luaForeground(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | func luaForegroundJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | ||||||
|  | 	if err := c.Check1Arg(); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	j, err := jobArg(c, 0) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if !j.running { | 	if !j.running { | ||||||
| 		return nil, errors.New("job not running") | 		return nil, errors.New("job not running") | ||||||
| 	} | 	} | ||||||
| @ -157,7 +166,7 @@ func (j *job) luaForeground(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | |||||||
| 	jobs.foreground = true | 	jobs.foreground = true | ||||||
| 	// this is kinda funny | 	// this is kinda funny | ||||||
| 	// background continues the process incase it got suspended | 	// background continues the process incase it got suspended | ||||||
| 	err := j.background() | 	err = j.background() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| @ -171,12 +180,21 @@ func (j *job) luaForeground(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | |||||||
| 	return c.Next(), nil | 	return c.Next(), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (j *job) luaBackground(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | func luaBackgroundJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | ||||||
|  | 	if err := c.Check1Arg(); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	j, err := jobArg(c, 0) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	if !j.running { | 	if !j.running { | ||||||
| 		return nil, errors.New("job not running") | 		return nil, errors.New("job not running") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err := j.background() | 	err = j.background() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| @ -215,8 +233,10 @@ func (j *jobHandler) add(cmd string, args []string, path string) *job { | |||||||
| 		stdout: &bytes.Buffer{}, | 		stdout: &bytes.Buffer{}, | ||||||
| 		stderr: &bytes.Buffer{}, | 		stderr: &bytes.Buffer{}, | ||||||
| 	} | 	} | ||||||
|  | 	jb.ud = jobUserData(jb) | ||||||
|  | 
 | ||||||
| 	j.jobs[j.latestID] = jb | 	j.jobs[j.latestID] = jb | ||||||
| 	hooks.Em.Emit("job.add", jb.lua()) | 	hooks.Em.Emit("job.add", rt.UserDataValue(jb.ud)) | ||||||
| 
 | 
 | ||||||
| 	return jb | 	return jb | ||||||
| } | } | ||||||
| @ -257,6 +277,44 @@ func (j *jobHandler) stopAll() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (j *jobHandler) loader(rtm *rt.Runtime) *rt.Table { | func (j *jobHandler) loader(rtm *rt.Runtime) *rt.Table { | ||||||
|  | 	jobMethods := rt.NewTable() | ||||||
|  | 	jFuncs := map[string]util.LuaExport{ | ||||||
|  | 		"stop": {luaStopJob, 1, false}, | ||||||
|  | 		"start": {luaStartJob, 1, false}, | ||||||
|  | 		"foreground": {luaForegroundJob, 1, false}, | ||||||
|  | 		"background": {luaBackgroundJob, 1, false}, | ||||||
|  | 	} | ||||||
|  | 	util.SetExports(l, jobMethods, jFuncs) | ||||||
|  | 
 | ||||||
|  | 	jobMeta := rt.NewTable() | ||||||
|  | 	jobIndex := func(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | ||||||
|  | 		j, _ := jobArg(c, 0) | ||||||
|  | 
 | ||||||
|  | 		arg := c.Arg(1) | ||||||
|  | 		val := jobMethods.Get(arg) | ||||||
|  | 
 | ||||||
|  | 		if val != rt.NilValue { | ||||||
|  | 			return c.PushingNext1(t.Runtime, val), nil | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		keyStr, _ := arg.TryString() | ||||||
|  | 
 | ||||||
|  | 		switch keyStr { | ||||||
|  | 			case "cmd": val = rt.StringValue(j.cmd) | ||||||
|  | 			case "running": val = rt.BoolValue(j.running) | ||||||
|  | 			case "id": val = rt.IntValue(int64(j.id)) | ||||||
|  | 			case "pid": val = rt.IntValue(int64(j.pid)) | ||||||
|  | 			case "exitCode": val = rt.IntValue(int64(j.exitCode)) | ||||||
|  | 			case "stdout": val = rt.StringValue(string(j.stdout.Bytes())) | ||||||
|  | 			case "stderr": val = rt.StringValue(string(j.stderr.Bytes())) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return c.PushingNext1(t.Runtime, val), nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	jobMeta.Set(rt.StringValue("__index"), rt.FunctionValue(rt.NewGoFunction(jobIndex, "__index", 2, false))) | ||||||
|  | 	l.SetRegistry(jobMetaKey, rt.TableValue(jobMeta)) | ||||||
|  | 
 | ||||||
| 	jobFuncs := map[string]util.LuaExport{ | 	jobFuncs := map[string]util.LuaExport{ | ||||||
| 		"all": {j.luaAllJobs, 0, false}, | 		"all": {j.luaAllJobs, 0, false}, | ||||||
| 		"last": {j.luaLastJob, 0, false}, | 		"last": {j.luaLastJob, 0, false}, | ||||||
| @ -271,6 +329,30 @@ func (j *jobHandler) loader(rtm *rt.Runtime) *rt.Table { | |||||||
| 	return luaJob | 	return luaJob | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func jobArg(c *rt.GoCont, arg int) (*job, error) { | ||||||
|  | 	j, ok := valueToJob(c.Arg(arg)) | ||||||
|  | 	if !ok { | ||||||
|  | 		return nil, fmt.Errorf("#%d must be a job", arg + 1) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return j, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func valueToJob(val rt.Value) (*job, bool) { | ||||||
|  | 	u, ok := val.TryUserData() | ||||||
|  | 	if !ok { | ||||||
|  | 		return nil, false | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	j, ok := u.Value().(*job) | ||||||
|  | 	return j, ok | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func jobUserData(j *job) *rt.UserData { | ||||||
|  | 	jobMeta := l.Registry(jobMetaKey) | ||||||
|  | 	return rt.NewUserData(j, jobMeta.AsTable()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (j *jobHandler) luaGetJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | func (j *jobHandler) luaGetJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | ||||||
| 	j.mu.RLock() | 	j.mu.RLock() | ||||||
| 	defer j.mu.RUnlock() | 	defer j.mu.RUnlock() | ||||||
| @ -288,7 +370,7 @@ func (j *jobHandler) luaGetJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | |||||||
| 		return c.Next(), nil | 		return c.Next(), nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return c.PushingNext1(t.Runtime, job.lua()), nil | 	return c.PushingNext(t.Runtime, rt.UserDataValue(job.ud)), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (j *jobHandler) luaAddJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | func (j *jobHandler) luaAddJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | ||||||
| @ -317,7 +399,7 @@ func (j *jobHandler) luaAddJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | |||||||
| 
 | 
 | ||||||
| 	jb := j.add(cmd, args, execPath) | 	jb := j.add(cmd, args, execPath) | ||||||
| 
 | 
 | ||||||
| 	return c.PushingNext1(t.Runtime, jb.lua()), nil | 	return c.PushingNext1(t.Runtime, rt.UserDataValue(jb.ud)), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (j *jobHandler) luaAllJobs(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | func (j *jobHandler) luaAllJobs(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | ||||||
| @ -326,7 +408,7 @@ func (j *jobHandler) luaAllJobs(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | |||||||
| 
 | 
 | ||||||
| 	jobTbl := rt.NewTable() | 	jobTbl := rt.NewTable() | ||||||
| 	for id, job := range j.jobs { | 	for id, job := range j.jobs { | ||||||
| 		jobTbl.Set(rt.IntValue(int64(id)), job.lua()) | 		jobTbl.Set(rt.IntValue(int64(id)), rt.UserDataValue(job.ud)) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return c.PushingNext1(t.Runtime, rt.TableValue(jobTbl)), nil | 	return c.PushingNext1(t.Runtime, rt.TableValue(jobTbl)), nil | ||||||
| @ -358,5 +440,5 @@ func (j *jobHandler) luaLastJob(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) { | |||||||
| 		return c.Next(), nil | 		return c.Next(), nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return c.PushingNext1(t.Runtime, job.lua()), nil | 	return c.PushingNext1(t.Runtime, rt.UserDataValue(job.ud)), nil | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user