]> git.eshelyaron.com Git - emacs.git/commitdiff
run-in-thread accepts a new optional argument: nolock.
authorGiuseppe Scrivano <gscrivano@gnu.org>
Fri, 18 Sep 2009 20:16:30 +0000 (22:16 +0200)
committerGiuseppe Scrivano <gscrivano@gnu.org>
Fri, 18 Sep 2009 20:16:30 +0000 (22:16 +0200)
When it is no-nil the thread does not try to get a lock on the current
buffer before work on it.

With this change, the following example works quite smoothly; while
loading imap folders, gnus yields to another thread:

(load-library "gnus")

;; Redefine to use yield
(defun imap-send-command-wait (command &optional buffer)
 (imap-wait-for-tag (prog1 (imap-send-command command buffer) (yield)) buffer))

(progn
 (run-in-thread '(gnus) t)
 (dotimes (i 20)
   ;; yield is called automatically during a buffer-switch
   (message (format "I got here %i" i))))

src/buffer.c
src/thread.c
src/thread.h

index 492030fc918a2757ea65f8b1ff468025fd522480..60c63fecdffa76a9a9d888c85564c4ecc8b8d2b3 100644 (file)
@@ -1880,6 +1880,7 @@ acquire_buffer (char *end, void *nb)
 
       /* If our desired buffer is locked, wait for it.  */
       while (other_threads_p ()
+             && !current_thread->nolock
             && !EQ (new_buffer->owner, Qnil)
             /* We set the owner to Qt to mean it is being killed.  */
             && !EQ (new_buffer->owner, Qt))
@@ -1930,7 +1931,10 @@ set_buffer_internal_1 (b)
   flush_stack_call_func (acquire_buffer, b);
   /* FIXME: if buffer is killed */
   b->prev_owner = b->owner;
-  b->owner = get_current_thread ();
+  if (current_thread->nolock)
+    b->owner = Qnil;
+  else
+    b->owner = get_current_thread ();
   current_buffer = b;
   last_known_column_point = -1;   /* invalidate indentation cache */
 
index 98aa3ff4fdd842654b7acc495cfcef1c8c48bc97..332b55c5ae9fc3db18515dd30539a3eed6a3f059 100644 (file)
@@ -208,11 +208,13 @@ run_thread (void *state)
   return NULL;
 }
 
-DEFUN ("run-in-thread", Frun_in_thread, Srun_in_thread, 1, 1, 0,
+DEFUN ("run-in-thread", Frun_in_thread, Srun_in_thread, 1, 2, 0,
        doc: /* Start a new thread and run FUNCTION in it.
-When the function exits, the thread dies.  */)
-     (function)
+When the function exits, the thread dies.  When NOLOCK is no-nil the thread
+does not try to get a lock on the current buffer.  */)
+     (function, nolock)
      Lisp_Object function;
+     Lisp_Object nolock;
 {
   char stack_pos;
   pthread_t thr;
@@ -230,6 +232,7 @@ When the function exits, the thread dies.  */)
                                                      m_gcprolist));
 
   new_thread->func = function;
+  new_thread->nolock = !EQ (nolock, Qnil);
   new_thread->initial_specpdl = Qnil;
   new_thread->m_current_buffer = current_thread->m_current_buffer;
   new_thread->stack_bottom = &stack_pos;
@@ -295,7 +298,7 @@ user_thread_p (void)
 }
 
 DEFUN ("inhibit-yield", Finhibit_yield, Sinhibit_yield, 1, 1, 0,
-       doc: /* Inhibit the yield function. */)
+       doc: /* Inhibit the yield function.  */)
      (val)
      Lisp_Object val;
 {
@@ -320,6 +323,7 @@ init_threads (void)
   pthread_mutex_init (&global_lock, NULL);
   pthread_mutex_lock (&global_lock);
   primary_thread.pthread_id = pthread_self ();
+  primary_thread.nolock = 0;
 }
 
 void
index fe3e465d1cbdd34d5f0fbbf2aec22fd4ae193a5e..982f1b1775aac27f20dcaa02046f19154d5e5adc 100644 (file)
@@ -71,6 +71,9 @@ struct thread_state
   struct thread_state *next_thread;
 
   pthread_t pthread_id;
+
+  /* If nonzero the thread access a buffer without lock it.  */
+  int nolock;
 };
 
 extern __thread struct thread_state *current_thread;