>From f2ee44eeeba84bcdb7af8100c6c4a3570f2665ff Mon Sep 17 00:00:00 2001
From: Matthew Mondor <mmondor@pulsar-zone.net>
Date: Mon, 4 Nov 2013 23:33:50 -0500
Subject: [PATCH] Implement a few non-blocking MP functions:

MP:TRY-GET-SEMAPHORE
  returns NIL if the semaphore could not be obtained, or the count
  if it could be obtained

MP:MAILBOX-TRY-READ
  returns a message if it's available, NIL if the queue is empty

MP:MAILBOX-TRY-SEND
  returns the sent message if it could be queued, or NIL
  (mailbox is full)
---
 src/c/symbols_list.h      |  3 +++
 src/c/symbols_list2.h     |  3 +++
 src/c/threads/mailbox.d   | 40 ++++++++++++++++++++++++++++++++++++++++
 src/c/threads/semaphore.d | 11 +++++++++++
 src/h/external.h          |  3 +++
 5 files changed, 60 insertions(+)

diff --git a/src/c/symbols_list.h b/src/c/symbols_list.h
index 47851b5..7d0fed7 100755
--- a/src/c/symbols_list.h
+++ b/src/c/symbols_list.h
@@ -1592,6 +1592,7 @@ cl_symbols[] = {
 {MP_ "MAKE-SEMAPHORE", MP_ORDINARY, IF_MP(mp_make_semaphore), -1, OBJNULL},
 {MP_ "SIGNAL-SEMAPHORE", MP_ORDINARY, IF_MP(mp_signal_semaphore), -1, OBJNULL},
 {MP_ "WAIT-ON-SEMAPHORE", MP_ORDINARY, IF_MP(mp_wait_on_semaphore), 1, OBJNULL},
+{MP_ "TRY-GET-SEMAPHORE", MP_ORDINARY, IF_MP(mp_try_get_semaphore), 1, OBJNULL},
 {MP_ "SEMAPHORE-COUNT", MP_ORDINARY, IF_MP(mp_semaphore_count), 1, OBJNULL},
 {MP_ "SEMAPHORE-NAME", MP_ORDINARY, IF_MP(mp_semaphore_name), 1, OBJNULL},
 {MP_ "SEMAPHORE-WAIT-COUNT", MP_ORDINARY, IF_MP(mp_semaphore_wait_count), 1, OBJNULL},
@@ -1615,7 +1616,9 @@ cl_symbols[] = {
 {MP_ "MAILBOX-COUNT", MP_ORDINARY, IF_MP(mp_mailbox_count), 1, OBJNULL},
 {MP_ "MAILBOX-EMPTY-P", MP_ORDINARY, IF_MP(mp_mailbox_empty_p), 1, OBJNULL},
 {MP_ "MAILBOX-READ", MP_ORDINARY, IF_MP(mp_mailbox_read), 1, OBJNULL},
+{MP_ "MAILBOX-TRY-READ", MP_ORDINARY, IF_MP(mp_mailbox_try_read), 1, OBJNULL},
 {MP_ "MAILBOX-SEND", MP_ORDINARY, IF_MP(mp_mailbox_send), 2, OBJNULL},
+{MP_ "MAILBOX-TRY-SEND", MP_ORDINARY, IF_MP(mp_mailbox_try_send), 2, OBJNULL},
 /* #endif defined(ECL_THREADS) */
 
 {SYS_ "WHILE", SI_ORDINARY, NULL, -1, OBJNULL},
diff --git a/src/c/symbols_list2.h b/src/c/symbols_list2.h
index 5d99c94..4a6f7b1 100644
--- a/src/c/symbols_list2.h
+++ b/src/c/symbols_list2.h
@@ -1592,6 +1592,7 @@ cl_symbols[] = {
 {MP_ "MAKE-SEMAPHORE",IF_MP("mp_make_semaphore")},
 {MP_ "SIGNAL-SEMAPHORE",IF_MP("mp_signal_semaphore")},
 {MP_ "WAIT-ON-SEMAPHORE",IF_MP("mp_wait_on_semaphore")},
+{MP_ "TRY-GET-SEMAPHORE",IF_MP("mp_try_get_semaphore")},
 {MP_ "SEMAPHORE-COUNT",IF_MP("mp_semaphore_count")},
 {MP_ "SEMAPHORE-NAME",IF_MP("mp_semaphore_name")},
 {MP_ "SEMAPHORE-WAIT-COUNT",IF_MP("mp_semaphore_wait_count")},
@@ -1615,7 +1616,9 @@ cl_symbols[] = {
 {MP_ "MAILBOX-COUNT",IF_MP("mp_mailbox_count")},
 {MP_ "MAILBOX-EMPTY-P",IF_MP("mp_mailbox_empty_p")},
 {MP_ "MAILBOX-READ",IF_MP("mp_mailbox_read")},
+{MP_ "MAILBOX-TRY-READ",IF_MP("mp_mailbox_try_read")},
 {MP_ "MAILBOX-SEND",IF_MP("mp_mailbox_send")},
+{MP_ "MAILBOX-TRY-SEND",IF_MP("mp_mailbox_try_send")},
 /* #endif defined(ECL_THREADS) */
 
 {SYS_ "WHILE",NULL},
diff --git a/src/c/threads/mailbox.d b/src/c/threads/mailbox.d
index ae0a66d..1686841 100755
--- a/src/c/threads/mailbox.d
+++ b/src/c/threads/mailbox.d
@@ -108,6 +108,25 @@ mp_mailbox_read(cl_object mailbox)
 }
 
 cl_object
+mp_mailbox_try_read(cl_object mailbox)
+{
+	cl_env_ptr env = ecl_process_env();
+	cl_fixnum ndx;
+	cl_object output;
+	unlikely_if (ecl_t_of(mailbox) != t_mailbox) {
+		FEerror_not_a_mailbox(mailbox);
+	}
+	output = mp_try_get_semaphore(mailbox->mailbox.reader_semaphore);
+	if (output != ECL_NIL) {
+		ndx = AO_fetch_and_add1((AO_t*)&mailbox->mailbox.read_pointer) &
+			mailbox->mailbox.mask;
+		output = mailbox->mailbox.data->vector.self.t[ndx];
+		mp_signal_semaphore(1, mailbox->mailbox.writer_semaphore);
+	}
+	ecl_return1(env, output);
+}
+
+cl_object
 mp_mailbox_send(cl_object mailbox, cl_object msg)
 {
 	cl_env_ptr env = ecl_process_env();
@@ -124,3 +143,24 @@ mp_mailbox_send(cl_object mailbox, cl_object msg)
 	mp_signal_semaphore(1, mailbox->mailbox.reader_semaphore);
 	ecl_return0(env);
 }
+
+cl_object
+mp_mailbox_try_send(cl_object mailbox, cl_object msg)
+{
+	cl_env_ptr env = ecl_process_env();
+	cl_object output;
+	cl_fixnum ndx;
+	unlikely_if (ecl_t_of(mailbox) != t_mailbox) {
+		FEerror_not_a_mailbox(mailbox);
+	}
+	output = mp_try_get_semaphore(mailbox->mailbox.writer_semaphore);
+	if (output != ECL_NIL) {
+		output = msg;
+		ndx = AO_fetch_and_add1((AO_t*)&mailbox->mailbox.write_pointer) &
+			mailbox->mailbox.mask;
+		mailbox->mailbox.data->vector.self.t[ndx] = msg;
+		mp_signal_semaphore(1, mailbox->mailbox.reader_semaphore);
+	}
+	ecl_return1(env, output);
+}
+
diff --git a/src/c/threads/semaphore.d b/src/c/threads/semaphore.d
index 023735e..9f41eb6 100644
--- a/src/c/threads/semaphore.d
+++ b/src/c/threads/semaphore.d
@@ -127,3 +127,14 @@ mp_wait_on_semaphore(cl_object semaphore)
 	}
 	ecl_return1(env, output);
 }
+
+cl_object
+mp_try_get_semaphore(cl_object semaphore)
+{
+	cl_env_ptr env = ecl_process_env();
+	cl_object output;
+	unlikely_if (ecl_t_of(semaphore) != t_semaphore) {
+		FEerror_not_a_semaphore(semaphore);
+	}
+	ecl_return1(env, get_semaphore_inner(env, semaphore));
+}
diff --git a/src/h/external.h b/src/h/external.h
index e3dee77..10352f3 100755
--- a/src/h/external.h
+++ b/src/h/external.h
@@ -1742,6 +1742,7 @@ extern ECL_API cl_object mp_semaphore_count(cl_object);
 extern ECL_API cl_object mp_semaphore_name(cl_object);
 extern ECL_API cl_object mp_semaphore_wait_count(cl_object);
 extern ECL_API cl_object mp_wait_on_semaphore(cl_object);
+extern ECL_API cl_object mp_try_get_semaphore(cl_object);
 extern ECL_API cl_object mp_signal_semaphore _ECL_ARGS((cl_narg, cl_object, ...));
 extern ECL_API cl_object ecl_make_semaphore(cl_object name, cl_fixnum count);
 
@@ -1762,7 +1763,9 @@ extern ECL_API cl_object mp_mailbox_name(cl_object mailbox);
 extern ECL_API cl_object mp_mailbox_count(cl_object mailbox);
 extern ECL_API cl_object mp_mailbox_empty_p(cl_object);
 extern ECL_API cl_object mp_mailbox_read(cl_object mailbox);
+extern ECL_API cl_object mp_mailbox_try_read(cl_object mailbox);
 extern ECL_API cl_object mp_mailbox_send(cl_object mailbox, cl_object msg);
+extern ECL_API cl_object mp_mailbox_try_send(cl_object mailbox, cl_object msg);
 
 /* threads/atomic.c */
 
-- 
1.7.12

