summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS7
-rw-r--r--doc/ref/api-scheduling.texi38
-rw-r--r--libguile.h1
-rw-r--r--libguile/Makefile.am4
-rw-r--r--libguile/arbiters.c174
-rw-r--r--libguile/arbiters.h41
-rw-r--r--libguile/deprecated.c95
-rw-r--r--libguile/deprecated.h6
-rw-r--r--libguile/init.c2
-rw-r--r--module/oop/goops.scm6
-rw-r--r--test-suite/Makefile.am1
-rw-r--r--test-suite/tests/arbiters.test102
12 files changed, 112 insertions, 365 deletions
diff --git a/NEWS b/NEWS
index 2ee3d3f6e..f94e590bc 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,13 @@ Changes in 2.1.5 (changes since the 2.1.4 alpha release):
* New interfaces
* Performance improvements
* Incompatible changes
+* New deprecations
+** Arbiters deprecated
+
+Arbiters were an experimental mutual exclusion facility from 20 years
+ago that didn't survive the test of time. Use mutexes or atomic boxes
+instead.
+
* Bug fixes
diff --git a/doc/ref/api-scheduling.texi b/doc/ref/api-scheduling.texi
index 38f5ac4a2..de076374d 100644
--- a/doc/ref/api-scheduling.texi
+++ b/doc/ref/api-scheduling.texi
@@ -8,7 +8,6 @@
@section Threads, Mutexes, Asyncs and Dynamic Roots
@menu
-* Arbiters:: Synchronization primitives.
* Asyncs:: Asynchronous procedure invocation.
* Atomics:: Atomic references.
* Threads:: Multiple threads of execution.
@@ -22,43 +21,6 @@
@end menu
-@node Arbiters
-@subsection Arbiters
-@cindex arbiters
-
-Arbiters are synchronization objects, they can be used by threads to
-control access to a shared resource. An arbiter can be locked to
-indicate a resource is in use, and unlocked when done.
-
-An arbiter is like a light-weight mutex (@pxref{Mutexes and Condition
-Variables}). It uses less memory and may be faster, but there's no
-way for a thread to block waiting on an arbiter, it can only test and
-get the status returned.
-
-@deffn {Scheme Procedure} make-arbiter name
-@deffnx {C Function} scm_make_arbiter (name)
-Return an object of type arbiter and name @var{name}. Its
-state is initially unlocked. Arbiters are a way to achieve
-process synchronization.
-@end deffn
-
-@deffn {Scheme Procedure} try-arbiter arb
-@deffnx {C Function} scm_try_arbiter (arb)
-If @var{arb} is unlocked, then lock it and return @code{#t}.
-If @var{arb} is already locked, then do nothing and return
-@code{#f}.
-@end deffn
-
-@deffn {Scheme Procedure} release-arbiter arb
-@deffnx {C Function} scm_release_arbiter (arb)
-If @var{arb} is locked, then unlock it and return @code{#t}. If
-@var{arb} is already unlocked, then do nothing and return @code{#f}.
-
-Typical usage is for the thread which locked an arbiter to later
-release it, but that's not required, any thread can release it.
-@end deffn
-
-
@node Asyncs
@subsection Asyncs
diff --git a/libguile.h b/libguile.h
index 8354e7cca..0a1f0dcd6 100644
--- a/libguile.h
+++ b/libguile.h
@@ -30,7 +30,6 @@ extern "C" {
#include "libguile/__scm.h"
#include "libguile/alist.h"
-#include "libguile/arbiters.h"
#include "libguile/array-handle.h"
#include "libguile/array-map.h"
#include "libguile/arrays.h"
diff --git a/libguile/Makefile.am b/libguile/Makefile.am
index e5011da91..31cff7587 100644
--- a/libguile/Makefile.am
+++ b/libguile/Makefile.am
@@ -120,7 +120,6 @@ libguile_@GUILE_EFFECTIVE_VERSION@_la_CFLAGS = $(GUILE_CFLAGS) $(AM_CFLAGS)
libguile_@GUILE_EFFECTIVE_VERSION@_la_SOURCES = \
alist.c \
- arbiters.c \
array-handle.c \
array-map.c \
arrays.c \
@@ -231,7 +230,6 @@ libguile_@GUILE_EFFECTIVE_VERSION@_la_SOURCES = \
DOT_X_FILES = \
alist.x \
- arbiters.x \
array-handle.x \
array-map.x \
arrays.x \
@@ -339,7 +337,6 @@ EXTRA_DOT_X_FILES = @EXTRA_DOT_X_FILES@
DOT_DOC_FILES = \
alist.doc \
- arbiters.doc \
array-handle.doc \
array-map.doc \
arrays.doc \
@@ -567,7 +564,6 @@ modincludedir = $(pkgincludedir)/$(GUILE_EFFECTIVE_VERSION)/libguile
modinclude_HEADERS = \
__scm.h \
alist.h \
- arbiters.h \
array-handle.h \
array-map.h \
arrays.h \
diff --git a/libguile/arbiters.c b/libguile/arbiters.c
deleted file mode 100644
index f1ace572d..000000000
--- a/libguile/arbiters.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/* Copyright (C) 1995,1996, 1997, 2000, 2001, 2004, 2005, 2006, 2008, 2011 Free Software Foundation, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 3 of
- * the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-
-
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "libguile/_scm.h"
-#include "libguile/ports.h"
-#include "libguile/smob.h"
-
-#include "libguile/validate.h"
-#include "libguile/arbiters.h"
-
-
-/* FETCH_STORE sets "fet" to the value fetched from "mem" and then stores
- "sto" there. The fetch and store are done atomically, so once the fetch
- has been done no other thread or processor can fetch from there before
- the store is done.
-
- The operands are scm_t_bits, fet and sto are plain variables, mem is a
- memory location (ie. an lvalue).
-
- ENHANCE-ME: Add more cpu-specifics. glibc atomicity.h has some of the
- sort of thing required. FETCH_STORE could become some sort of
- compare-and-store if that better suited what various cpus do. */
-
-#if defined (__GNUC__) && defined (i386) && SIZEOF_SCM_T_BITS == 4
-/* This is for i386 with the normal 32-bit scm_t_bits. The xchg instruction
- is atomic on a single processor, and it automatically asserts the "lock"
- bus signal so it's atomic on a multi-processor (no need for the lock
- prefix on the instruction).
-
- The mem operand is read-write but "+" is not used since old gcc
- (eg. 2.7.2) doesn't support that. "1" for the mem input doesn't work
- (eg. gcc 3.3) when mem is a pointer dereference like current usage below.
- Having mem as a plain input should be ok though. It tells gcc the value
- is live, but as an "m" gcc won't fetch it itself (though that would be
- harmless). */
-
-#define FETCH_STORE(fet,mem,sto) \
- do { \
- asm ("xchg %0, %1" \
- : "=r" (fet), "=m" (mem) \
- : "0" (sto), "m" (mem)); \
- } while (0)
-#endif
-
-#ifndef FETCH_STORE
-/* This is a generic version, with a mutex to ensure the operation is
- atomic. Unfortunately this approach probably makes arbiters no faster
- than mutexes (though still using less memory of course), so some
- CPU-specifics are highly desirable. */
-#define FETCH_STORE(fet,mem,sto) \
- do { \
- scm_i_scm_pthread_mutex_lock (&scm_i_misc_mutex); \
- (fet) = (mem); \
- (mem) = (sto); \
- scm_i_pthread_mutex_unlock (&scm_i_misc_mutex); \
- } while (0)
-#endif
-
-
-static scm_t_bits scm_tc16_arbiter;
-
-
-#define SCM_LOCK_VAL (scm_tc16_arbiter | (1L << 16))
-#define SCM_UNLOCK_VAL scm_tc16_arbiter
-#define SCM_ARB_LOCKED(arb) ((SCM_CELL_WORD_0 (arb)) & (1L << 16))
-
-
-static int
-arbiter_print (SCM exp, SCM port, scm_print_state *pstate)
-{
- scm_puts ("#<arbiter ", port);
- if (SCM_ARB_LOCKED (exp))
- scm_puts ("locked ", port);
- scm_iprin1 (SCM_PACK (SCM_SMOB_DATA (exp)), port, pstate);
- scm_putc ('>', port);
- return !0;
-}
-
-SCM_DEFINE (scm_make_arbiter, "make-arbiter", 1, 0, 0,
- (SCM name),
- "Return an arbiter object, initially unlocked. Currently\n"
- "@var{name} is only used for diagnostic output.")
-#define FUNC_NAME s_scm_make_arbiter
-{
- SCM_RETURN_NEWSMOB (scm_tc16_arbiter, SCM_UNPACK (name));
-}
-#undef FUNC_NAME
-
-
-/* The atomic FETCH_STORE here is so two threads can't both see the arbiter
- unlocked and return #t. The arbiter itself wouldn't be corrupted by
- this, but two threads both getting #t would be contrary to the intended
- semantics. */
-
-SCM_DEFINE (scm_try_arbiter, "try-arbiter", 1, 0, 0,
- (SCM arb),
- "If @var{arb} is unlocked, then lock it and return @code{#t}.\n"
- "If @var{arb} is already locked, then do nothing and return\n"
- "@code{#f}.")
-#define FUNC_NAME s_scm_try_arbiter
-{
- scm_t_bits old;
- scm_t_bits *loc;
- SCM_VALIDATE_SMOB (1, arb, arbiter);
- loc = (scm_t_bits*)SCM_SMOB_OBJECT_N_LOC (arb, 0);
- FETCH_STORE (old, *loc, SCM_LOCK_VAL);
- return scm_from_bool (old == SCM_UNLOCK_VAL);
-}
-#undef FUNC_NAME
-
-
-/* The atomic FETCH_STORE here is so two threads can't both see the arbiter
- locked and return #t. The arbiter itself wouldn't be corrupted by this,
- but we don't want two threads both thinking they were the unlocker. The
- intended usage is for the code which locked to be responsible for
- unlocking, but we guarantee the return value even if multiple threads
- compete. */
-
-SCM_DEFINE (scm_release_arbiter, "release-arbiter", 1, 0, 0,
- (SCM arb),
- "If @var{arb} is locked, then unlock it and return @code{#t}.\n"
- "If @var{arb} is already unlocked, then do nothing and return\n"
- "@code{#f}.\n"
- "\n"
- "Typical usage is for the thread which locked an arbiter to\n"
- "later release it, but that's not required, any thread can\n"
- "release it.")
-#define FUNC_NAME s_scm_release_arbiter
-{
- scm_t_bits old;
- scm_t_bits *loc;
- SCM_VALIDATE_SMOB (1, arb, arbiter);
- loc = (scm_t_bits*)SCM_SMOB_OBJECT_N_LOC (arb, 0);
- FETCH_STORE (old, *loc, SCM_UNLOCK_VAL);
- return scm_from_bool (old == SCM_LOCK_VAL);
-}
-#undef FUNC_NAME
-
-
-
-void
-scm_init_arbiters ()
-{
- scm_tc16_arbiter = scm_make_smob_type ("arbiter", 0);
- scm_set_smob_print (scm_tc16_arbiter, arbiter_print);
-#include "libguile/arbiters.x"
-}
-
-/*
- Local Variables:
- c-file-style: "gnu"
- End:
-*/
diff --git a/libguile/arbiters.h b/libguile/arbiters.h
deleted file mode 100644
index 214e92a34..000000000
--- a/libguile/arbiters.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* classes: h_files */
-
-#ifndef SCM_ARBITERS_H
-#define SCM_ARBITERS_H
-
-/* Copyright (C) 1995,1996,2000, 2006, 2008 Free Software Foundation, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 3 of
- * the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-
-
-
-#include "libguile/__scm.h"
-
-
-
-SCM_API SCM scm_make_arbiter (SCM name);
-SCM_API SCM scm_try_arbiter (SCM arb);
-SCM_API SCM scm_release_arbiter (SCM arb);
-SCM_INTERNAL void scm_init_arbiters (void);
-
-#endif /* SCM_ARBITERS_H */
-
-/*
- Local Variables:
- c-file-style: "gnu"
- End:
-*/
diff --git a/libguile/deprecated.c b/libguile/deprecated.c
index af7643487..bae4ed449 100644
--- a/libguile/deprecated.c
+++ b/libguile/deprecated.c
@@ -486,10 +486,105 @@ scm_slot_exists_using_class_p (SCM class, SCM obj, SCM slot_name)
+#define FETCH_STORE(fet,mem,sto) \
+ do { \
+ scm_i_scm_pthread_mutex_lock (&scm_i_misc_mutex); \
+ (fet) = (mem); \
+ (mem) = (sto); \
+ scm_i_pthread_mutex_unlock (&scm_i_misc_mutex); \
+ } while (0)
+
+static scm_t_bits scm_tc16_arbiter;
+
+
+#define SCM_LOCK_VAL (scm_tc16_arbiter | (1L << 16))
+#define SCM_UNLOCK_VAL scm_tc16_arbiter
+#define SCM_ARB_LOCKED(arb) ((SCM_CELL_WORD_0 (arb)) & (1L << 16))
+
+
+static int
+arbiter_print (SCM exp, SCM port, scm_print_state *pstate)
+{
+ scm_puts ("#<arbiter ", port);
+ if (SCM_ARB_LOCKED (exp))
+ scm_puts ("locked ", port);
+ scm_iprin1 (SCM_PACK (SCM_SMOB_DATA (exp)), port, pstate);
+ scm_putc ('>', port);
+ return !0;
+}
+
+SCM_DEFINE (scm_make_arbiter, "make-arbiter", 1, 0, 0,
+ (SCM name),
+ "Return an arbiter object, initially unlocked. Currently\n"
+ "@var{name} is only used for diagnostic output.")
+#define FUNC_NAME s_scm_make_arbiter
+{
+ scm_c_issue_deprecation_warning
+ ("Arbiters are deprecated. "
+ "Use mutexes or atomic variables instead.");
+
+ SCM_RETURN_NEWSMOB (scm_tc16_arbiter, SCM_UNPACK (name));
+}
+#undef FUNC_NAME
+
+
+/* The atomic FETCH_STORE here is so two threads can't both see the arbiter
+ unlocked and return #t. The arbiter itself wouldn't be corrupted by
+ this, but two threads both getting #t would be contrary to the intended
+ semantics. */
+
+SCM_DEFINE (scm_try_arbiter, "try-arbiter", 1, 0, 0,
+ (SCM arb),
+ "If @var{arb} is unlocked, then lock it and return @code{#t}.\n"
+ "If @var{arb} is already locked, then do nothing and return\n"
+ "@code{#f}.")
+#define FUNC_NAME s_scm_try_arbiter
+{
+ scm_t_bits old;
+ scm_t_bits *loc;
+ SCM_VALIDATE_SMOB (1, arb, arbiter);
+ loc = (scm_t_bits*)SCM_SMOB_OBJECT_N_LOC (arb, 0);
+ FETCH_STORE (old, *loc, SCM_LOCK_VAL);
+ return scm_from_bool (old == SCM_UNLOCK_VAL);
+}
+#undef FUNC_NAME
+
+
+/* The atomic FETCH_STORE here is so two threads can't both see the arbiter
+ locked and return #t. The arbiter itself wouldn't be corrupted by this,
+ but we don't want two threads both thinking they were the unlocker. The
+ intended usage is for the code which locked to be responsible for
+ unlocking, but we guarantee the return value even if multiple threads
+ compete. */
+
+SCM_DEFINE (scm_release_arbiter, "release-arbiter", 1, 0, 0,
+ (SCM arb),
+ "If @var{arb} is locked, then unlock it and return @code{#t}.\n"
+ "If @var{arb} is already unlocked, then do nothing and return\n"
+ "@code{#f}.\n"
+ "\n"
+ "Typical usage is for the thread which locked an arbiter to\n"
+ "later release it, but that's not required, any thread can\n"
+ "release it.")
+#define FUNC_NAME s_scm_release_arbiter
+{
+ scm_t_bits old;
+ scm_t_bits *loc;
+ SCM_VALIDATE_SMOB (1, arb, arbiter);
+ loc = (scm_t_bits*)SCM_SMOB_OBJECT_N_LOC (arb, 0);
+ FETCH_STORE (old, *loc, SCM_UNLOCK_VAL);
+ return scm_from_bool (old == SCM_LOCK_VAL);
+}
+#undef FUNC_NAME
+
+
+
void
scm_i_init_deprecated ()
{
+ scm_tc16_arbiter = scm_make_smob_type ("arbiter", 0);
+ scm_set_smob_print (scm_tc16_arbiter, arbiter_print);
#include "libguile/deprecated.x"
}
diff --git a/libguile/deprecated.h b/libguile/deprecated.h
index 592dc98d5..5e8e8f819 100644
--- a/libguile/deprecated.h
+++ b/libguile/deprecated.h
@@ -217,6 +217,12 @@ SCM_DEPRECATED SCM scm_slot_exists_using_class_p (SCM cls, SCM obj, SCM slot_nam
+SCM_DEPRECATED SCM scm_make_arbiter (SCM name);
+SCM_DEPRECATED SCM scm_try_arbiter (SCM arb);
+SCM_DEPRECATED SCM scm_release_arbiter (SCM arb);
+
+
+
void scm_i_init_deprecated (void);
#endif
diff --git a/libguile/init.c b/libguile/init.c
index 3738538ae..31363c69b 100644
--- a/libguile/init.c
+++ b/libguile/init.c
@@ -35,7 +35,6 @@
/* Everybody has an init function. */
#include "libguile/alist.h"
-#include "libguile/arbiters.h"
#include "libguile/async.h"
#include "libguile/atomic.h"
#include "libguile/backtrace.h"
@@ -419,7 +418,6 @@ scm_i_init_guile (void *base)
scm_init_thread_procs (); /* requires gsubrs */
scm_init_procprop ();
scm_init_alist ();
- scm_init_arbiters (); /* requires smob_prehistory */
scm_init_async (); /* requires smob_prehistory */
scm_init_boolean ();
scm_init_chars ();
diff --git a/module/oop/goops.scm b/module/oop/goops.scm
index 6dae45418..1d56cc7e1 100644
--- a/module/oop/goops.scm
+++ b/module/oop/goops.scm
@@ -74,7 +74,7 @@
;; corresponding classes, which may be obtained via class-of,
;; once you have an instance. Perhaps FIXME to provide a
;; smob-type-name->class procedure.
- <arbiter> <promise> <thread> <mutex> <condition-variable>
+ <promise> <thread> <mutex> <condition-variable>
<regexp> <hook> <bitvector> <random-state> <async>
<directory> <array> <character-set>
<dynamic-object> <guardian> <macro>
@@ -3096,7 +3096,9 @@ var{initargs}."
;;; {SMOB and port classes}
;;;
-(define <arbiter> (find-subclass <top> '<arbiter>))
+(begin-deprecated
+ (define-public <arbiter> (find-subclass <top> '<arbiter>)))
+
(define <promise> (find-subclass <top> '<promise>))
(define <thread> (find-subclass <top> '<thread>))
(define <mutex> (find-subclass <top> '<mutex>))
diff --git a/test-suite/Makefile.am b/test-suite/Makefile.am
index 3c88405cb..f940d78c7 100644
--- a/test-suite/Makefile.am
+++ b/test-suite/Makefile.am
@@ -26,7 +26,6 @@ SCM_TESTS = tests/00-initial-env.test \
tests/00-socket.test \
tests/alist.test \
tests/and-let-star.test \
- tests/arbiters.test \
tests/arrays.test \
tests/bit-operations.test \
tests/bitvectors.test \
diff --git a/test-suite/tests/arbiters.test b/test-suite/tests/arbiters.test
deleted file mode 100644
index 36dc7edbd..000000000
--- a/test-suite/tests/arbiters.test
+++ /dev/null
@@ -1,102 +0,0 @@
-;;;; arbiters.test --- test arbiters functions -*- scheme -*-
-;;;;
-;;;; Copyright (C) 2004, 2006 Free Software Foundation, Inc.
-;;;;
-;;;; This library is free software; you can redistribute it and/or
-;;;; modify it under the terms of the GNU Lesser General Public
-;;;; License as published by the Free Software Foundation; either
-;;;; version 3 of the License, or (at your option) any later version.
-;;;;
-;;;; This library is distributed in the hope that it will be useful,
-;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-;;;; Lesser General Public License for more details.
-;;;;
-;;;; You should have received a copy of the GNU Lesser General Public
-;;;; License along with this library; if not, write to the Free Software
-;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-(define-module (test-suite test-arbiters)
- #:use-module (test-suite lib))
-
-;;;
-;;; arbiter display
-;;;
-
-(with-test-prefix "arbiter display"
- ;; nothing fancy, just exercise the printing code
-
- (pass-if "never locked"
- (let ((arb (make-arbiter "foo"))
- (port (open-output-string)))
- (display arb port)
- #t))
-
- (pass-if "locked"
- (let ((arb (make-arbiter "foo"))
- (port (open-output-string)))
- (try-arbiter arb)
- (display arb port)
- #t))
-
- (pass-if "unlocked"
- (let ((arb (make-arbiter "foo"))
- (port (open-output-string)))
- (try-arbiter arb)
- (release-arbiter arb)
- (display arb port)
- #t)))
-
-;;;
-;;; try-arbiter
-;;;
-
-(with-test-prefix "try-arbiter"
-
- (pass-if "lock"
- (let ((arb (make-arbiter "foo")))
- (try-arbiter arb)))
-
- (pass-if "already locked"
- (let ((arb (make-arbiter "foo")))
- (try-arbiter arb)
- (not (try-arbiter arb))))
-
- (pass-if "already locked twice"
- (let ((arb (make-arbiter "foo")))
- (try-arbiter arb)
- (try-arbiter arb)
- (not (try-arbiter arb)))))
-
-;;;
-;;; release-arbiter
-;;;
-
-(with-test-prefix "release-arbiter"
-
- (pass-if "lock"
- (let ((arb (make-arbiter "foo")))
- (try-arbiter arb)
- (release-arbiter arb)))
-
- (pass-if "never locked"
- (let ((arb (make-arbiter "foo")))
- (not (release-arbiter arb))))
-
- (pass-if "never locked twice"
- (let ((arb (make-arbiter "foo")))
- (release-arbiter arb)
- (not (release-arbiter arb))))
-
- (pass-if "already unlocked"
- (let ((arb (make-arbiter "foo")))
- (try-arbiter arb)
- (release-arbiter arb)
- (not (release-arbiter arb))))
-
- (pass-if "already unlocked twice"
- (let ((arb (make-arbiter "foo")))
- (try-arbiter arb)
- (release-arbiter arb)
- (release-arbiter arb)
- (not (release-arbiter arb)))))