ed Brabus 1000 All Gray Sedan By uncrate.com Published On :: Tue, 12 Nov 2024 17:00:00 -0500 Full Article Modern Cars
ed Manscaped The Chairman Pro Electric Shaver By uncrate.com Published On :: Tue, 12 Nov 2024 17:51:35 -0500 Full Article Grooming
ed Learned something new By maryannemohanraj.com Published On :: Mon, 11 Nov 2024 13:59:00 +0000 Learned something new today— resin fidget spinner. ???? Full Article Uncategorized
ed Signed and personalized at request! By maryannemohanraj.com Published On :: Mon, 11 Nov 2024 18:12:00 +0000 We just made the decision to ship the remaining copies of Feast to us. There are about 800 left, out of the original 2000 copy print run. Which is a lot of copies, but given that we were originally scheduled to launch March 2020, and had to cancel an entire summer’s worth of scheduled bookstore […] Full Article Serendib Kitchen
ed Finished Rock pools By iron-mitten.blogspot.com Published On :: Fri, 08 Nov 2024 19:23:00 +0000 The last stage was to gloss varnish the water in the pools. This really brought them to life and gave them a sparkle.The kelp and some of the green rocks were also given a lick with the gloss brush too. Not too much, just enough to give them a damp look.The bottom of the pools were painted with loads of people's of different colours. This was then given a green wash, then a brown one to add depth to the pool. Full Article Celtic Mythology.
ed 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
ed Popular destinations in Sweden By satwcomic.com Published On :: Popular destinations in Sweden View Comic! Full Article
ed Why Virat Kohli, Jasprit Bumrah were missing from Perth nets; India ramp up privacy amid Manchester United-like security - Hindustan Times By news.google.com Published On :: Wed, 13 Nov 2024 04:53:31 GMT Why Virat Kohli, Jasprit Bumrah were missing from Perth nets; India ramp up privacy amid Manchester United-like security Hindustan TimesVirat Kohli in focus: Intense net session begins for upcoming Test series against Australia The Times of IndiaVirat Kohli in Australia for BGT: A timeline India TodayBlack veil of secrecy: India begin training in privacy in Perth ESPNcricinfoIndia to play intra-squad warm-up match at WACA on Friday ahead of Australia Tests but BCCI denies public viewing Hindustan Times Full Article
ed Melania Trump's 'I am the most bullied person' video viral as she 'rejects' Jill Biden's tea invite - The Times of India By news.google.com Published On :: Tue, 12 Nov 2024 19:44:00 GMT Melania Trump's 'I am the most bullied person' video viral as she 'rejects' Jill Biden's tea invite The Times of IndiaMelania Trump declines invite to meet Jill Biden over Mar-a-Lago raids when FBI ’snooped through her wardrobe’ MintJimmy Kimmel again mocks Donald Trump for Melania's ‘interesting’ decision to… Hindustan TimesBiden Invites Trump To White House, But Why Is Melania Refusing To Go? News18Melania Trump To Skip White House Meeting With Jill Biden: Report NDTV Full Article
ed Eight injured in explosion at oil refinery in UP's Mathura - ANI News By news.google.com Published On :: Tue, 12 Nov 2024 23:00:00 GMT Eight injured in explosion at oil refinery in UP's Mathura ANI News8 injured, three critical in major explosion at Indian Oil plant in UP's Mathura India TodayEight injured in fire at IndianOil’s Mathura refinery BusinessLineMathura refinery blast: Indian Oil refinery explosion injures 12 people The Financial ExpressAt least 8 injured in explosion at Mathura refinery The Indian Express Full Article
ed 3 Children, 3 Women Missing After 10 Suspected Kuki Militants Killed In Encounter In Manipur's Jiribam - NDTV By news.google.com Published On :: Tue, 12 Nov 2024 11:11:01 GMT 3 Children, 3 Women Missing After 10 Suspected Kuki Militants Killed In Encounter In Manipur's Jiribam NDTVManipur on boil: 2 more bodies found, 6 missing The Times of IndiaAdditional paramilitary forces rushed to Manipur amid spike in ethnic violence Hindustan TimesLetters to The Editor — November 13, 2024 The Hindu2 men found dead, 6 of family missing day after militants killed in Manipur India Today Full Article
ed Chennai doctor stabbed by assilants posing as patients - The Times of India By news.google.com Published On :: Wed, 13 Nov 2024 06:21:00 GMT Chennai doctor stabbed by assilants posing as patients The Times of IndiaChennai Doctor Stabbed 7 Times By Son Of Woman Who Had Cancer NDTVDoctor stabbed by patient’s attendant at Kalaignar Centenary Super Speciality Hospital in Chennai The HinduPatient's son stabs doctor 7 times in Chennai hospital, arrested India TodayDoctor stabbed multiple times in Tamil Nadu government hospital by patient’s relative Deccan Herald Full Article
ed congratulations borned By www.marriedtothesea.com Published On :: Thu, 17 Nov 2022 04:00:00 EST Today on Married To The Sea: congratulations bornedThis 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
ed mass media cents By www.marriedtothesea.com Published On :: Thu, 24 Nov 2022 04:00:00 EST Today on Married To The Sea: mass media centsThis 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
ed ouija message received By www.marriedtothesea.com Published On :: Sun, 01 Jan 2023 04:00:00 EST Today on Married To The Sea: ouija message receivedThis 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
ed borned in the hellscape By www.marriedtothesea.com Published On :: Sun, 15 Jan 2023 04:00:00 EST Today on Married To The Sea: borned in the hellscapeThis 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
ed im allowed to speak By www.marriedtothesea.com Published On :: Sun, 05 Feb 2023 04:00:00 EST Today on Married To The Sea: im allowed to speakThis 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
ed what happened to my sleepy pants By www.marriedtothesea.com Published On :: Wed, 29 Mar 2023 04:00:00 EDT Today on Married To The Sea: what happened to my sleepy pantsThis 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
ed wheed smoke By www.marriedtothesea.com Published On :: Wed, 25 Oct 2023 04:00:00 EDT Today on Married To The Sea: wheed smokeThis 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
ed watch you sled By www.marriedtothesea.com Published On :: Wed, 24 Jan 2024 04:00:00 EST Today on Married To The Sea: watch you sledThis 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
ed tried to deliver By www.marriedtothesea.com Published On :: Wed, 06 Mar 2024 04:00:00 EST Today on Married To The Sea: tried to deliverThis 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
ed i pledge allegiance By www.marriedtothesea.com Published On :: Wed, 13 Mar 2024 04:00:00 EDT Today on Married To The Sea: i pledge allegianceThis 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
ed were supposed to use the earth By www.marriedtothesea.com Published On :: Wed, 03 Apr 2024 04:00:00 EDT Today on Married To The Sea: were supposed to use the earthThis 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
ed ouch damned By www.marriedtothesea.com Published On :: Wed, 14 Aug 2024 04:00:00 EDT Today on Married To The Sea: ouch damnedThis 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
ed Webinar: nieuw HPV-screeningsbeleid en -vaccinatie - 19 november 2024 - Medi-Sfeer By news.google.com Published On :: Wed, 13 Nov 2024 08:08:57 GMT Webinar: nieuw HPV-screeningsbeleid en -vaccinatie - 19 november 2024 Medi-Sfeer Full Article
ed Peter Vandenbempt neemt praktijk op de korrel die steeds meer aan populariteit wint: "Gewoon geel geven, en een paar keer na elkaar" - Voetbalkrant.com By news.google.com Published On :: Tue, 12 Nov 2024 16:40:00 GMT Peter Vandenbempt neemt praktijk op de korrel die steeds meer aan populariteit wint: "Gewoon geel geven, en een paar keer na elkaar" Voetbalkrant.com"Je lacht gewoon iedereen uit": Peter Vandenbempt hekelt "blessures bij doelmannen" en komt met oplossing sporza.beDelanghe onder vuur na acteren tegen RSC Anderlecht: “Lacht iedereen uit” VoetbalPrimeur.beAlle middelen zijn goed: de 'gouden' truc die Cercle Brugge toepaste tegen RSC Anderlecht krijgt (voorlopig) geen staartje Voetbalkrant.comLoopje met de sportiviteit, Delanghe faket blessure tegen Anderlecht VoetbalPrimeur.be Full Article
ed Een Franse "alleskunner" boezemt iedereen angst in op Gentse Zesdaagse: "Zelfs als renner kijk je naar hem op" - sporza.be By news.google.com Published On :: Wed, 13 Nov 2024 07:12:00 GMT Een Franse "alleskunner" boezemt iedereen angst in op Gentse Zesdaagse: "Zelfs als renner kijk je naar hem op" sporza.beDe Vylder en Ghys sluiten als leiders de eerste dag van Gentse Zesdaagse af sporza.beMinder volks, minder spektakel, maar sneller dan ooit: hoe de Zesdaagse van Gent echt specialistenwerk is geworden De StandaardLindsay De Vylder, wereldkampioen op ontdekkingstocht: “Ik ga dringend beter moeten leren onderhandelen” Het Laatste NieuwsKoen Crucke geeft al zingend het startschot van 6 dagen volksfeest en wielerspektakel in ’t Kuipke Het Nieuwsblad Full Article
ed “Absurde toestanden” bij verplichting zonnepanelen voor grote verbruikers: “Zelfs bedrijf dat niets meer produceert, moet er leggen” - Het Laatste Nieuws By news.google.com Published On :: Wed, 13 Nov 2024 05:00:00 GMT “Absurde toestanden” bij verplichting zonnepanelen voor grote verbruikers: “Zelfs bedrijf dat niets meer produceert, moet er leggen” Het Laatste Nieuws Full Article
ed Overleden vrouw aangetroffen op oprit van woning in Zwijndrecht, parket opent onderzoek - VRT.be By news.google.com Published On :: Wed, 13 Nov 2024 08:02:08 GMT Overleden vrouw aangetroffen op oprit van woning in Zwijndrecht, parket opent onderzoek VRT.beVrouw vermoord op oprit van woning in Zwijndrecht bij Antwerpen: schedel van slachtoffer werd ingeslagen Het Laatste NieuwsVrouw dood aangetroffen op oprit van een woning in Zwijndrecht, parket start onderzoek naar gewelddadig overlijden Het NieuwsbladVermoorde vrouw aangetroffen voor woning in Zwijndrecht: parket start onderzoek Gazet van AntwerpenLevenloos lichaam van vrouw gevonden op oprit van woning in Zwijndrecht: schedel van slachtoffer werd ingeslagen Het Laatste Nieuws Full Article
ed Hoe een ‘hedendaagse pogrom’ wantrouwen zaait - De Standaard By news.google.com Published On :: Wed, 13 Nov 2024 02:00:00 GMT Hoe een ‘hedendaagse pogrom’ wantrouwen zaait De StandaardDe rellen in Amsterdam: voor de één een “Arabische pogrom”, voor de ander “zionistische propaganda” De StandaardOver antisemitisme en de haat jegens de andere mens TrouwOpinie: Het gaat te weinig over het antisemitisme van de PVV en haar leider zelf de VolkskrantAls ik als neutrale Nederlander de straat op zou gaan, zou ik zwaaien met een Palestijnse vlag, keppeltje op mijn kop AD Full Article
ed Untitled By cheezburger.com Published On :: Wed, 31 Mar 2010 08:00:36 -0700 Full Article car horse hummer mod not street legal
ed Convert Old Junk Bikes Into Race-Ready Fixed Gear Bikes in No Time! By cheezburger.com Published On :: Thu, 04 Oct 2012 08:00:00 -0700 EIGHTINCH shows us how to fix up old bikes using a fairly basic conversion kit. You'll need: Amelia wheels with tires & tubes 16t cog lockring Courier cranks A bottom bracket A KMC chain More videos for both seasoned and amateur bike enthusiasts here! Full Article bicycle bikes How To Video
ed Meet BRAD (Berkeley's Ridiculously Automated Dorm Room) By cheezburger.com Published On :: Fri, 04 May 2012 12:00:00 -0700 Party the absolute hardest you can imaginably party! Full Article dorm room Video
ed Iz Reddy Fur Sno By cheezburger.com Published On :: Thu, 06 Dec 2012 10:00:00 -0800 Yes, aiffinkso! Full Article small car snow plow g rated there I fixed it
ed Untitled By cheezburger.com Published On :: Wed, 14 Jul 2010 08:00:12 -0700 Full Article flip flops Kludge Music poles Professional At Work technology
ed Untitled By cheezburger.com Published On :: Mon, 15 Nov 2010 10:00:03 -0800 Full Article computer parts cooling fan overkill
ed You Seem To Have Picked Up Another Pickup There, Buddy By cheezburger.com Published On :: Tue, 06 Mar 2012 09:00:00 -0800 One is never enough. Full Article pickup truck truck bed
ed Untitled By cheezburger.com Published On :: Mon, 29 Nov 2010 14:00:00 -0800 Full Article drill ice cream kitchen Video
ed Armored Cruck? By cheezburger.com Published On :: Tue, 16 Oct 2012 10:00:00 -0700 I call it "Mad Max Chic." Full Article sedan
ed Untitled By cheezburger.com Published On :: Sat, 20 Mar 2010 10:00:06 -0700 Full Article car jack futon not intended use propped up
ed Untitled By cheezburger.com Published On :: Sat, 24 Jul 2010 06:00:39 -0700 Full Article beach boat chair Kludge paddle
ed TIFI WIN: The 10-Speed Lamp By cheezburger.com Published On :: Mon, 27 Aug 2012 09:00:00 -0700 Here we see a nice little floor lamp made from old bicycle parts. Be sure to lock it up or someone might steal it! Check out more theft-worthy WINs here! Full Article bicycle bike handlebars lamp tifi win
ed Lint Trap Fixed, Fire Averted By cheezburger.com Published On :: Fri, 09 Aug 2013 05:00:00 -0700 Full Article funny there I fixed it
ed Untitled By cheezburger.com Published On :: Tue, 12 Jan 2010 06:00:49 -0800 Full Article cardboard mp3 player recycling-is-good-right use what you have
ed They Tried Digging Up, Decided Building a Ladder Was Better By cheezburger.com Published On :: Thu, 15 Dec 2011 10:00:00 -0800 Full Article DIY ladder Professional At Work
ed USC football placed on 1 year of probation, fined for coaching staff violations By www.foxsports.com Published On :: Tue, 12 Nov 2024 16:38:10 -0500 Southern California’s football program has been fined $50,000 and placed on probation for one year by the NCAA because of multiple violations of coaching staff rules over two seasons Full Article college-football
ed Tropicana Field can be fixed by 2026, but Rays must play elsewhere in 2025 By www.foxsports.com Published On :: Tue, 12 Nov 2024 16:42:09 -0500 A detailed assessment of the hurricane damage to Tropicana Field concludes that the home of the Rays is structurally sound and can be repaired in time for the 2026 season, but not by 2025 Opening Day. Full Article mlb