emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Rendering regression in Gnus with gnus-treat-from-gravatar


From: Robert Pluim
Subject: Re: Rendering regression in Gnus with gnus-treat-from-gravatar
Date: Tue, 14 Apr 2020 15:14:11 +0200

>>>>> On Sat, 11 Apr 2020 18:53:38 +0200, Robert Pluim <address@hidden> said:

    Robert> OK, so itʼs the DNS. The libravatar method does a bunch of DNS
    Robert> queries, and those can be slow, and they're done for every article.

    Robert> I guess we need to see if we can make those DNS lookups 
asynchronous.

The following does at least make rendering of the article complete
straight away, although you might end up waiting a little longer for
the gravatar to actually appear. Iʼm assuming your emacs has thread
support.

(the inhibit-redisplay is there because otherwise this crashes on
macOS, where apparently you can only call certain OS window system
functions from the main thread).

diff --git a/lisp/image/gravatar.el b/lisp/image/gravatar.el
index ff59a72ac8..b9ad16bb28 100644
--- a/lisp/image/gravatar.el
+++ b/lisp/image/gravatar.el
@@ -149,7 +149,7 @@ gravatar--service-libravatar
           (dolist (record '(("_avatars-sec" . "https")
                             ("_avatars" . "http")))
             (let* ((query (concat (car record) "._tcp." domain))
-                   (result (dns-query query 'SRV)))
+                   (result (dns-query-cached query 'SRV)))
               (when result
                 (throw 'found (format "%s://%s/avatar"
                                       (cdr record)
@@ -189,17 +189,41 @@ gravatar-get-data
          (search-forward "\n\n" nil t)
          (buffer-substring (point) (point-max)))))
 
-;;;###autoload
-(defun gravatar-retrieve (mail-address callback &optional cbargs)
+(defvar gravatar-retrieve-params nil)
+(defvar gravatar-thread nil)
+(defvar gravatar-exit-thread nil)
+(defvar gravatar-mutex nil)
+(defvar gravatar-cond-var nil)
+
+(defun gravatar-retrieve-thread ()
   "Asynchronously retrieve a gravatar for MAIL-ADDRESS.
 When finished, call CALLBACK as (apply CALLBACK GRAVATAR CBARGS),
 where GRAVATAR is either an image descriptor, or the symbol
 `error' if the retrieval failed."
-  (let ((url (gravatar-build-url mail-address)))
-    (if (url-cache-expired url gravatar-cache-ttl)
-        (url-retrieve url #'gravatar-retrieved (list callback cbargs) t)
-      (with-current-buffer (url-fetch-from-cache url)
-        (gravatar-retrieved () callback cbargs)))))
+  (while (not gravatar-exit-thread)
+    (with-mutex gravatar-mutex
+      (condition-wait gravatar-cond-var)
+      (let ((inhibit-redisplay t)
+            (mail-address (nth 0 gravatar-retrieve-params))
+            (callback (nth 1 gravatar-retrieve-params))
+            (cbargs (nth 2 gravatar-retrieve-params)))
+        (let ((url (gravatar-build-url mail-address)))
+          (if (url-cache-expired url gravatar-cache-ttl)
+              (url-retrieve url #'gravatar-retrieved (list callback cbargs) t)
+            (with-current-buffer (url-fetch-from-cache url)
+              (gravatar-retrieved () callback cbargs)))))
+      (thread-yield))))
+
+;;;###autoload
+(defun gravatar-retrieve (mail-address callback &optional cbargs)
+  (unless gravatar-thread
+    (setq gravatar-mutex (make-mutex)
+          gravatar-cond-var (make-condition-variable gravatar-mutex)
+          gravatar-thread (make-thread #'gravatar-retrieve-thread)))
+  (with-mutex gravatar-mutex
+    (setq gravatar-retrieve-params
+          (list mail-address callback cbargs))
+    (condition-notify gravatar-cond-var)))
 
 ;;;###autoload
 (defun gravatar-retrieve-synchronously (mail-address)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]