Here it is. My first patch contains a example shell script in case you
want to add.
---
 cmd-wait-for.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 tmux.1         | 12 ++++++---
 2 files changed, 85 insertions(+), 8 deletions(-)
diff --git a/cmd-wait-for.c b/cmd-wait-for.c
index 6313358..5ab10f9 100644
--- a/cmd-wait-for.c
+++ b/cmd-wait-for.c
@@ -32,8 +32,8 @@ enum cmd_retval cmd_wait_for_exec(struct cmd *, struct cmd_q *);
 
 const struct cmd_entry cmd_wait_for_entry = {
 	"wait-for", "wait",
-	"S", 1, 1,
-	"[-S] channel",
+	"LSU", 1, 1,
+	"[-L | -S | -U] channel",
 	0,
 	NULL,
 	NULL,
@@ -42,7 +42,9 @@ const struct cmd_entry cmd_wait_for_entry = {
 
 struct wait_channel {
 	const char	       *name;
+	int								  locked;
 	TAILQ_HEAD(, cmd_q)	waiters;
+	TAILQ_HEAD(, cmd_q)	lockers;
 
 	RB_ENTRY(wait_channel)	entry;
 };
@@ -63,6 +65,10 @@ enum cmd_retval	cmd_wait_for_signal(struct cmd_q *, const char *,
 		    struct wait_channel *);
 enum cmd_retval	cmd_wait_for_wait(struct cmd_q *, const char *,
 		    struct wait_channel *);
+enum cmd_retval	cmd_wait_for_lock(struct cmd_q *, const char *,
+		    struct wait_channel *);
+enum cmd_retval	cmd_wait_for_unlock(struct cmd_q *, const char *,
+		    struct wait_channel *);
 
 enum cmd_retval
 cmd_wait_for_exec(struct cmd *self, struct cmd_q *cmdq)
@@ -76,6 +82,10 @@ cmd_wait_for_exec(struct cmd *self, struct cmd_q *cmdq)
 
 	if (args_has(args, 'S'))
 		return (cmd_wait_for_signal(cmdq, name, wc));
+	if (args_has(args, 'L'))
+		return (cmd_wait_for_lock(cmdq, name, wc));
+	if (args_has(args, 'U'))
+		return (cmd_wait_for_unlock(cmdq, name, wc));
 	return (cmd_wait_for_wait(cmdq, name, wc));
 }
 
@@ -95,9 +105,12 @@ cmd_wait_for_signal(struct cmd_q *cmdq, const char *name,
 		if (!cmdq_free(wq))
 			cmdq_continue(wq);
 	}
-	RB_REMOVE(wait_channels, &wait_channels, wc);
-	free((void*) wc->name);
-	free(wc);
+	
+	if (!wc->locked) {
+		RB_REMOVE(wait_channels, &wait_channels, wc);
+		free((void*) wc->name);
+		free(wc);
+	}
 
 	return (CMD_RETURN_NORMAL);
 }
@@ -114,7 +127,9 @@ cmd_wait_for_wait(struct cmd_q *cmdq, const char *name,
 	if (wc == NULL) {
 		wc = xmalloc(sizeof *wc);
 		wc->name = xstrdup(name);
+		wc->locked = 0;
 		TAILQ_INIT(&wc->waiters);
+		TAILQ_INIT(&wc->lockers);
 		RB_INSERT(wait_channels, &wait_channels, wc);
 	}
 	TAILQ_INSERT_TAIL(&wc->waiters, cmdq, waitentry);
@@ -122,3 +137,59 @@ cmd_wait_for_wait(struct cmd_q *cmdq, const char *name,
 
 	return (CMD_RETURN_WAIT);
 }
+
+enum cmd_retval
+cmd_wait_for_lock(struct cmd_q *cmdq, const char *name,
+    struct wait_channel *wc)
+{
+	if (cmdq->client == NULL || cmdq->client->session != NULL) {
+		cmdq_error(cmdq, "not able to lock");
+		return (CMD_RETURN_ERROR);
+	}
+
+	if (wc == NULL) {
+		wc = xmalloc(sizeof *wc);
+		wc->name = xstrdup(name);
+		wc->locked = 0;
+		TAILQ_INIT(&wc->waiters);
+		TAILQ_INIT(&wc->lockers);
+		RB_INSERT(wait_channels, &wait_channels, wc);
+	}
+
+	if (wc->locked) {
+		TAILQ_INSERT_TAIL(&wc->lockers, cmdq, waitentry);
+		cmdq->references++;
+		return (CMD_RETURN_WAIT);
+	}
+
+	wc->locked = 1;
+	return (CMD_RETURN_NORMAL);
+}
+
+enum cmd_retval
+cmd_wait_for_unlock(struct cmd_q *cmdq, const char *name,
+    struct wait_channel *wc)
+{
+	struct cmd_q	*wq;
+
+	if (wc == NULL || !wc->locked) {
+		cmdq_error(cmdq, "channel %s not locked", name);
+		return (CMD_RETURN_ERROR);
+	}
+
+	if ((wq = TAILQ_FIRST(&wc->lockers)) != NULL) {
+		TAILQ_REMOVE(&wc->lockers, wq, waitentry);
+		if (!cmdq_free(wq))
+			cmdq_continue(wq);
+	} else {
+		wc->locked = 0;
+		if (TAILQ_EMPTY(&wc->waiters)) {
+			RB_REMOVE(wait_channels, &wait_channels, wc);
+			free((void*) wc->name);
+			free(wc);
+		}
+	}
+
+	return (CMD_RETURN_NORMAL);
+}
+
diff --git a/tmux.1 b/tmux.1
index 8df7975..16eba8e 100644
--- a/tmux.1
+++ b/tmux.1
@@ -3554,16 +3554,22 @@ If the command doesn't return success, the exit status is also displayed.
 .D1 (alias: Ic info )
 Show server information and terminal details.
 .It Xo Ic wait-for
-.Fl S
+.Fl LSU
 .Ar channel
 .Xc
 .D1 (alias: Ic wait )
-When used without
-.Fl S ,
+When used without options,
 prevents the client from exiting until woken using
 .Ic wait-for
 .Fl S
 with the same channel.
+When 
+.Ic wait-for
+.Fl L 
+is used, the channel is locked and any clients that try to lock the same
+channel will have to wait until the channel is unlocked with
+.Ic wait-for
+.Fl U .
 This command only works from outside
 .Nm .
 .El
------------------------------------------------------------------------------
Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester  
Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the  
endpoint security space. For insight on selecting the right partner to 
tackle endpoint security challenges, access the full report. 
http://p.sf.net/sfu/symantec-dev2dev
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to