From: Giuseppe Scrivano Date: Fri, 18 Sep 2009 20:16:30 +0000 (+0200) Subject: run-in-thread accepts a new optional argument: nolock. X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=4a5034451ea883ddffaca58b1d741cfe8170decb;p=emacs.git run-in-thread accepts a new optional argument: nolock. 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)))) --- diff --git a/src/buffer.c b/src/buffer.c index 492030fc918..60c63fecdff 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -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 */ diff --git a/src/thread.c b/src/thread.c index 98aa3ff4fdd..332b55c5ae9 100644 --- a/src/thread.c +++ b/src/thread.c @@ -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 diff --git a/src/thread.h b/src/thread.h index fe3e465d1cb..982f1b1775a 100644 --- a/src/thread.h +++ b/src/thread.h @@ -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;