summaryrefslogtreecommitdiffstats
path: root/src/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/channel.c')
-rw-r--r--src/channel.c138
1 files changed, 119 insertions, 19 deletions
diff --git a/src/channel.c b/src/channel.c
index 7b811dbce2..83d057dbb0 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -368,6 +368,39 @@ channel_still_useful(channel_T *channel)
}
/*
+ * Close a channel and free all its resources.
+ */
+ static void
+channel_free_contents(channel_T *channel)
+{
+ channel_close(channel, TRUE);
+ channel_clear(channel);
+ ch_log(channel, "Freeing channel");
+}
+
+ static void
+channel_free_channel(channel_T *channel)
+{
+ if (channel->ch_next != NULL)
+ channel->ch_next->ch_prev = channel->ch_prev;
+ if (channel->ch_prev == NULL)
+ first_channel = channel->ch_next;
+ else
+ channel->ch_prev->ch_next = channel->ch_next;
+ vim_free(channel);
+}
+
+ static void
+channel_free(channel_T *channel)
+{
+ if (!in_free_unref_items)
+ {
+ channel_free_contents(channel);
+ channel_free_channel(channel);
+ }
+}
+
+/*
* Close a channel and free all its resources if there is no further action
* possible, there is no callback to be invoked or the associated job was
* killed.
@@ -397,22 +430,39 @@ channel_unref(channel_T *channel)
return FALSE;
}
-/*
- * Close a channel and free all its resources.
- */
+ int
+free_unused_channels_contents(int copyID, int mask)
+{
+ int did_free = FALSE;
+ channel_T *ch;
+
+ for (ch = first_channel; ch != NULL; ch = ch->ch_next)
+ if ((ch->ch_copyID & mask) != (copyID & mask))
+ {
+ /* Free the channel and ordinary items it contains, but don't
+ * recurse into Lists, Dictionaries etc. */
+ channel_free_contents(ch);
+ did_free = TRUE;
+ }
+ return did_free;
+}
+
void
-channel_free(channel_T *channel)
+free_unused_channels(int copyID, int mask)
{
- channel_close(channel, TRUE);
- channel_clear(channel);
- ch_log(channel, "Freeing channel");
- if (channel->ch_next != NULL)
- channel->ch_next->ch_prev = channel->ch_prev;
- if (channel->ch_prev == NULL)
- first_channel = channel->ch_next;
- else
- channel->ch_prev->ch_next = channel->ch_next;
- vim_free(channel);
+ channel_T *ch;
+ channel_T *ch_next;
+
+ for (ch = first_channel; ch != NULL; ch = ch_next)
+ {
+ ch_next = ch->ch_next;
+ if ((ch->ch_copyID & mask) != (copyID & mask))
+ {
+ /* Free the channel and ordinary items it contains, but don't
+ * recurse into Lists, Dictionaries etc. */
+ channel_free_channel(ch);
+ }
+ }
}
#if defined(FEAT_GUI) || defined(PROTO)
@@ -2457,6 +2507,7 @@ channel_clear(channel_T *channel)
channel_clear_one(channel, PART_SOCK);
channel_clear_one(channel, PART_OUT);
channel_clear_one(channel, PART_ERR);
+ /* there is no callback or queue for PART_IN */
vim_free(channel->ch_callback);
channel->ch_callback = NULL;
partial_unref(channel->ch_partial);
@@ -3913,7 +3964,7 @@ get_channel_arg(typval_T *tv, int check_open)
static job_T *first_job = NULL;
static void
-job_free(job_T *job)
+job_free_contents(job_T *job)
{
ch_log(job->jv_channel, "Freeing job");
if (job->jv_channel != NULL)
@@ -3928,19 +3979,33 @@ job_free(job_T *job)
}
mch_clear_job(job);
+ vim_free(job->jv_stoponexit);
+ vim_free(job->jv_exit_cb);
+ partial_unref(job->jv_exit_partial);
+}
+
+ static void
+job_free_job(job_T *job)
+{
if (job->jv_next != NULL)
job->jv_next->jv_prev = job->jv_prev;
if (job->jv_prev == NULL)
first_job = job->jv_next;
else
job->jv_prev->jv_next = job->jv_next;
-
- vim_free(job->jv_stoponexit);
- vim_free(job->jv_exit_cb);
- partial_unref(job->jv_exit_partial);
vim_free(job);
}
+ static void
+job_free(job_T *job)
+{
+ if (!in_free_unref_items)
+ {
+ job_free_contents(job);
+ job_free_job(job);
+ }
+}
+
void
job_unref(job_T *job)
{
@@ -3964,6 +4029,41 @@ job_unref(job_T *job)
}
}
+ int
+free_unused_jobs_contents(int copyID, int mask)
+{
+ int did_free = FALSE;
+ job_T *job;
+
+ for (job = first_job; job != NULL; job = job->jv_next)
+ if ((job->jv_copyID & mask) != (copyID & mask))
+ {
+ /* Free the channel and ordinary items it contains, but don't
+ * recurse into Lists, Dictionaries etc. */
+ job_free_contents(job);
+ did_free = TRUE;
+ }
+ return did_free;
+}
+
+ void
+free_unused_jobs(int copyID, int mask)
+{
+ job_T *job;
+ job_T *job_next;
+
+ for (job = first_job; job != NULL; job = job_next)
+ {
+ job_next = job->jv_next;
+ if ((job->jv_copyID & mask) != (copyID & mask))
+ {
+ /* Free the channel and ordinary items it contains, but don't
+ * recurse into Lists, Dictionaries etc. */
+ job_free_job(job);
+ }
+ }
+}
+
/*
* Allocate a job. Sets the refcount to one and sets options default.
*/