aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/clojure/contrib/singleton.clj38
1 files changed, 31 insertions, 7 deletions
diff --git a/src/clojure/contrib/singleton.clj b/src/clojure/contrib/singleton.clj
index 4761581d..02b89f3b 100644
--- a/src/clojure/contrib/singleton.clj
+++ b/src/clojure/contrib/singleton.clj
@@ -1,7 +1,7 @@
;;; singleton.clj: singleton functions
;; by Stuart Sierra, http://stuartsierra.com/
-;; April 9, 2009
+;; April 14, 2009
;; Copyright (c) Stuart Sierra, 2009. All rights reserved. The use
;; and distribution terms for this software are covered by the Eclipse
@@ -12,16 +12,40 @@
;; remove this notice, or any other, from this software.
+;; Change Log:
+;;
+;; April 14, 2009: added per-thread-singleton, renamed singleton to
+;; global-singleton
+;;
+;; April 9, 2009: initial version
+
+
(ns clojure.contrib.singleton)
-(defn singleton
- "Returns a memoized version of a function with no arguments. The
- memoized version caches the function's return value.
+(defn global-singleton
+ "Returns a global singleton function. f is a function of no
+ arguments that creates and returns some object. The singleton
+ function will call f just once, the first time it is needed, and
+ cache the value for all subsequent calls.
- This is useful for lazily creating global objects that are expensive
- to initialize. Warning: Make sure you really want a single global
- instance, and not one instance per thread."
+ Warning: global singletons are often unsafe in multi-threaded code.
+ Consider per-thread-singleton instead."
[f]
(let [instance (atom nil)
make-instance (fn [_] (f))]
(fn [] (or @instance (swap! instance make-instance)))))
+
+(defn per-thread-singleton
+ "Returns a per-thread singleton function. f is a function of no
+ arguments that creates and returns some object. The singleton
+ function will call f only once for each thread, and cache its value
+ for subsequent calls from the same thread. This allows you to
+ safely and lazily initialize shared objects on a per-thread basis.
+
+ Warning: due to a bug in JDK 5, it may not be safe to use a
+ per-thread-singleton in the initialization function for another
+ per-thread-singleton. See
+ http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5025230"
+ [f]
+ (let [thread-local (proxy [ThreadLocal] [] (initialValue [] (f)))]
+ (fn [] (.get thread-local))))