ewa Writer/director Steve McQueen reframes the whitewashed image of WWII's London bombings via a harrowing childhood adventure By www.inlander.com Published On :: Thu, 07 Nov 2024 01:30:00 -0800 Blitz opens amid a terrifying conflagration on a nighttime city street… Full Article Screen/Movie Reviews
ewa Kristen Stewart to Front 'Crimes of the Future', Selena Gomez to Lead 'Spiral' By www.aceshowbiz.com Published On :: Sat, 01 May 2021 20:39:24 +0000 The former 'Twilight' actress is set to play one of the major characters in sci-fi thriller 'Crimes of the Future' while the Disney alum is signed on for psychological thriller 'Spiral'. Full Article movie Crimes of the Future Kristen Stewart;Selena Gomez;Spiral
ewa Reward offered for information regarding baby’s death By thebirminghampress.com Published On :: Thu, 15 Jul 2021 22:59:44 +0000 Charity offers £5,000 reward over tragic discovery of baby’s body in Walsall canal. Full Article Community Crime Crimestoppers
ewa Crimestoppers offering reward over Walsall shooting By thebirminghampress.com Published On :: Thu, 20 May 2021 23:00:00 +0000 £5,000 reward offered for information on attempted murder shooting. Full Article Crime Emergency Services Crimestoppers
ewa Video Chats, Driveway Dances And Dino Parades Buffer Pandemic's Loneliness By www.gpbnews.org Published On :: Wed, 15 Jul 2020 09:00:00 +0000 When COVID-19 barreled into the U.S. this year the predominant public health advice for avoiding infection focused on physical isolation: No parties, concerts, or sports events. No congregating inside in bars or restaurants. No on-site family reunions. No play dates for kids. Just keep away from other people. Meanwhile, although social scientists supported that medical advice, they feared the required physical distancing would spark another epidemic — one of loneliness, which was already at a high level in the U.S. "You might expect this would make things much worse," says Julianne Holt-Lunstad , a neuroscientist and social psychologist at Brigham Young University. But several new studies suggest that huge increase in loneliness hasn't come to pass — at least, not yet. And the researchers studying the pandemic's emotional fallout say we humans may have ourselves to thank. "That sense of solidarity that people are feeling when they ... are collectively going through a challenge together Full Article
ewa Issues of the Environment: Ann Arbor school district making progress toward renewable energy and other sustainability goals By www.wemu.org Published On :: Wed, 04 Sep 2024 06:35:56 -0400 The Ann Arbor School District is transitioning away from the use of fossil fuels. The district was the first to sign up for DTE Energy’s MIGreen Power Program to get to 100% use of renewable energy, and the district will add four more all-electric school buses this academic year. WEMU's David Fair spoke with the Ann Arbor Schools' Director of Capital Programs, Jason Bing, about where the district is today and where it’s headed. Full Article
ewa Lottery Scam - WESTERN UNION CUSTOMER REWARD PROMOTION By www.cybertopcops.com Published On :: Tue, 08 Apr 2014 21:48:15 +0200 A SCREAMING 419 scammer. Maybe he is frustrated because nobody believes in the $700,000 prize money. Full Article
ewa Banking Phishing Scam - Your StandardBank Cash Rewards Programme By www.cybertopcops.com Published On :: Sat, 13 Sep 2014 09:25:42 +0200 Phishing scammers using UCount awards as bait to steal your Standard Bank Internet Banking login details. Full Article
ewa Outpost Firewall Pro Review By www.cybertopcops.com Published On :: Sat, 14 Jul 2012 21:33:59 GMT Read our review of Outpost Firewall Pro, the best software firewall solution in the industry. Full Article
ewa How To Improve the avast! Internet Security Firewall By www.nicetoknow.co.za Published On :: Tue, 01 Apr 2014 18:51:31 GMT A quick and easy way of making the avast! Internet Security Firewall much more effective. Full Article
ewa Ready for launch: Colorado-based astronauts to take on first commercial spacewalk By www.denverpost.com Published On :: Mon, 22 Jul 2024 12:00:40 +0000 What do a former violinist and a retired military pilot have in common? They're both from Colorado and launching into space this summer. Full Article Business Colorado News Latest Headlines News aerospace Air Force Boulder engineering International Space Station military NASA space SpaceX travel University of Colorado University of Colorado Boulder
ewa Minister Attends Renewable Energy Forum By bernews.com Published On :: Thu, 04 Nov 2021 22:08:03 +0000 Minister of Home Affairs Walter Roban represented Bermuda at the 13th Caribbean Renewable Energy Forum [CREF] held on the 28 and 29 of October. A Government spokesperson said, “The event is considered the largest annual event in the Caribbean energy market. This regional stakeholder event that explores opportunities to accelerate investment in clean energy is […] Full Article All Environment #SolarEnergy
ewa NSC To Begin Renewable Energy Phase 3 By bernews.com Published On :: Mon, 08 Aug 2022 13:51:56 +0000 The National Sports Centre said they “will commence work on the third phase of its renewable energy project which is expected to produce 20% savings on utility costs to the facility.” A spokesperson said, “Phase one, which has been completed, involved the installation of a new energy efficient heating/cooling system to regulate temperatures in the […] Full Article All Environment News Sports #OilAndEnergy #SolarEnergy
ewa Photos: Vehicle Overboard By Causeway By bernews.com Published On :: Sat, 14 May 2022 13:04:36 +0000 The two male occupants of the vehicle “did not appear to have been injured” after they crashed overboard in the area of the Causeway, the police confirmed today. A police spokesperson said, “Shortly before 6:00 a.m. today, Saturday, 14th May, 2022, police received a 911 report that a SUV had gone overboard at the Causeway. […] Full Article Accidents and fires Accidents/Fires All News Photos Videos #CarOverboard #Causeway #Collision
ewa Dr. Ewart Brown Pays Tribute To Quincy Jones By bernews.com Published On :: Tue, 05 Nov 2024 13:12:50 +0000 Former Premier of Bermuda Dr. Ewart Brown paid tribute to the late Quincy Jones, recalling that the celebrated musician and producer “loved Bermuda.” Dr. Brown said, “Meeting Quincy Jones and spending time with him was awesome. When I lived in Los Angeles, every single person I met who was in the entertainment industry recognized him […] Full Article All Entertainment Music News #BermudaPolitics
ewa 1:6 Scale Janeway Figure From Exo-6 By trektoday.com Published On :: Tue, 17 Aug 2021 22:19:13 +0000 Fans of Captain Janeway will be pleased to hear the announcement that a new Janeway... Full Article Section 31 EXO-6 figure Janeway
ewa SLC-0L-05: Lighting's Gateway Drug By strobist.blogspot.com Published On :: Wed, 25 Nov 2020 22:26:00 +0000 Quick, guess the lighting.If you said two lights, and use of high-speed sync to get the shallow depth of field, that's a pretty good guess.If you said zero lights and a rigid high-efficiency reflector, that's an even better (and correct) guess.When working with an inexperienced assistant — or looking to introduce someone to the world of off-camera lighting — a rigid/high-efficiency reflector is a fantastic and inexpensive place to start.Read more » Full Article
ewa TurtleWare: Dynamic Vars - A New Hope By turtleware.eu Published On :: Tue, 22 Oct 2024 00:00:00 GMT Table of Contents Dynamic Bindings The problem The solution Dynamic slots The context Summary Dynamic Bindings Common Lisp has an important language feature called dynamic binding. It is possible to rebind a dynamic variable somewhere on the call stack and downstream functions will see that new value, and when the stack is unwound, the old value is brought back. While Common Lisp does not specify multi-threading, it seems to be a consensus among various implementations that dynamic bindings are thread-local, allowing for controlling the computing context in a safe way. Before we start experiments, let's define a package to isolate our namespace: (defpackage "EU.TURTLEWARE.BLOG/DLET" (:local-nicknames ("MOP" #+closer-mop "C2MOP" #+(and (not closer-mop) ecl) "MOP" #+(and (not closer-mop) ccl) "CCL" #+(and (not closer-mop) sbcl) "SB-MOP")) (:use "CL")) (in-package "EU.TURTLEWARE.BLOG/DLET") Dynamic binding of variables is transparent to the programmer, because the operator LET is used for both lexical and dynamic bindings. For example: (defvar *dynamic-variable* 42) (defun test () (let ((*dynamic-variable* 15) (lexical-variable 12)) (lambda () (print (cons *dynamic-variable* lexical-variable))))) (funcall (test)) ;;; (42 . 12) (let ((*dynamic-variable* 'xx)) (funcall (test))) ;;; (xx . 12) Additionally the language specifies a special operator PROGV that gives the programmer a control over the dynamic binding mechanism, by allowing passing the dynamic variable by value instead of its name. Dynamic variables are represented by symbols: (progv (list '*dynamic-variable*) (list 'zz) (funcall (test))) ;;; (zz . 12) The problem Nowadays it is common to encapsulate the state in the instance of a class. Sometimes that state is dynamic. It would be nice if we could use dynamic binding to control it. That said slots are not variables, and if there are many objects of the same class with different states, then using dynamic variables defined with DEFVAR is not feasible. Consider the following classes which we want to be thread-safe: (defgeneric call-with-ink (cont window ink)) (defclass window-1 () ((ink :initform 'red :accessor ink))) (defmethod call-with-ink (cont (win window-1) ink) (let ((old-ink (ink win))) (setf (ink win) ink) (unwind-protect (funcall cont) (setf (ink win) old-ink)))) (defclass window-2 () ()) (defvar *ink* 'blue) (defmethod ink ((window window-2)) *ink*) (defmethod call-with-ink (cont (win window-2) ink) (let ((*ink* ink)) (funcall cont))) The first example is clearly not thread safe. If we access the WINDOW-1 instance from multiple threads, then they will overwrite a value of the slot INK. The second example is not good either, because when we have many instances of WINDOW-2 then they share the binding. Nesting CALL-WITH-INK will overwrite the binding of another window. The solution The solution is to use PROGV: (defclass window-3 () ((ink :initform (gensym)))) (defmethod initialize-instance :after ((win window-3) &key) (setf (symbol-value (slot-value win 'ink)) 'red)) (defmethod call-with-ink (cont (win window-3) ink) (progv (list (slot-value win 'ink)) (list ink) (funcall cont))) This way each instance has its own dynamic variable that may be rebound with a designated operator CALL-WITH-INK. It is thread-safe and private. We may add some syntactic sugar so it is more similar to let: (defmacro dlet (bindings &body body) (loop for (var val) in bindings collect var into vars collect val into vals finally (return `(progv (list ,@vars) (list ,@vals) ,@body)))) (defmacro dset (&rest pairs) `(setf ,@(loop for (var val) on pairs by #'cddr collect `(symbol-value ,var) collect val))) (defmacro dref (variable) `(symbol-value ,variable)) Dynamic slots While meta-classes are not easily composable, it is worth noting that we can mold it better into the language by specifying that slot itself has a dynamic value. This way CLOS aficionados will have a new tool in their arsenal. The approach we'll take is that a fresh symbol is stored as the value of each instance-allocated slot, and then accessors for the slot value will use these symbols as a dynamic variable. Here are low-level accessors: ;;; Accessing and binding symbols behind the slot. We don't use SLOT-VALUE, ;;; because it will return the _value_ of the dynamic variable, and not the ;;; variable itself. (defun slot-dvar (object slotd) (mop:standard-instance-access object (mop:slot-definition-location slotd))) (defun slot-dvar* (object slot-name) (let* ((class (class-of object)) (slotd (find slot-name (mop:class-slots class) :key #'mop:slot-definition-name))) (slot-dvar object slotd))) (defmacro slot-dlet (bindings &body body) `(dlet ,(loop for ((object slot-name) val) in bindings collect `((slot-dvar* ,object ,slot-name) ,val)) ,@body)) Now we'll define the meta-class. We need that to specialize functions responsible for processing slot definitions and the instance allocation. Notice, that we make use of a kludge to communicate between COMPUTE-EFFECTIVE-SLOT-DEFINITION and EFFECTIVE-SLOT-DEFINITION-CLASS – this is because the latter has no access to the direct slot definitions. ;;; The metaclass CLASS-WITH-DYNAMIC-SLOTS specifies alternative effective slot ;;; definitions for slots with an initarg :dynamic. (defclass class-with-dynamic-slots (standard-class) ()) ;;; Class with dynamic slots may be subclasses of the standard class. (defmethod mop:validate-superclass ((class class-with-dynamic-slots) (super standard-class)) t) ;;; When allocating the instance we initialize all slots to a fresh symbol that ;;; represents the dynamic variable. (defmethod allocate-instance ((class class-with-dynamic-slots) &rest initargs) (declare (ignore initargs)) (let ((object (call-next-method))) (loop for slotd in (mop:class-slots class) when (typep slotd 'dynamic-effective-slot) do (setf (mop:standard-instance-access object (mop:slot-definition-location slotd)) (gensym (string (mop:slot-definition-name slotd))))) object)) ;;; To improve potential composability of CLASS-WITH-DYNAMIC-SLOTS with other ;;; metaclasses we treat specially only slots that has :DYNAMIC in initargs, ;;; otherwise we call the next method. (defmethod mop:direct-slot-definition-class ((class class-with-dynamic-slots) &rest initargs) (loop for (key val) on initargs by #'cddr when (eq key :dynamic) do (return-from mop:direct-slot-definition-class (find-class 'dynamic-direct-slot))) (call-next-method)) ;;; The metaobject protocol did not specify an elegant way to communicate ;;; between the direct slot definition and the effective slot definition. ;;; Luckily we have dynamic bindings! :-) (defvar *kludge/mop-deficiency/dynamic-slot-p* nil) (defmethod mop:compute-effective-slot-definition ((class class-with-dynamic-slots) name direct-slotds) (if (typep (first direct-slotds) 'dynamic-direct-slot) (let* ((*kludge/mop-deficiency/dynamic-slot-p* t)) (call-next-method)) (call-next-method))) (defmethod mop:effective-slot-definition-class ((class class-with-dynamic-slots) &rest initargs) (declare (ignore initargs)) (if *kludge/mop-deficiency/dynamic-slot-p* (find-class 'dynamic-effective-slot) (call-next-method))) Finally we define a direct and an effective slot classes, and specialize slot accessors that are invoked by the instance accessors. ;;; There is a considerable boilerplate involving customizing slots. ;;; ;;; - direct slot definition: local to a single defclass form ;;; ;;; - effective slot definition: combination of all direct slots with the same ;;; name in the class and its superclasses ;;; (defclass dynamic-direct-slot (mop:standard-direct-slot-definition) ((dynamic :initform nil :initarg :dynamic :reader dynamic-slot-p))) ;;; DYNAMIC-EFFECTIVE-SLOT is implemented to return as slot-value values of the ;;; dynamic variable that is stored with the instance. ;;; ;;; It would be nice if we could specify :ALLOCATION :DYNAMIC for the slot, but ;;; then STANDARD-INSTANCE-ACCESS would go belly up. We could make a clever ;;; workaround, but who cares? (defclass dynamic-effective-slot (mop:standard-effective-slot-definition) ()) (defmethod mop:slot-value-using-class ((class class-with-dynamic-slots) object (slotd dynamic-effective-slot)) (dref (slot-dvar object slotd))) (defmethod (setf mop:slot-value-using-class) (new-value (class class-with-dynamic-slots) object (slotd dynamic-effective-slot)) (dset (slot-dvar object slotd) new-value)) (defmethod mop:slot-boundp-using-class ((class class-with-dynamic-slots) object (slotd dynamic-effective-slot)) (boundp (slot-dvar object slotd))) (defmethod mop:slot-makunbound-using-class ((class class-with-dynamic-slots) object (slotd dynamic-effective-slot)) (makunbound (slot-dvar object slotd))) With this, we can finally define a class with slots that have dynamic values. What's more, we may bind them like dynamic variables. ;;; Let there be light. (defclass window-4 () ((ink :initform 'red :dynamic t :accessor ink) (normal :initform 'normal :accessor normal)) (:metaclass class-with-dynamic-slots)) (let ((object (make-instance 'window-4))) (slot-dlet (((object 'ink) 15)) (print (ink object))) (print (ink object))) ContextL provides a similar solution with dynamic slots, although it provides much more, like layered classes. This example is much more self-contained. The context Lately I'm working on the repaint queue for McCLIM. While doing so I've decided to make stream operations thread-safe, so it is possible to draw on the stream and write to it from arbitrary thread asynchronously. The access to the output record history needs to be clearly locked, so that may be solved by the mutex. Graphics state is another story, consider the following functions running from separate threads: (defun team-red () (with-drawing-options (stream :ink +dark-red+) (loop for i from 0 below 50000 do (write-string (format nil "XXX: ~5d~%" i) stream)))) (defun team-blue () (with-drawing-options (stream :ink +dark-blue+) (loop for i from 0 below 50000 do (write-string (format nil "YYY: ~5d~%" i) stream)))) (defun team-pink () (with-drawing-options (stream :ink +deep-pink+) (loop for i from 0 below 25000 do (case (random 2) (0 (draw-rectangle* stream 200 (* i 100) 250 (+ (* i 100) 50))) (1 (draw-circle* stream 225 (+ (* i 100) 25) 25)))))) (defun gonow (stream) (window-clear stream) (time (let ((a (clim-sys:make-process #'team-red)) (b (clim-sys:make-process #'team-blue)) (c (clim-sys:make-process #'team-grue))) (bt:join-thread a) (bt:join-thread b) (bt:join-thread c) (format stream "done!~%"))) ) Operations like WRITE-STRING and DRAW-RECTANGLE can be implemented by holding a lock over the shared resource without much disruption. The drawing color on the other hand is set outside of the loop, so if we had locked the graphics state with a lock, then these functions would be serialized despite being called from different processes. The solution to this problem is to make graphics context a dynamic slot that is accessed with WITH-DRAWING-OPTIONS. Summary I hope that I've convinced you that dynamic variables are cool (I'm sure that majority of readers here are already convinced), and that dynamic slots are even cooler :-). Watch forward to the upcoming McCLIM release! If you like technical writeups like this, please consider supporting me on Patreon. Full Article
ewa TurtleWare: Dynamic Vars - The Empire Strikes Back By turtleware.eu Published On :: Mon, 28 Oct 2024 00:00:00 GMT Table of Contents Thread Local storage exhausted The layer of indirection I can fix her Let's write some tests! Summary Thread Local storage exhausted In the last post I've described a technique to use dynamic variables by value instead of the name by utilizing the operator PROGV. Apparently it works fine on all Common Lisp implementations I've tried except from SBCL, where the number of thread local variables is by default limited to something below 4000. To add salt to the injury, these variables are not garbage collected. Try the following code to crash into LDB: (defun foo () (loop for i from 0 below 4096 do (when (zerop (mod i 100)) (print i)) (progv (list (gensym)) (list 42) (values)))) (foo) This renders our new technique not very practical given SBCL popularity. We need to either abandon the idea or come up with a workaround. The layer of indirection Luckily for us we've already introduced a layer of indirection. Operators to access dynamic variables are called DLET, DSET and DREF. This means, that it is enough to provide a kludge implementation for SBCL with minimal changes to the remaining code. The old code works the same as previously except that instead of SYMBOL-VALUE we use the accessor DYNAMIC-VARIABLE-VALUE, and the old call to PROGV is now DYNAMIC-VARIABLE-PROGV. Moreover DYNAMIC-EFFECTIVE-SLOT used functions BOUNDP and MAKUNBOUND, so we replace these with DYNAMIC-VARIABLE-BOUND-P and DYNAMIC-VARIABLE-MAKUNBOUND. To abstract away things further we also introduce the constructor MAKE-DYNAMIC-VARIABLE (defpackage "EU.TURTLEWARE.BLOG/DLET" (:local-nicknames ("MOP" #+closer-mop "C2MOP" #+(and (not closer-mop) ecl) "MOP" #+(and (not closer-mop) ccl) "CCL" #+(and (not closer-mop) sbcl) "SB-MOP")) (:use "CL")) (in-package "EU.TURTLEWARE.BLOG/DLET") (eval-when (:compile-toplevel :execute :load-toplevel) (unless (member :bordeaux-threads *features*) (error "Please load BORDEAUX-THREADS.")) (when (member :sbcl *features*) (unless (member :fake-progv-kludge *features*) (format t "~&;; Using FAKE-PROGV-KLUDGE for SBCL.~%") (push :fake-progv-kludge *features*)))) (defmacro dlet (bindings &body body) (flet ((pred (binding) (and (listp binding) (= 2 (length binding))))) (unless (every #'pred bindings) (error "DLET: bindings must be lists of two values.~%~ Invalid bindings:~%~{ ~s~%~}" (remove-if #'pred bindings)))) (loop for (var val) in bindings collect var into vars collect val into vals finally (return `(dynamic-variable-progv (list ,@vars) (list ,@vals) ,@body)))) (defmacro dset (&rest pairs) `(setf ,@(loop for (var val) on pairs by #'cddr collect `(dref ,var) collect val))) (defmacro dref (variable) `(dynamic-variable-value ,variable)) ;;; ... (defmethod mop:slot-boundp-using-class ((class standard-class) object (slotd dynamic-effective-slot)) (dynamic-variable-bound-p (slot-dvar object slotd))) (defmethod mop:slot-makunbound-using-class ((class standard-class) object (slotd dynamic-effective-slot)) (dynamic-variable-makunbound (slot-dvar object slotd))) With these in place we can change the portable implementation to conform. #-fake-progv-kludge (progn (defun make-dynamic-variable () (gensym)) (defun dynamic-variable-value (variable) (symbol-value variable)) (defun (setf dynamic-variable-value) (value variable) (setf (symbol-value variable) value)) (defun dynamic-variable-bound-p (variable) (boundp variable)) (defun dynamic-variable-makunbound (variable) (makunbound variable)) (defmacro dynamic-variable-progv (vars vals &body body) `(progv ,vars ,vals ,@body))) I can fix her The implementation for SBCL will mediate access to the dynamic variable value with a synchronized hash table with weak keys. The current process is the key of the hash table and the list of bindings is the value of the hash table. For compatibility between implementations the top level value of the symbol will be shared. The variable +FAKE-UNBOUND+ is the marker that signifies, that the variable has no value. When the list of bindings is EQ to +CELL-UNBOUND+, then it means that we should use the global value. We add new bindings by pushing to it. #+fake-progv-kludge (progn (defvar +fake-unbound+ 'unbound) (defvar +cell-unbound+ '(no-binding)) (defclass dynamic-variable () ((tls-table :initform (make-hash-table :synchronized t :weakness :key) :reader dynamic-variable-tls-table) (top-value :initform +fake-unbound+ :accessor dynamic-variable-top-value))) (defun make-dynamic-variable () (make-instance 'dynamic-variable)) (defun dynamic-variable-bindings (dvar) (let ((process (bt:current-thread)) (tls-table (dynamic-variable-tls-table dvar))) (gethash process tls-table +cell-unbound+))) (defun (setf dynamic-variable-bindings) (value dvar) (let ((process (bt:current-thread)) (tls-table (dynamic-variable-tls-table dvar))) (setf (gethash process tls-table +cell-unbound+) value)))) We define two readers for the variable value - one that simply reads the value, and the other that signals an error if the variable is unbound. Writer for its value either replaces the current binding, or if the value cell is unbound, then we modify the top-level symbol value. We use the value +FAKE-UNBOUND+ to check whether the variable is bound and to make it unbound. #+fake-progv-kludge (progn (defun %dynamic-variable-value (dvar) (let ((tls-binds (dynamic-variable-bindings dvar))) (if (eq tls-binds +cell-unbound+) (dynamic-variable-top-value dvar) (car tls-binds)))) (defun dynamic-variable-value (dvar) (let ((tls-value (%dynamic-variable-value dvar))) (when (eq tls-value +fake-unbound+) (error 'unbound-variable :name "(unnamed)")) tls-value)) (defun (setf dynamic-variable-value) (value dvar) (let ((tls-binds (dynamic-variable-bindings dvar))) (if (eq tls-binds +cell-unbound+) (setf (dynamic-variable-top-value dvar) value) (setf (car tls-binds) value)))) (defun dynamic-variable-bound-p (dvar) (not (eq +fake-unbound+ (%dynamic-variable-value dvar)))) (defun dynamic-variable-makunbound (dvar) (setf (dynamic-variable-value dvar) +fake-unbound+))) Finally we define the operator to dynamically bind variables that behaves similar to PROGV. Note that we PUSH and POP from the thread-local hash table DYNAMIC-VARIABLE-BINDINGS, so no synchronization is necessary. #+fake-progv-kludge (defmacro dynamic-variable-progv (vars vals &body body) (let ((svars (gensym)) (svals (gensym)) (var (gensym)) (val (gensym))) `(let ((,svars ,vars)) (loop for ,svals = ,vals then (rest ,svals) for ,var in ,svars for ,val = (if ,svals (car ,svals) +fake-unbound+) do (push ,val (dynamic-variable-bindings ,var))) (unwind-protect (progn ,@body) (loop for ,var in ,svars do (pop (dynamic-variable-bindings ,var))))))) Let's write some tests! But of course, we are going to also write a test framework. It's short, I promise. As a bonus point the API is compatibile with fiveam, so it is possible to drop tests as is in the appropriate test suite. (defvar *all-tests* '()) (defun run-tests () (dolist (test (reverse *all-tests*)) (format *debug-io* "Test ~a... " test) (handler-case (funcall test) (serious-condition (c) (format *debug-io* "Failed: ~a~%" c)) (:no-error (&rest args) (declare (ignore args)) (format *debug-io* "Passed.~%"))))) (defmacro test (name &body body) `(progn (pushnew ',name *all-tests*) (defun ,name () ,@body))) (defmacro is (form) `(assert ,form)) (defmacro pass ()) (defmacro signals (condition form) `(is (block nil (handler-case ,form (,condition () (return t))) nil))) (defmacro finishes (form) `(is (handler-case ,form (serious-condition (c) (declare (ignore c)) nil) (:no-error (&rest args) (declare (ignore args)) t)))) Now let's get to tests. First we'll test our metaclass: (defclass dynamic-let.test-class () ((slot1 :initarg :slot1 :dynamic nil :accessor slot1) (slot2 :initarg :slot2 :dynamic t :accessor slot2) (slot3 :initarg :slot3 :accessor slot3)) (:metaclass class-with-dynamic-slots)) (defparameter *dynamic-let.test-instance-1* (make-instance 'dynamic-let.test-class :slot1 :a :slot2 :b :slot3 :c)) (defparameter *dynamic-let.test-instance-2* (make-instance 'dynamic-let.test-class :slot1 :x :slot2 :y :slot3 :z)) (test dynamic-let.1 (let ((o1 *dynamic-let.test-instance-1*) (o2 *dynamic-let.test-instance-2*)) (with-slots (slot1 slot2 slot3) o1 (is (eq :a slot1)) (is (eq :b slot2)) (is (eq :c slot3))) (with-slots (slot1 slot2 slot3) o2 (is (eq :x slot1)) (is (eq :y slot2)) (is (eq :z slot3))))) (test dynamic-let.2 (let ((o1 *dynamic-let.test-instance-1*) (o2 *dynamic-let.test-instance-2*)) (signals error (slot-dlet (((o1 'slot1) 1)) nil)) (slot-dlet (((o1 'slot2) :k)) (is (eq :k (slot-value o1 'slot2))) (is (eq :y (slot-value o2 'slot2)))))) (test dynamic-let.3 (let ((o1 *dynamic-let.test-instance-1*) (exit nil) (fail nil)) (flet ((make-runner (values) (lambda () (slot-dlet (((o1 'slot2) :start)) (let ((value (slot2 o1))) (unless (eq value :start) (setf fail value))) (loop until (eq exit t) do (setf (slot2 o1) (elt values (random (length values)))) (let ((value (slot2 o1))) (unless (member value values) (setf fail value) (setf exit t)))))))) (let ((r1 (bt:make-thread (make-runner '(:k1 :k2)))) (r2 (bt:make-thread (make-runner '(:k3 :k4)))) (r3 (bt:make-thread (make-runner '(:k5 :k6))))) (sleep .1) (setf exit t) (map nil #'bt:join-thread (list r1 r2 r3)) (is (eq (slot2 o1) :b)) (is (null fail)))))) Then let's test the dynamic variable itself: (test dynamic-let.4 "Test basic dvar operators." (let ((dvar (make-dynamic-variable))) (is (eql 42 (dset dvar 42))) (is (eql 42 (dref dvar))) (ignore-errors (dlet ((dvar :x)) (is (eql :x (dref dvar))) (error "foo"))) (is (eql 42 (dref dvar))))) (test dynamic-let.5 "Test bound-p operator." (let ((dvar (make-dynamic-variable))) (is (not (dynamic-variable-bound-p dvar))) (dset dvar 15) (is (dynamic-variable-bound-p dvar)) (dynamic-variable-makunbound dvar) (is (not (dynamic-variable-bound-p dvar))))) (test dynamic-let.6 "Test makunbound operator." (let ((dvar (make-dynamic-variable))) (dset dvar t) (is (dynamic-variable-bound-p dvar)) (finishes (dynamic-variable-makunbound dvar)) (is (not (dynamic-variable-bound-p dvar))))) (test dynamic-let.7 "Test locally bound-p operator." (let ((dvar (make-dynamic-variable))) (is (not (dynamic-variable-bound-p dvar))) (dlet ((dvar 15)) (is (dynamic-variable-bound-p dvar))) (is (not (dynamic-variable-bound-p dvar))))) (test dynamic-let.8 "Test locally unbound-p operator." (let ((dvar (make-dynamic-variable))) (dset dvar t) (is (dynamic-variable-bound-p dvar)) (dlet ((dvar nil)) (is (dynamic-variable-bound-p dvar)) (finishes (dynamic-variable-makunbound dvar)) (is (not (dynamic-variable-bound-p dvar)))) (is (dynamic-variable-bound-p dvar)))) (test dynamic-let.9 "Stress test the implementation (see :FAKE-PROGV-KLUDGE)." (finishes ; at the same time (let ((dvars (loop repeat 4096 collect (make-dynamic-variable)))) ;; ensure tls variable (loop for v in dvars do (dlet ((v 1)))) (loop for i from 0 below 4096 for r = (random 4096) for v1 in dvars for v2 = (elt dvars r) do (when (zerop (mod i 64)) (pass)) (dlet ((v1 42) (v2 43)) (values)))))) (test dynamic-let.0 "Stress test the implementation (see :FAKE-PROGV-KLUDGE)." (finishes ; can be gc-ed (loop for i from 0 below 4096 do (when (zerop (mod i 64)) (pass)) (dlet (((make-dynamic-variable) 42)) (values))))) All that is left is to test both dynamic variable implementations: BLOG/DLET> (lisp-implementation-type) "ECL" BLOG/DLET> (run-tests) Test DYNAMIC-LET.1... Passed. Test DYNAMIC-LET.2... Passed. Test DYNAMIC-LET.3... Passed. Test DYNAMIC-LET.4... Passed. Test DYNAMIC-LET.5... Passed. Test DYNAMIC-LET.6... Passed. Test DYNAMIC-LET.7... Passed. Test DYNAMIC-LET.8... Passed. Test DYNAMIC-LET.9... Passed. Test DYNAMIC-LET.0... Passed. NIL And with the kludge: BLOG/DLET> (lisp-implementation-type) "SBCL" BLOG/DLET> (run-tests) Test DYNAMIC-LET.1... Passed. Test DYNAMIC-LET.2... Passed. Test DYNAMIC-LET.3... Passed. Test DYNAMIC-LET.4... Passed. Test DYNAMIC-LET.5... Passed. Test DYNAMIC-LET.6... Passed. Test DYNAMIC-LET.7... Passed. Test DYNAMIC-LET.8... Passed. Test DYNAMIC-LET.9... Passed. Test DYNAMIC-LET.0... Passed. NIL Summary In this post we've made our implementation to work on SBCL even when there are more than a few thousand dynamic variables. We've also added a simple test suite that checks the basic behavior. As it often happens, after achieving some goal we get greedy and achieve more. That's the case here as well. In the next (and the last) post in this series I'll explore the idea of adding truly thread-local variables without a shared global value. This will be useful for lazily creating context on threads that are outside of our control. We'll also generalize the implementation so it is possible to subclass and implement ones own flavor of a dynamic variable. Full Article
ewa TurtleWare: Dynamic Vars - Return of the Jedi By turtleware.eu Published On :: Mon, 04 Nov 2024 00:00:00 GMT Table of Contents The protocol Control operators Synchronized hash tables with weakness First-class dynamic variables STANDARD-DYNAMIC-VARIABLE SURROGATE-DYNAMIC-VARIABLE Thread-local variables The protocol The implementation Thread-local slots What can we use it for? In the previous two posts I've presented an implementation of first-class dynamic variables using PROGV and a surrogate implementation for SBCL. Now we will double down on this idea and make the protocol extensible. Finally we'll implement a specialized version of dynamic variables where even the top level value of the variable is thread-local. The protocol Previously we've defined operators as either macros or functions. Different implementations were protected by the feature flag and symbols collided. Now we will introduce the protocol composed of a common superclass and functions that are specialized by particular implementations. Most notably we will introduce a new operator CALL-WITH-DYNAMIC-VARIABLE that is responsible for establishing a single binding. Thanks to that it will be possible to mix dynamic variables of different types within a single DLET statement. (defclass dynamic-variable () ()) (defgeneric dynamic-variable-bindings (dvar)) (defgeneric dynamic-variable-value (dvar)) (defgeneric (setf dynamic-variable-value) (value dvar)) (defgeneric dynamic-variable-bound-p (dvar)) (defgeneric dynamic-variable-makunbound (dvar)) (defgeneric call-with-dynamic-variable (cont dvar &optional value)) Moreover we'll define a constructor that is specializable by a key. This design will allow us to refer to the dynamic variable class by using a shorter name. We will also define the standard class to be used and an matching constructor. (defparameter *default-dynamic-variable-class* #-fake-progv-kludge 'standard-dynamic-variable #+fake-progv-kludge 'surrogate-dynamic-variable) (defgeneric make-dynamic-variable-using-key (key &rest initargs) (:method (class &rest initargs) (apply #'make-instance class initargs)) (:method ((class (eql t)) &rest initargs) (apply #'make-instance *default-dynamic-variable-class* initargs)) (:method ((class null) &rest initargs) (declare (ignore class initargs)) (error "Making a dynamic variable that is not, huh?"))) (defun make-dynamic-variable (&rest initargs) (apply #'make-dynamic-variable-using-key t initargs)) Control operators Control operators are the same as previously, that is a set of four macros that consume the protocol specified above. Note that DYNAMIC-VARIABLE-PROGV expands to a recursive call where each binding is processed separately. (defmacro dlet (bindings &body body) (flet ((pred (binding) (and (listp binding) (= 2 (length binding))))) (unless (every #'pred bindings) (error "DLET: bindings must be lists of two values.~%~ Invalid bindings:~%~{ ~s~%~}" (remove-if #'pred bindings)))) (loop for (var val) in bindings collect var into vars collect val into vals finally (return `(dynamic-variable-progv (list ,@vars) (list ,@vals) ,@body)))) (defmacro dset (&rest pairs) `(setf ,@(loop for (var val) on pairs by #'cddr collect `(dref ,var) collect val))) (defmacro dref (variable) `(dynamic-variable-value ,variable)) (defun call-with-dynamic-variable-progv (cont vars vals) (flet ((thunk () (if vals (call-with-dynamic-variable cont (car vars) (car vals)) (call-with-dynamic-variable cont (car vars))))) (if vars (call-with-dynamic-variable-progv #'thunk (cdr vars) (cdr vals)) (funcall cont)))) (defmacro dynamic-variable-progv (vars vals &body body) (let ((cont (gensym))) `(flet ((,cont () ,@body)) (call-with-dynamic-variable-progv (function ,cont) ,vars ,vals)))) Synchronized hash tables with weakness Previously we've used SBCL-specific options to define a synchronized hash table with weak keys. This won't do anymore, because we will need a similar object to implement the thread-local storage for top level values. trivial-garbage is a portability layer that allows to define hash tables with a specified weakness, but it does not provide an argument that would abstract away synchronization. We will ensure thread-safety with locks instead. (defclass tls-table () ((table :initform (trivial-garbage:make-weak-hash-table :test #'eq :weakness :key)) (lock :initform (bt:make-lock)))) (defun make-tls-table () (make-instance 'tls-table)) (defmacro with-tls-table ((var self) &body body) (let ((obj (gensym))) `(let* ((,obj ,self) (,var (slot-value ,obj 'table))) (bt:with-lock-held ((slot-value ,obj 'lock)) ,@body)))) First-class dynamic variables STANDARD-DYNAMIC-VARIABLE Previously in the default implementation we've represented dynamic variables with a symbol. The new implementation is similar except that the symbol is read from a STANDARD-OBJECT that represents the variable. This also enables us to specialize the function CALL-WITH-DYNAMIC-VARIABLE: (defclass standard-dynamic-variable (dynamic-variable) ((symbol :initform (gensym) :accessor dynamic-variable-bindings))) (defmethod dynamic-variable-value ((dvar standard-dynamic-variable)) (symbol-value (dynamic-variable-bindings dvar))) (defmethod (setf dynamic-variable-value) (value (dvar standard-dynamic-variable)) (setf (symbol-value (dynamic-variable-bindings dvar)) value)) (defmethod dynamic-variable-bound-p ((dvar standard-dynamic-variable)) (boundp (dynamic-variable-bindings dvar))) (defmethod dynamic-variable-makunbound ((dvar standard-dynamic-variable)) (makunbound (dynamic-variable-bindings dvar))) (defmethod call-with-dynamic-variable (cont (dvar standard-dynamic-variable) &optional (val nil val-p)) (progv (list (dynamic-variable-bindings dvar)) (if val-p (list val) ()) (funcall cont))) SURROGATE-DYNAMIC-VARIABLE The implementation of the SURROGATE-DYNAMIC-VARIABLE is almost the same as previously. The only difference is that we use the previously defined indirection to safely work with hash tables. Also note, that we are not add the feature condition - both classes is always created. (defvar +fake-unbound+ 'unbound) (defvar +cell-unbound+ '(no-binding)) (defclass surrogate-dynamic-variable (dynamic-variable) ((tls-table :initform (make-tls-table) :reader dynamic-variable-tls-table) (top-value :initform +fake-unbound+ :accessor dynamic-variable-top-value))) (defmethod dynamic-variable-bindings ((dvar surrogate-dynamic-variable)) (let ((process (bt:current-thread))) (with-tls-table (tls-table (dynamic-variable-tls-table dvar)) (gethash process tls-table +cell-unbound+)))) (defmethod (setf dynamic-variable-bindings) (value (dvar surrogate-dynamic-variable)) (let ((process (bt:current-thread))) (with-tls-table (tls-table (dynamic-variable-tls-table dvar)) (setf (gethash process tls-table) value)))) (defun %dynamic-variable-value (dvar) (let ((tls-binds (dynamic-variable-bindings dvar))) (if (eq tls-binds +cell-unbound+) (dynamic-variable-top-value dvar) (car tls-binds)))) (defmethod dynamic-variable-value ((dvar surrogate-dynamic-variable)) (let ((tls-value (%dynamic-variable-value dvar))) (when (eq tls-value +fake-unbound+) (error 'unbound-variable :name "(unnamed)")) tls-value)) (defmethod (setf dynamic-variable-value) (value (dvar surrogate-dynamic-variable)) (let ((tls-binds (dynamic-variable-bindings dvar))) (if (eq tls-binds +cell-unbound+) (setf (dynamic-variable-top-value dvar) value) (setf (car tls-binds) value)))) (defmethod dynamic-variable-bound-p ((dvar surrogate-dynamic-variable)) (not (eq +fake-unbound+ (%dynamic-variable-value dvar)))) (defmethod dynamic-variable-makunbound ((dvar surrogate-dynamic-variable)) (setf (dynamic-variable-value dvar) +fake-unbound+)) ;;; Apparently CCL likes to drop^Helide some writes and that corrupts bindings ;;; table. Let's ensure that the value is volatile. #+ccl (defvar *ccl-ensure-volatile* nil) (defmethod call-with-dynamic-variable (cont (dvar surrogate-dynamic-variable) &optional (val +fake-unbound+)) (push val (dynamic-variable-bindings dvar)) (let (#+ccl (*ccl-ensure-volatile* (dynamic-variable-bindings dvar))) (unwind-protect (funcall cont) (pop (dynamic-variable-bindings dvar))))) Thread-local variables We've refactored the previous code to be extensible. Now we can use metaobjects from the previous post without change. We can also test both implementations in the same process interchangeably by customizing the default class parameter. It is the time now to have some fun and extend dynamic variables into variables with top value not shared between different threads. This will enable ultimate thread safety. With our new protocol the implementation is trivial! The protocol First we will define the protocol class. THREAD-LOCAL-VARIABLE is a variant of a DYNAMIC-VARIABLE with thread-local top values. We specify initialization arguments :INITVAL and :INITFUN that will be used to assign the top value of a binding. The difference is that INITVAL specifies a single value, while INITFUN can produce an unique object on each invocation. INITARG takes a precedence over INTIFUN, and if neither is supplied, then a variable is unbound. We include the constructor that builds on MAKE-DYNAMIC-VARIABLE-USING-KEY, and macros corresponding to DEFVAR and DEFPARAMETER. Note that they expand to :INITFUN - this assures that the initialization form is re-evaluated for each new thread where the variable is used. (defclass thread-local-variable (dynamic-variable) ()) (defmethod initialize-instance :after ((self thread-local-variable) &key initfun initval) (declare (ignore self initfun initval))) (defparameter *default-thread-local-variable-class* #-fake-progv-kludge 'standard-thread-local-variable #+fake-progv-kludge 'surrogate-thread-local-variable) (defun make-thread-local-variable (&rest initargs) (apply #'make-dynamic-variable-using-key *default-thread-local-variable-class* initargs)) (defmacro create-tls-variable (&optional (form nil fp) &rest initargs) `(make-thread-local-variable ,@(when fp `(:initfun (lambda () ,form))) ,@initargs)) (defmacro define-tls-variable (name &rest initform-and-initargs) `(defvar ,name (create-tls-variable ,@initform-and-initargs))) (defmacro define-tls-parameter (name &rest initform-and-initargs) `(defparameter ,name (create-tls-variable ,@initform-and-initargs))) Perhaps it is a good time to introduce a new convention for tls variable names. I think that surrounding names with the minus sign is a nice idea, because it signifies, that it is something less than a global value. For example: DYNAMIC-VARS> (define-tls-variable -context- (progn (print "Initializing context!") (list :context))) -CONTEXT- DYNAMIC-VARS> -context- #<a EU.TURTLEWARE.DYNAMIC-VARS::STANDARD-THREAD-LOCAL-VARIABLE 0x7f7636c08640> DYNAMIC-VARS> (dref -context-) "Initializing context!" (:CONTEXT) DYNAMIC-VARS> (dref -context-) (:CONTEXT) DYNAMIC-VARS> (dset -context- :the-new-value) :THE-NEW-VALUE DYNAMIC-VARS> (dref -context-) :THE-NEW-VALUE DYNAMIC-VARS> (bt:make-thread (lambda () (print "Let's read it!") (print (dref -context-)))) #<process "Anonymous thread" 0x7f7637a26cc0> "Let's read it!" "Initializing context!" (:CONTEXT) DYNAMIC-VARS> (dref -context-) :THE-NEW-VALUE The implementation You might have noticed the inconspicuous operator DYNAMIC-VARIABLE-BINDINGS that is part of the protocol. It returns an opaque object that represents values of the dynamic variable in the current context: for STANDARD-DYNAMIC-VARIABLE it is a symbol for SURROGATE-DYNAMIC-VARIABLE it is a thread-local list of bindings In any case all other operators first take this object and then use it to read, write or bind the value. The gist of the tls variables implementation is to always return an object that is local to the thread. To store these objects we will use the tls-table we've defined earlier. (defclass thread-local-variable-mixin (dynamic-variable) ((tls-table :initform (make-tls-table) :reader dynamic-variable-tls-table) (tls-initfun :initarg :initfun :initform nil :accessor thread-local-variable-initfun) (tls-initval :initarg :initval :initform +fake-unbound+ :accessor thread-local-variable-initval))) For the class STANDARD-THREAD-LOCAL-VARIABLE we will simply return a different symbol depending on the thread: (defclass standard-thread-local-variable (thread-local-variable-mixin thread-local-variable standard-dynamic-variable) ()) (defmethod dynamic-variable-bindings ((tvar standard-thread-local-variable)) (flet ((make-new-tls-bindings () (let ((symbol (gensym)) (initval (thread-local-variable-initval tvar)) (initfun (thread-local-variable-initfun tvar))) (cond ((not (eq +fake-unbound+ initval)) (setf (symbol-value symbol) initval)) ((not (null initfun)) (setf (symbol-value symbol) (funcall initfun)))) symbol))) (let ((key (bt:current-thread))) (with-tls-table (tls-table (dynamic-variable-tls-table tvar)) (or (gethash key tls-table) (setf (gethash key tls-table) (make-new-tls-bindings))))))) And for the class SURROGATE-THREAD-LOCAL-VARIABLE the only difference from the SURROGATE-DYNAMIC-VARIABLE implementation is to cons a new list as the initial value (even when it is unbound) to ensure it is not EQ to +CELL-UNBOUND+. (defclass surrogate-thread-local-variable (thread-local-variable-mixin thread-local-variable surrogate-dynamic-variable) ()) (defmethod dynamic-variable-bindings ((tvar surrogate-thread-local-variable)) (flet ((make-new-tls-bindings () (let ((initval (thread-local-variable-initval tvar)) (initfun (thread-local-variable-initfun tvar))) (cond ((not (eq +fake-unbound+ initval)) (list initval)) ((not (null initfun)) (list (funcall initfun))) (t (list +fake-unbound+)))))) (let ((key (bt:current-thread))) (with-tls-table (tls-table (dynamic-variable-tls-table tvar)) (or (gethash key tls-table) (setf (gethash key tls-table) (make-new-tls-bindings))))))) That's all, now we have two implementations of thread-local variables. Ramifications are similar as with "ordinary" dynamic variables - the standard implementation is not advised for SBCL, because it will crash in LDB. Thread-local slots First we are going to allow to defined dynamic variable types with an abbreviated names. This will enable us to specify in the slot definition that type, for example (MY-SLOT :DYNAMIC :TLS :INITFORM 34) ;;; Examples how to add shorthand type names for the dynamic slots: (defmethod make-dynamic-variable-using-key ((key (eql :tls)) &rest initargs) (apply #'make-dynamic-variable-using-key *default-thread-local-variable-class* initargs)) (defmethod make-dynamic-variable-using-key ((key (eql :normal-tls)) &rest initargs) (apply #'make-dynamic-variable-using-key 'standard-thread-local-variable initargs)) (defmethod make-dynamic-variable-using-key ((key (eql :kludge-tls)) &rest initargs) (apply #'make-dynamic-variable-using-key 'surrogate-thread-local-variable initargs)) ;;; For *DEFAULT-DYNAMIC-VARIABLE* specify :DYNAMIC T. (defmethod make-dynamic-variable-using-key ((key (eql :normal-dyn)) &rest initargs) (apply #'make-dynamic-variable-using-key 'standard-dynamic-variable initargs)) (defmethod make-dynamic-variable-using-key ((key (eql :kludge-dyn)) &rest initargs) (apply #'make-dynamic-variable-using-key 'surrogate-dynamic-variable initargs)) In order to do that, we need to remember he value of the argument :DYNAMIC. We will read it with DYNAMIC-VARIABLE-TYPE and that value will be available in both direct and the effective slot: ;;; Slot definitions ;;; There is a considerable boilerplate involving customizing slots. ;;; ;;; - direct slot definition: local to a single defclass form ;;; ;;; - effective slot definition: combination of all direct slots with the same ;;; name in the class and its superclasses ;;; (defclass dynamic-direct-slot (mop:standard-direct-slot-definition) ((dynamic :initform nil :initarg :dynamic :reader dynamic-variable-type))) ;;; The metaobject protocol did not specify an elegant way to communicate ;;; between the direct slot definition and the effective slot definition. ;;; Luckily we have dynamic bindings! :-) (defvar *kludge/mop-deficiency/dynamic-variable-type* nil) ;;; DYNAMIC-EFFECTIVE-SLOT is implemented to return as slot-value values of the ;;; dynamic variable that is stored with the instance. ;;; ;;; It would be nice if we could specify :ALLOCATION :DYNAMIC for the slot, but ;;; then STANDARD-INSTANCE-ACCESS would go belly up. We could make a clever ;;; workaround, but who cares? (defclass dynamic-effective-slot (mop:standard-effective-slot-definition) ((dynamic :initform *kludge/mop-deficiency/dynamic-variable-type* :reader dynamic-variable-type))) Moreover we specialize the function MAKE-DYNAMIC-VARIABLE-USING-KEY to the effective slot class. The initargs in this method are meant for the instance. When the dynamic variable is created, we check whether it is a thread-local variable and initialize its INITVAL and INITFUN to values derived from INITARGS, MOP:SLOT-DEFINITION-INITARGS and MOP:SLOT-DEFINITION-INITFUN: (defmethod make-dynamic-variable-using-key ((key dynamic-effective-slot) &rest initargs) (let* ((dvar-type (dynamic-variable-type key)) (dvar (make-dynamic-variable-using-key dvar-type))) (when (typep dvar 'thread-local-variable) (loop with slot-initargs = (mop:slot-definition-initargs key) for (key val) on initargs by #'cddr when (member key slot-initargs) do (setf (thread-local-variable-initval dvar) val)) (setf (thread-local-variable-initfun dvar) (mop:slot-definition-initfunction key))) dvar)) The rest of the implementation of DYNAMIC-EFFECTIVE-SLOT is unchanged: (defmethod mop:slot-value-using-class ((class standard-class) object (slotd dynamic-effective-slot)) (dref (slot-dvar object slotd))) (defmethod (setf mop:slot-value-using-class) (new-value (class standard-class) object (slotd dynamic-effective-slot)) (dset (slot-dvar object slotd) new-value)) (defmethod mop:slot-boundp-using-class ((class standard-class) object (slotd dynamic-effective-slot)) (dynamic-variable-bound-p (slot-dvar object slotd))) (defmethod mop:slot-makunbound-using-class ((class standard-class) object (slotd dynamic-effective-slot)) (dynamic-variable-makunbound (slot-dvar object slotd))) The implementation of CLASS-WITH-DYNAMIC-SLOTS is also very similar. The first difference in that ALLOCATE-INSTANCE calls MAKE-DYNAMIC-VARIABLE-USING-KEY instead of MAKE-DYNAMIC-VARIABLE and supplies the effective slot definition as the key, and the instance initargs as the remaining arguments. Note that at this point initargs are already validated by MAKE-INSTANCE. The second difference is that MOP:COMPUTE-EFFECTIVE-SLOT-DEFINITION binds the flag *KLUDGE/MOP-DEFICIENCY/DYNAMIC-VARIABLE-TYPE* to DYNAMIC-VARIABLE-TYPE. ;;; This is a metaclass that allows defining dynamic slots that are bound with ;;; the operator SLOT-DLET, and, depending on the type, may have thread-local ;;; top value. ;;; ;;; The metaclass CLASS-WITH-DYNAMIC-SLOTS specifies alternative effective slot ;;; definitions for slots with an initarg :dynamic. (defclass class-with-dynamic-slots (standard-class) ()) ;;; Class with dynamic slots may be subclasses of the standard class. (defmethod mop:validate-superclass ((class class-with-dynamic-slots) (super standard-class)) t) ;;; When allocating the instance we initialize all slots to a fresh symbol that ;;; represents the dynamic variable. (defmethod allocate-instance ((class class-with-dynamic-slots) &rest initargs) (let ((object (call-next-method))) (loop for slotd in (mop:class-slots class) when (typep slotd 'dynamic-effective-slot) do (setf (mop:standard-instance-access object (mop:slot-definition-location slotd)) (apply #'make-dynamic-variable-using-key slotd initargs))) object)) ;;; To improve potential composability of CLASS-WITH-DYNAMIC-SLOTS with other ;;; metaclasses we treat specially only slots that has :DYNAMIC in initargs, ;;; otherwise we call the next method. (defmethod mop:direct-slot-definition-class ((class class-with-dynamic-slots) &rest initargs) (loop for (key) on initargs by #'cddr when (eq key :dynamic) do (return-from mop:direct-slot-definition-class (find-class 'dynamic-direct-slot))) (call-next-method)) (defmethod mop:compute-effective-slot-definition ((class class-with-dynamic-slots) name direct-slotds) (declare (ignore name)) (let ((latest-slotd (first direct-slotds))) (if (typep latest-slotd 'dynamic-direct-slot) (let ((*kludge/mop-deficiency/dynamic-variable-type* (dynamic-variable-type latest-slotd))) (call-next-method)) (call-next-method)))) (defmethod mop:effective-slot-definition-class ((class class-with-dynamic-slots) &rest initargs) (declare (ignore initargs)) (if *kludge/mop-deficiency/dynamic-variable-type* (find-class 'dynamic-effective-slot) (call-next-method))) Finally the implementation of SLOT-DLET does not change: ;;; Accessing and binding symbols behind the slot. We don't use SLOT-VALUE, ;;; because it will return the _value_ of the dynamic variable, and not the ;;; variable itself. (defun slot-dvar (object slotd) (check-type slotd dynamic-effective-slot) (mop:standard-instance-access object (mop:slot-definition-location slotd))) (defun slot-dvar* (object slot-name) (let* ((class (class-of object)) (slotd (find slot-name (mop:class-slots class) :key #'mop:slot-definition-name))) (slot-dvar object slotd))) (defmacro slot-dlet (bindings &body body) `(dlet ,(loop for ((object slot-name) val) in bindings collect `((slot-dvar* ,object ,slot-name) ,val)) ,@body)) Finally we can define a class with slots that do not share the top value: DYNAMIC-VARS> (defclass c1 () ((slot1 :initarg :slot1 :dynamic nil :accessor slot1) (slot2 :initarg :slot2 :dynamic t :accessor slot2) (slot3 :initarg :slot3 :dynamic :tls :accessor slot3)) (:metaclass class-with-dynamic-slots)) #<The EU.TURTLEWARE.DYNAMIC-VARS::CLASS-WITH-DYNAMIC-SLOTS EU.TURTLEWARE.DYNAMIC-VARS::C1> DYNAMIC-VARS> (with-slots (slot1 slot2 slot3) *object* (setf slot1 :x slot2 :y slot3 :z) (list slot1 slot2 slot3)) (:X :Y :Z) DYNAMIC-VARS> (bt:make-thread (lambda () (with-slots (slot1 slot2 slot3) *object* (setf slot1 :i slot2 :j slot3 :k) (print (list slot1 slot2 slot3))))) #<process "Anonymous thread" 0x7f76424c0240> (:I :J :K) DYNAMIC-VARS> (with-slots (slot1 slot2 slot3) *object* (list slot1 slot2 slot3)) (:I :J :Z) What can we use it for? Now that we know how to define thread-local variables, we are left with a question what can we use it for. Consider having a line-buffering stream. One possible implementation could be sketched as: (defclass line-buffering-stream (fancy-stream) ((current-line :initform (make-adjustable-string) :accessor current-line) (current-ink :initform +black+ :accessor current-ink))) (defmethod stream-write-char ((stream line-buffering-stream) char) (if (char= char # ewline) (terpri stream) (vector-push-extend char (current-line stream)))) (defmethod stream-terpri ((stream line-buffering-stream)) (%put-line-on-screen (current-line stream) (current-ink stream)) (setf (fill-pointer (current-line stream)) 0)) If this stream is shared between multiple threads, then even if individual operations and %PUT-LINE-ON-SCREEN are thread-safe , we have a problem. For example FORMAT writes are not usually atomic and individual lines are easily corrupted. If we use custom colors, these are also a subject of race conditions. The solution is as easy as making both slots thread-local. In that case the buffered line is private to each thread and it is put on the screen atomically: (defclass line-buffering-stream (fancy-stream) ((current-line :initform (make-adjustable-string) :accessor current-line :dynamic :tls) (current-ink :initform +black+ :accessor current-ink :dynamic :tls)) (:metaclass class-with-dynamic-slots)) Technique is not limited to streams. It may benefit thread-safe drawing, request processing, resource management and more. By subclassing DYNAMIC-VARIABLE we could create also variables that are local to different objects than processes. I hope that you've enjoyed reading this post as much as I had writing it. If you are interested in a full standalone implementation, with tests and system definitions, you may get it here. Cheers! Full Article
ewa nonrenewable resource By www.marriedtothesea.com Published On :: Wed, 04 Oct 2023 04:00:00 EDT Today on Married To The Sea: nonrenewable resourceThis RSS feed is brought to you by Drew and Natalie's podcast Garbage Brain University. Our new series Everything Is Real explores the world of cryptids, aliens, quantum physics, the occult, and more. If you use this RSS feed, please consider supporting us by becoming a patron. Patronage includes membership to our private Discord server and other bonus material non-patrons never see! Full Article autogen_comic
ewa EA Play: EA Sports FC 24 Joins the Play List This June, As Well as New Rewards By news.xbox.com Published On :: Thu, 20 Jun 2024 19:00:00 +0000 The post EA Play: EA Sports FC 24 Joins the Play List This June, As Well as New Rewards appeared first on Xbox Wire. Full Article Games Xbox Game Pass EA Play EA Play List EA Sports F1 24 EA Sports FC 24
ewa Open Gateway: Step into mock lunar orbit habitat at Space Center Houston By www.space.com Published On :: Tue, 12 Nov 2024 19:00:00 +0000 The public can now step into the future of lunar exploration at Space Center Houston by entering an early mockup for Northrop Grumman's Gateway astronaut accommodations around the moon. Full Article Artemis Space Exploration Missions
ewa The Naked Truth Behind ‘SNL’s Topless Martha Stewart Promo By www.cracked.com Published On :: Mon, 11 Nov 2024 06:00:00 -0800 By Brian VanHooker Published: November 11th, 2024 Full Article
ewa Girl Texts Guy Insult in an Attempt to Flirt, and Ends up Getting Stonewalled after Some Serious Awkwardness By cheezburger.com Published On :: Sun, 18 Sep 2016 10:00:00 -0700 It all starts with the anything-but-smooth introduction... Full Article FAIL tinder Awkward insult dating
ewa How to spend a weekend in Malaga, the cultural gateway to Andalucía By www.telegraph.co.uk Published On :: Sun, 08 Sep 2024 17:00:00 GMT Full Article topics:places/europe structure:travel/nightlife topics:places/malaga structure:travel/hotels storytype:standard travel-entity:article topics:places/andalusia topics:places/spain structure:travel/destination-guides-100 structure:travel structure:travel/attractions structure:travel/bars structure:better-life/better-life-evergreen structure:better-life/better-life-guide
ewa How iron-air batteries could fill gaps in renewable energy By www.pbs.org Published On :: Wed, 23 Aug 2023 04:18:00 +0000 Rust Belt cities could be the perfect place to develop this renewable energy solution. Full Article
ewa 'You're not marrying a Jew': Martha Stewart says her father slapped her after engagement By www.jpost.com Published On :: Wed, 30 Oct 2024 19:46:57 GMT In the documentary, Martha Stewart opens up about her childhood and the complicated relationship she had with her father. Full Article marriage celebrity netflix antisemitism
ewa News24 | Lottoland wins Google battle, Mogale City sewage disaster: Today's top 7 stories in 7 minutes By www.news24.com Published On :: Tuesday Nov 12 2024 18:32:16 News24 brings you the top stories of the day, summarised into neat little packages. Read through quickly or listen to the articles via our customised text-to-speech feature. Full Article
ewa News24 | WASTE LAND | Mogale City sewage disaster sees faeces-laden river water testing 100 times above legal limit By www.news24.com Published On :: Tuesday Nov 12 2024 04:45:19 Scientific tests confirm rivers and dams have been poisoned by the raw sewage dumped by the municipality in the Bloubankspruit and Crocodile Rivers, killing aquatic life and destroying businesses and livelihoods. Full Article
ewa Jon Stewart on the bewildering denial in remaining an undecided voter By boingboing.net Published On :: Tue, 01 Oct 2024 15:10:43 +0000 Jon Stewart tears apart the denials and false claims Trump supporters make about their terrible candidate and wonders how anyone can remain undecided. At the top of this piece by Stewart sits the strange claim MAGAs keep making that Vice President Harris isn't clear about her plans. — Read the rest The post Jon Stewart on the bewildering denial in remaining an undecided voter appeared first on Boing Boing. Full Article Post Entertainment politics video
ewa How modular renewables can reduce the costs of relying on carbon capture By www.chathamhouse.org Published On :: Thu, 10 Oct 2024 09:57:06 +0000 How modular renewables can reduce the costs of relying on carbon capture Expert comment LToremark 10 October 2024 COP29 must raise countries’ ambitions to deploy vastly more low-cost modular renewable technologies to help meet the tripling of renewables target set at COP28 and reduce our reliance on expensive carbon capture systems. The most important international climate conference is around the corner. COP29 in Baku, Azerbaijan will be especially important because next year countries will submit their five-yearly national climate plans – or Nationally Determined Contributions (NDCs) – as set out under the Paris Agreement. Related content COP28: What was achieved, and what needs to happen now At COP28 in Dubai last year, the final text was heralded as a last-minute success as – somewhat surprisingly – it was the first ever COP to commit to ‘transition away from fossil fuels in energy systems in a just, orderly and equitable manner’. To support this, over 200 countries also committed to triple renewable capacity by 2030.Under current NDCs, even if all countries achieve their most ambitious decarbonization plans, the world would still fall 30 per cent short of tripling renewable capacity by 2030. At COP29 in November, hosted by a petrostate, additional agreement is needed to operationalize the removal of fossil fuels from the global energy system and set the ambition for those crucial NDCs in 2025. Failing to do so means the opportunity to triple renewables by 2030 will slip away. But the actions of oil producing nations, international oil companies, their associated supply chains and networks of lobbyists have in recent years done their best to disrupt and slow down the energy transition and water down key negotiations during COPs and elsewhere. During the final days of COP28, the Organization of the Petroleum Exporting Countries (OPEC) sent private letters to its 13 members – including COP28 host the United Arab Emirates (UAE) – urging them to ‘proactively reject any text or formula that targets energy, i.e. fossil fuels, rather than emissions’. OPEC members own 80 per cent of global oil reserves.Due to the startling decline in the cost of renewables and electric vehicles, fossil fuel producers are increasingly concerned. To fight back they are turning to carbon capture and storage (CCS) technologies and carbon removal options, which would enable the continued burning of fossil fuels – and protect their assets and business models. Related content To phase out or phase down? Why the debate on fossil fuels misses key point A key battle ground for oil and gas producers is the difference between abated and unabated fossil fuels.Abatement is the process of capturing CO2 as fossil fuels are burnt to prevent a proportion of those CO2 emissions from entering the atmosphere, either by using that CO2 in products or storing it in geological formations deep underground in near perpetuity, commonly referred to as CCS.After COP28 there was optimism that the final agreement was significant and covered all fossil fuels without ambiguity around whether they are unabated or abated. But the definition of unabated has not actually been agreed within the COP process. During the 2021 COP26 summit, the Glasgow Climate Pact mentioned unabated in reference to coal. Could a gas power station capturing 51 per cent of the emitted CO2 be considered abated?And what about the so-called downstream emissions? Downstream emissions from cars, planes, tanker ships and diesel generators etc make up 50–80 per cent of the total emissions from oil – and there are no plans to attach mini-CCS systems to cars.CCS and engineered carbon removals are also likely to be expensive. Analysis by the Oxford Smith School of Enterprise and the Environment has shown that high CCS pathways to net zero emissions in 2050 would cost at least $30 trillion more than a low CCS pathway with more renewables – roughly $1 trillion more per year. The rapid cost reductions of solar, wind and batteries are due to their modular nature. The costs of CCS have also remained the same for the past 40 years, while the costs of renewables like solar, wind and lithium-ion batteries have dropped radically. Solar costs have declined by 90 per cent in the last decade. The rapid cost reductions of solar, wind and batteries are due to their modular nature. Around 70 billion solar cells will be manufactured this year, the majority in China. It is the repetitive modular manufacturing process that has led to rapid efficiency improvements and cost reductions. Each Tesla has around 7,000 lithium-ion battery cells, and the price of these modular batteries fell 14 per cent between 2022 and 2023 alone. The modular criteria can help define the technology winners of the future, technologies we should selectively support and accelerate over the coming years. While huge industrial power stations, oil rigs and refineries have their benefits, they are not modular in the same way. Their economy of scale is in the large size of each asset. CCS is bolted on to fossil fuel infrastructure but there are less than 50,000 fossil fuel producing assets globally. By contrast, there were 1.5 billion solar panels produced in 2022. The cost of deploying CCS is therefore unlikely to benefit from the rapid cost reductions of modular renewables. Nuclear even less so. There are 440 nuclear power stations in operation today, they take many years to build and remain hugely expensive. Full Article
ewa Jon Stewart Blows Up Key Theory on Why Dems Got ‘Shellacked’ By www.yahoo.com Published On :: 2024-11-12T05:05:30Z Full Article
ewa Sophos Firewall hardening best practices By news.sophos.com Published On :: Fri, 25 Oct 2024 12:41:06 +0000 Make the most of your Sophos Firewall. Full Article Products & Services Firewall network Pacific Rim Defense
ewa Renewable Power Unlock New Efficiencies for High-Performance Computing By www.hpcwire.com Published On :: Thu, 14 Mar 2024 13:00:44 +0000 The surge in digital transformation across industries has led to exponential data growth, driving a heightened demand for computing power. However, this growth also intensifies concerns about energy consumption and […] The post Renewable Power Unlock New Efficiencies for High-Performance Computing appeared first on HPCwire. Full Article
ewa Newark Principals Speak Out, Get Suspended by Christie's Superintendent By blogs.edweek.org Published On :: Sat, 18 Jan 2014 00:00:00 +0000 Now Newark, New Jersey, is exploding, thanks to the attempts at intimidation by Governor Christie's hand-picked superintendent of schools, Cami Anderson. Full Article New_Jersey
ewa Newark Group Presses on With Schools Boycott By blogs.edweek.org Published On :: Mon, 08 Sep 2014 00:00:00 +0000 Parents Unified for Local School Education New Jersey is calling for community-driven schools and opposes the One Newark reorganization plan. Full Article New_Jersey
ewa Florida State Education Commissioner Pam Stewart Resigns By blogs.edweek.org Published On :: Wed, 05 Dec 2018 00:00:00 +0000 The state's board of education had renewed Commissioner Pam Stewart's contract for a year before the midterm election but after the election of a new Republican governor, she said she'd leave in January instead. Full Article Florida
ewa Striatal Serotonin Release Signals Reward Value By www.jneurosci.org Published On :: 2024-10-09 Mitchell G. SpringOct 9, 2024; 44:e0602242024-e0602242024BehavioralSystemsCognitive Full Article
ewa A Virtual In Vivo Dissection and Analysis of Socioaffective Symptoms Related to Cerebellum-Midbrain Reward Circuitry in Humans By www.jneurosci.org Published On :: 2024-10-09T09:30:20-07:00 Emerging research in nonhuman animals implicates cerebellar projections to the ventral tegmental area (VTA) in appetitive behaviors, but these circuits have not been characterized in humans. Here, we mapped cerebello-VTA white matter connectivity in a cohort of men and women using probabilistic tractography on diffusion imaging data from the Human Connectome Project. We uncovered the topographical organization of these connections by separately tracking from parcels of cerebellar lobule VI, crus I/II, vermis, paravermis, and cerebrocerebellum. Results revealed that connections between the cerebellum and VTA predominantly originate in the right cerebellar hemisphere, interposed nucleus, and paravermal cortex and terminate mostly ipsilaterally. Paravermal crus I sends the most connections to the VTA compared with other lobules. We discovered a mediolateral gradient of connectivity, such that the medial cerebellum has the highest connectivity with the VTA. Individual differences in microstructure were associated with measures of negative affect and social functioning. By splitting the tracts into quarters, we found that the socioaffective effects were driven by the third quarter of the tract, corresponding to the point at which the fibers leave the deep nuclei. Taken together, we produced detailed maps of cerebello-VTA structural connectivity for the first time in humans and established their relevance for trait differences in socioaffective regulation. Full Article
ewa Striatal Serotonin Release Signals Reward Value By www.jneurosci.org Published On :: 2024-10-09T09:30:20-07:00 Serotonin modulates diverse phenotypes and functions including depressive, aggressive, impulsive, and feeding behaviors, all of which have reward-related components. To date, research has focused on understanding these effects by measuring and manipulating dorsal raphe serotonin neurons and using single-receptor approaches. These studies have led to a better understanding of the heterogeneity of serotonin actions on behavior; however, they leave open many questions about the timing and location of serotonin's actions modulating the neural circuits that drive these behaviors. Recent advances in genetically encoded fluorescent biosensors, including the GPCR activation-based sensor for serotonin (GRAB-5-HT), enable the measurement of serotonin release in mice on a timescale compatible with a single rewarding event without corelease confounds. Given substantial evidence from slice electrophysiology experiments showing that serotonin influences neural activity of the striatal circuitry, and the known role of the dorsal medial striatal (DMS) in reward-directed behavior, we focused on understanding the parameters and timing that govern serotonin release in the DMS in the context of reward consumption, external reward value, internal state, and cued reward. Overall, we found that serotonin release is associated with each of these and encodes reward anticipation, value, approach, and consumption in the DMS. Full Article
ewa FAO launches new South-South Cooperation Gateway: an information sharing platform By www.fao.org Published On :: Wed, 10 Jun 2015 00:00:00 GMT South-South Cooperation is the mutual sharing and exchange of development solutions - knowledge, experiences and good practices, policies, technology and resources - between and among countries in the global [...] Full Article
ewa FAO and India's SEWA join efforts to empower rural women and youth By www.fao.org Published On :: Tue, 13 Sep 2016 00:00:00 GMT India's Self Employed Women's Association (SEWA) and FAO are strengthening their collaboration to boost rural development and reduce poverty in Asia and Africa via local initiatives focused on empowering rural [...] Full Article
ewa Sharks: Stewards of the Reef By www.smithsonianmag.com Published On :: Mon, 07 Oct 2024 00:00:00 -0000 In this trailer, experts discuss the importance of sharks to the health of coral reefs. Marine ecologist Enric Sala of Scripps Institution of Oceanography talks about the role of sharks as top predators in ocean ecosystems. Peter Knight, executive director of WildAid, and Sonja Fordham of the Ocean Conservancy detail the decline of shark populations worldwide as a result of fishing pressure Full Article
ewa Anus-Breathing Animals and Pigeon-Guided Missiles: Ig Nobel Prizes Reward Unusual but Valuable Science By www.smithsonianmag.com Published On :: Wed, 18 Sep 2024 13:30:00 +0000 The annual award ceremony featured costumes, songs and paper airplanes as scientists recognized comedic research across ten disciplines Full Article
ewa 'It hurts': Saskatchewan Roughriders react to West Final loss in Winnipeg By www.cbc.ca Published On :: Sun, 10 Nov 2024 01:37:20 EST Head coach Corey Mace, quarterback Trevor Harris and linebacker Jameer Thurman talk about coming up short in the CFL West Final. The Roughriders lost the the Winnipeg Blue Bombers 38-22 sending the Bombers to their fifth straight Grey Cup. Full Article
ewa Saskatchewan Huskies head coach Scott Flory after losing a defensive battle to provincial rival By www.cbc.ca Published On :: Sun, 10 Nov 2024 01:06:42 EST It was only the second time the Saskatchewan Huskies and the Regina Rams have met in the Hardy Cup championship game. This time it was the Rams coming out on top 19-14. Huskies head coach Scott Flory says there were too many turnovers and too many plays left on the field after a hard fought game. Full Article
ewa NCC explores adapting standards around opening Rideau Canal Skateway By www.cbc.ca Published On :: Mon, 11 Nov 2024 15:16:50 EST The National Capital Commission says it opened the Rideau Canal Skateway below its usual stands for ice thickness a few times last season — and plans to do the same this year. Full Article News/Canada/Ottawa
ewa Urban Renewal Commission - Oct 02, 2019 By oregon-city.granicus.com Published On :: Wed, 02 Oct 2019 06:15:00 -0800 The agenda for Urban Renewal Commission dated Wednesday, 02 October 2019 has been archived. Access it here: https://oregon-city.granicus.com/MediaPlayer.php?view_id=4&clip_id=2321 Download File Full Article
ewa Urban Renewal Commission - Nov 25, 2019 By oregon-city.granicus.com Published On :: Mon, 25 Nov 2019 06:30:00 -0800 The agenda for Urban Renewal Commission dated Monday, 25 November 2019 has been archived. Access it here: https://oregon-city.granicus.com/MediaPlayer.php?view_id=4&clip_id=2348 Download File Full Article