mirror of
https://github.com/neovim/neovim.git
synced 2025-09-13 14:58:18 +00:00
job: Refactor to use pointers instead of ids
'job_start' returns the id as an out paramter, and the 'job_find' function is now used by eval.c to translate job ids into pointers.
This commit is contained in:
@@ -10471,11 +10471,12 @@ static void f_job_start(typval_T *argvars, typval_T *rettv)
|
|||||||
// The last item of argv must be NULL
|
// The last item of argv must be NULL
|
||||||
argv[i] = NULL;
|
argv[i] = NULL;
|
||||||
|
|
||||||
rettv->vval.v_number = job_start(argv,
|
job_start(argv,
|
||||||
xstrdup((char *)argvars[0].vval.v_string),
|
xstrdup((char *)argvars[0].vval.v_string),
|
||||||
on_job_stdout,
|
on_job_stdout,
|
||||||
on_job_stderr,
|
on_job_stderr,
|
||||||
on_job_exit);
|
on_job_exit,
|
||||||
|
&rettv->vval.v_number);
|
||||||
|
|
||||||
if (rettv->vval.v_number <= 0) {
|
if (rettv->vval.v_number <= 0) {
|
||||||
if (rettv->vval.v_number == 0) {
|
if (rettv->vval.v_number == 0) {
|
||||||
@@ -10502,19 +10503,21 @@ static void f_job_stop(typval_T *argvars, typval_T *rettv)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!job_stop(argvars[0].vval.v_number)) {
|
Job *job = job_find(argvars[0].vval.v_number);
|
||||||
|
|
||||||
|
if (!job) {
|
||||||
// Probably an invalid job id
|
// Probably an invalid job id
|
||||||
EMSG(_(e_invjob));
|
EMSG(_(e_invjob));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
job_stop(job);
|
||||||
rettv->vval.v_number = 1;
|
rettv->vval.v_number = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "jobwrite()" function
|
// "jobwrite()" function
|
||||||
static void f_job_write(typval_T *argvars, typval_T *rettv)
|
static void f_job_write(typval_T *argvars, typval_T *rettv)
|
||||||
{
|
{
|
||||||
bool res;
|
|
||||||
rettv->v_type = VAR_NUMBER;
|
rettv->v_type = VAR_NUMBER;
|
||||||
rettv->vval.v_number = 0;
|
rettv->vval.v_number = 0;
|
||||||
|
|
||||||
@@ -10529,16 +10532,16 @@ static void f_job_write(typval_T *argvars, typval_T *rettv)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = job_write(argvars[0].vval.v_number,
|
Job *job = job_find(argvars[0].vval.v_number);
|
||||||
xstrdup((char *)argvars[1].vval.v_string),
|
|
||||||
strlen((char *)argvars[1].vval.v_string));
|
|
||||||
|
|
||||||
if (!res) {
|
if (!job) {
|
||||||
// Invalid job id
|
// Invalid job id
|
||||||
EMSG(_(e_invjob));
|
EMSG(_(e_invjob));
|
||||||
}
|
}
|
||||||
|
|
||||||
rettv->vval.v_number = 1;
|
rettv->vval.v_number = job_write(job,
|
||||||
|
xstrdup((char *)argvars[1].vval.v_string),
|
||||||
|
strlen((char *)argvars[1].vval.v_string));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -24,7 +24,7 @@ typedef struct {
|
|||||||
msgpack_unpacker *unpacker;
|
msgpack_unpacker *unpacker;
|
||||||
msgpack_sbuffer *sbuffer;
|
msgpack_sbuffer *sbuffer;
|
||||||
union {
|
union {
|
||||||
int job_id;
|
Job *job;
|
||||||
struct {
|
struct {
|
||||||
RStream *read;
|
RStream *read;
|
||||||
WStream *write;
|
WStream *write;
|
||||||
@@ -68,11 +68,25 @@ void channel_teardown()
|
|||||||
/// stdin/stdout. stderr is forwarded to the editor error stream.
|
/// stdin/stdout. stderr is forwarded to the editor error stream.
|
||||||
///
|
///
|
||||||
/// @param argv The argument vector for the process
|
/// @param argv The argument vector for the process
|
||||||
void channel_from_job(char **argv)
|
bool channel_from_job(char **argv)
|
||||||
{
|
{
|
||||||
Channel *channel = register_channel();
|
Channel *channel = register_channel();
|
||||||
channel->is_job = true;
|
channel->is_job = true;
|
||||||
channel->data.job_id = job_start(argv, channel, job_out, job_err, NULL);
|
|
||||||
|
int status;
|
||||||
|
channel->data.job = job_start(argv,
|
||||||
|
channel,
|
||||||
|
job_out,
|
||||||
|
job_err,
|
||||||
|
NULL,
|
||||||
|
&status);
|
||||||
|
|
||||||
|
if (status <= 0) {
|
||||||
|
close_channel(channel);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an API channel from a libuv stream representing a tcp or
|
/// Creates an API channel from a libuv stream representing a tcp or
|
||||||
@@ -282,7 +296,9 @@ static void close_channel(Channel *channel)
|
|||||||
msgpack_unpacker_free(channel->unpacker);
|
msgpack_unpacker_free(channel->unpacker);
|
||||||
|
|
||||||
if (channel->is_job) {
|
if (channel->is_job) {
|
||||||
job_stop(channel->data.job_id);
|
if (channel->data.job) {
|
||||||
|
job_stop(channel->data.job);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
rstream_free(channel->data.streams.read);
|
rstream_free(channel->data.streams.read);
|
||||||
wstream_free(channel->data.streams.write);
|
wstream_free(channel->data.streams.write);
|
||||||
|
@@ -128,14 +128,15 @@ void job_teardown()
|
|||||||
/// @param stderr_cb Callback that will be invoked when data is available
|
/// @param stderr_cb Callback that will be invoked when data is available
|
||||||
/// on stderr
|
/// on stderr
|
||||||
/// @param exit_cb Callback that will be invoked when the job exits
|
/// @param exit_cb Callback that will be invoked when the job exits
|
||||||
/// @return The job id if the job started successfully. If the the first item /
|
/// @param[out] The job id if the job started successfully, 0 if the job table
|
||||||
/// of `argv`(the program) could not be executed, -1 will be returned.
|
/// is full, -1 if the program could not be executed.
|
||||||
// 0 will be returned if the job table is full.
|
/// @return The job pointer if the job started successfully, NULL otherwise
|
||||||
int job_start(char **argv,
|
Job *job_start(char **argv,
|
||||||
void *data,
|
void *data,
|
||||||
rstream_cb stdout_cb,
|
rstream_cb stdout_cb,
|
||||||
rstream_cb stderr_cb,
|
rstream_cb stderr_cb,
|
||||||
job_exit_cb job_exit_cb)
|
job_exit_cb job_exit_cb,
|
||||||
|
int *status)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
Job *job;
|
Job *job;
|
||||||
@@ -149,12 +150,14 @@ int job_start(char **argv,
|
|||||||
|
|
||||||
if (i == MAX_RUNNING_JOBS) {
|
if (i == MAX_RUNNING_JOBS) {
|
||||||
// No free slots
|
// No free slots
|
||||||
return 0;
|
*status = 0;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
job = xmalloc(sizeof(Job));
|
job = xmalloc(sizeof(Job));
|
||||||
// Initialize
|
// Initialize
|
||||||
job->id = i + 1;
|
job->id = i + 1;
|
||||||
|
*status = job->id;
|
||||||
job->pending_refs = 3;
|
job->pending_refs = 3;
|
||||||
job->pending_closes = 4;
|
job->pending_closes = 4;
|
||||||
job->data = data;
|
job->data = data;
|
||||||
@@ -192,7 +195,8 @@ int job_start(char **argv,
|
|||||||
// Spawn the job
|
// Spawn the job
|
||||||
if (uv_spawn(uv_default_loop(), &job->proc, &job->proc_opts) != 0) {
|
if (uv_spawn(uv_default_loop(), &job->proc, &job->proc_opts) != 0) {
|
||||||
free_job(job);
|
free_job(job);
|
||||||
return -1;
|
*status = -1;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give all handles a reference to the job
|
// Give all handles a reference to the job
|
||||||
@@ -219,51 +223,45 @@ int job_start(char **argv,
|
|||||||
}
|
}
|
||||||
job_count++;
|
job_count++;
|
||||||
|
|
||||||
return job->id;
|
return job;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Finds a job instance by id
|
||||||
|
///
|
||||||
|
/// @param id The job id
|
||||||
|
/// @return the Job instance
|
||||||
|
Job *job_find(int id)
|
||||||
|
{
|
||||||
|
Job *job;
|
||||||
|
|
||||||
|
if (id <= 0 || id > MAX_RUNNING_JOBS || !(job = table[id - 1])
|
||||||
|
|| job->stopped) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return job;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Terminates a job. This is a non-blocking operation, but if the job exists
|
/// Terminates a job. This is a non-blocking operation, but if the job exists
|
||||||
/// it's guaranteed to succeed(SIGKILL will eventually be sent)
|
/// it's guaranteed to succeed(SIGKILL will eventually be sent)
|
||||||
///
|
///
|
||||||
/// @param id The job id
|
/// @param job The Job instance
|
||||||
/// @return true if the stop request was successfully sent, false if the job
|
void job_stop(Job *job)
|
||||||
/// id is invalid(probably because it has already stopped)
|
|
||||||
bool job_stop(int id)
|
|
||||||
{
|
{
|
||||||
Job *job = find_job(id);
|
|
||||||
|
|
||||||
if (job == NULL || job->stopped) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
job->stopped = true;
|
job->stopped = true;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes data to the job's stdin. This is a non-blocking operation, it
|
/// Writes data to the job's stdin. This is a non-blocking operation, it
|
||||||
/// returns when the write request was sent.
|
/// returns when the write request was sent.
|
||||||
///
|
///
|
||||||
/// @param id The job id
|
/// @param job The Job instance
|
||||||
/// @param data Buffer containing the data to be written
|
/// @param data Buffer containing the data to be written
|
||||||
/// @param len Size of the data
|
/// @param len Size of the data
|
||||||
/// @return true if the write request was successfully sent, false if the job
|
/// @return true if the write request was successfully sent, false if writing
|
||||||
/// id is invalid(probably because it has already stopped)
|
/// to the job stream failed (possibly because the OS buffer is full)
|
||||||
bool job_write(int id, char *data, uint32_t len)
|
bool job_write(Job *job, char *data, uint32_t len)
|
||||||
{
|
{
|
||||||
Job *job = find_job(id);
|
return wstream_write(job->in, wstream_new_buffer(data, len, free));
|
||||||
|
|
||||||
if (job == NULL || job->stopped) {
|
|
||||||
free(data);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wstream_write(job->in, wstream_new_buffer(data, len, free))) {
|
|
||||||
job_stop(job->id);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs the read callback associated with the job exit event
|
/// Runs the read callback associated with the job exit event
|
||||||
@@ -315,15 +313,6 @@ static bool is_alive(Job *job)
|
|||||||
return uv_process_kill(&job->proc, 0) == 0;
|
return uv_process_kill(&job->proc, 0) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Job * find_job(int id)
|
|
||||||
{
|
|
||||||
if (id <= 0 || id > MAX_RUNNING_JOBS) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return table[id - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_job(Job *job)
|
static void free_job(Job *job)
|
||||||
{
|
{
|
||||||
uv_close((uv_handle_t *)&job->proc_stdout, close_cb);
|
uv_close((uv_handle_t *)&job->proc_stdout, close_cb);
|
||||||
|
Reference in New Issue
Block a user