unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* advice needed for multi-threading patch
@ 2009-08-26  4:38 Tom Tromey
  2009-08-26  7:06 ` Ken Raeburn
                   ` (2 more replies)
  0 siblings, 3 replies; 54+ messages in thread
From: Tom Tromey @ 2009-08-26  4:38 UTC (permalink / raw)
  To: Emacs development discussions

I was inspired by Giuseppe Scrivano's work from last year:

http://lists.gnu.org/archive/html/emacs-devel/2008-11/msg01067.html

... so I started working on my own patch to implement multi-threading in
Emacs.  I've tried to follow Stefan's advice as given in that thread.
In particular I've (initially) implemented cooperative multi-threading.

Some background for my particular question:

My implementation of dynamic binding uses a structure like so:

    struct Lisp_ThreadLocal
      {
        enum Lisp_Misc_Type type : 16;	/* = Lisp_Misc_ThreadLocal */
        unsigned gcmarkbit : 1;
        int spacer : 15;
        Lisp_Object global;
        Lisp_Object thread_alist;
      };

... the idea being that a let-bound variable will be on 'thread_alist'
(keyed by the thread), and other threads will see the value in 'global'.
These objects are found in symbol value slots.

I managed to handle the V* global variables by writing some elisp that
changed every declaration of a variable mentioned in a DEFVAR_LISP from
Vfoo to impl_Vfoo and also emitted a new header with a lot of:

    #define Vfoo *find_variable_location (&impl_Vfoo)

This was pretty simple and non-intrusive, in the sense that it is
totally automated, so I can easily reapply it as Emacs changes.

... which brings me to my problem.  I'd also like to apply a similar
treatment to buffer-local variables.  However, those do not have
convenient accessor macros, and before starting the laborious task of
wrapping all buffer field accesses, I thought I'd ask for advice.  Is
this a sane way to proceed?  Should I do something different?  Could I
get such a patch in before the rest of this work, just to make my local
divergence smaller?

I'll also note that the above approach does not work for DEFVAR_INT.  I
have a plan for those but I fear it is somewhat expensive.  If you have
an idea...

Tom




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-26  4:38 advice needed for multi-threading patch Tom Tromey
@ 2009-08-26  7:06 ` Ken Raeburn
  2009-08-26 14:52   ` Stefan Monnier
  2009-08-26 16:08   ` Tom Tromey
  2009-08-26 15:02 ` Stefan Monnier
  2009-08-29  0:28 ` Giuseppe Scrivano
  2 siblings, 2 replies; 54+ messages in thread
From: Ken Raeburn @ 2009-08-26  7:06 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Emacs development discussions

On Aug 26, 2009, at 00:38, Tom Tromey wrote:
> In particular I've (initially) implemented cooperative multi- 
> threading.

Interesting!

(BTW, my guile-emacs work is also coming along slowly [1], and Guile  
supports multithreading, though my current variable-binding support  
isn't thread-safe.  OTOH, Daniel Kraft has been working on loading/ 
compiling basic elisp in Guile, with thread-safe dynamic bindings.   
We've got some work to do to make these development projects converge  
though.  I hope you and Daniel and I aren't doing redundant work.)

> I managed to handle the V* global variables by writing some elisp that
> changed every declaration of a variable mentioned in a DEFVAR_LISP  
> [....]

I've written similar elisp code for doing transformations of patterns  
within the Emacs code -- mostly more localized things like "XCONS  
(expr)->car" to "XCAR (expr)", but with support for somewhat complex  
values of "expr" that have to have balanced parens, etc.  I wonder if  
anyone's looking at collecting elisp tools for C refactoring somewhere.

> This was pretty simple and non-intrusive, in the sense that it is
> totally automated, so I can easily reapply it as Emacs changes.

Same here.  It can *look* very intrusive, even pervasive, when the  
uses are scattered around the source tree, but simple transforms like  
this aren't as scary as they might look to someone who doesn't  
recognize what's happening.

> ... which brings me to my problem.  I'd also like to apply a similar
> treatment to buffer-local variables.  However, those do not have
> convenient accessor macros, and before starting the laborious task of
> wrapping all buffer field accesses, I thought I'd ask for advice.  Is
> this a sane way to proceed?  Should I do something different?  Could I
> get such a patch in before the rest of this work, just to make my  
> local
> divergence smaller?

Should I take this to mean you've already dealt with the buffer-local  
variables created by make-variable-buffer-local, which don't live in  
the buffer structure?  If so, I wonder if you can make use of those  
changes, by replacing XBUFFER(b)->thing with SYMBOL_VALUE(Qthing)  
where Qthing holds a symbol that's marked as buffer-local; then all  
the changes for the interaction between thread-local and buffer-local  
bindings would be localized in indirect_variable and friends, which  
would then have to deal with both Lisp_Misc_Buffer_Objfwd and  
Lisp_Misc_Buffer_Local_Value.  The Guile work I'm doing would also  
probably benefit from such changes, down the road.

(One change I'm looking at in my Guile work is changing  
indirect_variable to accept and return Lisp_Objects instead of struct  
Lisp_Symbol pointers, for better GC safety.  I doubt such a change  
would significantly affect your work, though it may touch on  
overlapping bits of code.)

Ken

[1] http://lists.gnu.org/archive/html/guile-devel/2009-08/ 
msg00163.html ; I also have a sort of "project page" I wrote up a  
while back, but it's not quite current.




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-26  7:06 ` Ken Raeburn
@ 2009-08-26 14:52   ` Stefan Monnier
  2009-08-26 18:50     ` Ken Raeburn
  2009-08-26 16:08   ` Tom Tromey
  1 sibling, 1 reply; 54+ messages in thread
From: Stefan Monnier @ 2009-08-26 14:52 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: Tom Tromey, Emacs development discussions

> (One change I'm looking at in my Guile work is changing indirect_variable to
> accept and return Lisp_Objects instead of struct  Lisp_Symbol pointers, for
> better GC safety.

I've done the exact opposite change fairly recently, so it would be
going backwards.


        Stefan




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-26  4:38 advice needed for multi-threading patch Tom Tromey
  2009-08-26  7:06 ` Ken Raeburn
@ 2009-08-26 15:02 ` Stefan Monnier
  2009-08-26 15:31   ` Tom Tromey
  2009-08-29  0:28 ` Giuseppe Scrivano
  2 siblings, 1 reply; 54+ messages in thread
From: Stefan Monnier @ 2009-08-26 15:02 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Emacs development discussions

> ... which brings me to my problem.  I'd also like to apply a similar
> treatment to buffer-local variables.  However, those do not have
> convenient accessor macros, and before starting the laborious task of
> wrapping all buffer field accesses, I thought I'd ask for advice.  Is
> this a sane way to proceed?  Should I do something different?  Could I
> get such a patch in before the rest of this work, just to make my local
> divergence smaller?

I'm not sure I understand what you want to do and which problem you want
to solve.  In my mind, in the first iteration of "adding multithreading
to Emacs", no buffer could have two active threads at the same time
(i.e. set-buffer would impose some kind of synchronization).  In such
a context, I think that buffer-local variables (and fields in the buffer
structures) don't need any special treatment, right?

> I'll also note that the above approach does not work for DEFVAR_INT.
> I have a plan for those but I fear it is somewhat expensive.  If you
> have an idea...

You can start with

  #define Vfoo XINT(*find_variable_location (&impl_Vfoo))

and then fix up all the cases where the variable in accessed as an lvalue.
In general, I'm not opposed to introducing macros for such accesses in
the trunk, if it can make such work easier.


        Stefan




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-26 15:02 ` Stefan Monnier
@ 2009-08-26 15:31   ` Tom Tromey
  2009-08-26 19:18     ` Stefan Monnier
  0 siblings, 1 reply; 54+ messages in thread
From: Tom Tromey @ 2009-08-26 15:31 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Emacs development discussions

>>>>> "Stefan" == Stefan Monnier <monnier@iro.umontreal.ca> writes:

Tom> ... which brings me to my problem.  I'd also like to apply a similar
Tom> treatment to buffer-local variables.  However, those do not have
Tom> convenient accessor macros, and before starting the laborious task of
Tom> wrapping all buffer field accesses, I thought I'd ask for advice.  Is
Tom> this a sane way to proceed?  Should I do something different?  Could I
Tom> get such a patch in before the rest of this work, just to make my local
Tom> divergence smaller?

Stefan> I'm not sure I understand what you want to do and which problem you want
Stefan> to solve.

I'm trying to properly implement per-thread let binding in the presence
of buffer-local variables.

I was planning to do this by inserting a thread-based lookup anywhere a
buffer-local was accessed.  However, to do this, I need to insert a
function call anywhere a field corresponding to a DEFVAR_PER_BUFFER is
used.

So, e.g., I would like to change:

    b->major_mode = Qfundamental_mode;

to:

    BUFFER_MAJOR_MODE (b) = Qfundamental_mode;

Doing this transform for all 54 DEFVAR_PER_BUFFER fields is a big pain,
though, so I thought I'd ask about it first.

Stefan> In my mind, in the first iteration of "adding multithreading
Stefan> to Emacs", no buffer could have two active threads at the same time
Stefan> (i.e. set-buffer would impose some kind of synchronization).  In such
Stefan> a context, I think that buffer-local variables (and fields in the buffer
Stefan> structures) don't need any special treatment, right?

I will try that.

Tom> I'll also note that the above approach does not work for DEFVAR_INT.
Tom> I have a plan for those but I fear it is somewhat expensive.  If you
Tom> have an idea...

Stefan> You can start with

Stefan>   #define Vfoo XINT(*find_variable_location (&impl_Vfoo))

Stefan> and then fix up all the cases where the variable in accessed as
Stefan> an lvalue.  In general, I'm not opposed to introducing macros
Stefan> for such accesses in the trunk, if it can make such work easier.

Yeah, this was my plan :-)

Tom




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-26  7:06 ` Ken Raeburn
  2009-08-26 14:52   ` Stefan Monnier
@ 2009-08-26 16:08   ` Tom Tromey
  2009-08-26 18:50     ` Ken Raeburn
  1 sibling, 1 reply; 54+ messages in thread
From: Tom Tromey @ 2009-08-26 16:08 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: Emacs development discussions

>>>>> "Ken" == Ken Raeburn <raeburn@raeburn.org> writes:

Ken> I hope you and Daniel and I aren't doing redundant work.

Unless your changes apply to Emacs I don't think they are really
redundant.  I think the key thing is agree how it ought to work, so we
end up with the same model, but I don't anticipate any problems there.

Ken> I've written similar elisp code for doing transformations of patterns
Ken> within the Emacs code -- mostly more localized things like "XCONS
Ken> (expr)->car" to "XCAR (expr)", but with support for somewhat complex
Ken> values of "expr" that have to have balanced parens, etc.

If you still have these, I would appreciate a copy, so that I don't have
to reinvent them.  Are they in your git repository?

Ken> I wonder if anyone's looking at collecting elisp tools for C
Ken> refactoring somewhere.

There may be some on the CEDET site.  I don't remember seeing any on the
wiki or elsewhere.

Ken> Should I take this to mean you've already dealt with the buffer-local
Ken> variables created by make-variable-buffer-local, which don't live in
Ken> the buffer structure?

Well... nominally.  It is still a buggy mess.

Ken> If so, I wonder if you can make use of those
Ken> changes, by replacing XBUFFER(b)->thing with SYMBOL_VALUE(Qthing)
Ken> where Qthing holds a symbol that's marked as buffer-local; then all
Ken> the changes for the interaction between thread-local and buffer-local
Ken> bindings would be localized in indirect_variable and friends, which
Ken> would then have to deal with both Lisp_Misc_Buffer_Objfwd and
Ken> Lisp_Misc_Buffer_Local_Value.

I will have to think about this.  This would imply removing all those
slots from struct buffer; I suppose my concern would be that the result
would be too inefficient.

I've also been considering a similar thing for the Vfoo globals: remove
them and have the C code always refer to them via SYMBOL_VALUE.

Tom




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-26 14:52   ` Stefan Monnier
@ 2009-08-26 18:50     ` Ken Raeburn
  2009-08-27  3:12       ` Stefan Monnier
  0 siblings, 1 reply; 54+ messages in thread
From: Ken Raeburn @ 2009-08-26 18:50 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Tom Tromey, Emacs development discussions

On Aug 26, 2009, at 10:52, Stefan Monnier wrote:
>> (One change I'm looking at in my Guile work is changing  
>> indirect_variable to
>> accept and return Lisp_Objects instead of struct  Lisp_Symbol  
>> pointers, for
>> better GC safety.
>
> I've done the exact opposite change fairly recently, so it would be
> going backwards.

Oh, right... I meant to ask you at some point if there was a reason  
for that other than streamlining performance a little.

In the guile-emacs code, lots of things can trigger GC that wouldn't  
in Emacs, and it can happen in any thread; with some changes in the  
works on the Guile side, it may not even require a thread to reach a  
special synchronization point.  The Guile model for random application- 
defined object types involves a SCM value that points to an cell or  
double-cell object, holding an integer indicating the type and 1-3  
additional words that can be pointers or SCM values or whatever.  So  
if you've got a big structure like a buffer, one of those words points  
to it.  But if the SCM value isn't seen during GC, the cell doesn't  
get marked and gets released, and the big structure gets freed up, and  
much badness ensues.

Now, with the GC work in progress, it's possible that during  
conservative stack scanning, the pointer to the big structure might be  
enough to cause it to not get freed up; I'm not that familiar with the  
new code.  But the conservative approach seems to be to keep the SCM  
(Lisp_Object) values live as long as the pointed-to data is needed.

It may also be that all of the callers will keep references to the  
symbol object until the indirect_variable work is done, even with  
uninterned symbols.  If that's the case, maybe I don't need to be  
concerned on this score.

However, there's also the little matter that eventually I want to make  
Emacs use Guile symbols for its own symbols, for better interaction  
between the languages.  That means that "struct Lisp_Symbol" would go  
away.  If it's part of the internal function interfaces, that means  
the Guile work has to have greater divergence from the upstream code.

Ken




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-26 16:08   ` Tom Tromey
@ 2009-08-26 18:50     ` Ken Raeburn
  2009-08-27  5:07       ` Miles Bader
  0 siblings, 1 reply; 54+ messages in thread
From: Ken Raeburn @ 2009-08-26 18:50 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Emacs development discussions

On Aug 26, 2009, at 12:08, Tom Tromey wrote:
> Ken> I hope you and Daniel and I aren't doing redundant work.
>
> Unless your changes apply to Emacs I don't think they are really
> redundant.  I think the key thing is agree how it ought to work, so we
> end up with the same model, but I don't anticipate any problems there.

Well, in their current form, my Emacs changes are kind of ugly, so  
they won't be applied in their current form.  Some of them are hacks  
to get things working, so we can (eventually) evaluate the feasibility  
of merging in Guile for real.  It's not that I don't want to fix  
things properly; but fixing some of them properly requires either  
large-scale divergence from the Emacs repository -- in small but  
pervasive and less well automated ways -- or changes to how things are  
done in the Emacs repository that can't be enforced very cleanly, and  
which my only argument for is, "well, my Guile work that may or may  
not ever get folded in is going to need it."

The big issue -- the *huge* one -- is that all-bits-zero, the default  
C initializer for a static Lisp_Object and the result of bzero, is an  
integer-zero in Emacs currently and an invalid object representation  
in Guile.  There are lots of places where such values get used, or  
Lisp_Object variables or fields are made visible to the GC system  
before being properly "initialized" with valid representations.

I could go change all of the places like that to first initialize a  
location with a valid object before using it, but I don't see how to  
tweak the non-Guile version to help me catch such cases without, say,  
changing Lisp_Int to use a nonzero tag, which would affect performance  
(how much?), and would stop XINT/XUINT from being a shortcut for  
"gimme all the bits" in the hash code and perhaps a few other places I  
haven't tracked down yet.

Or, I could change things like staticpro to first store a valid object  
value, which then requires that the assignment of the desired value in  
the various init_foo functions *must* happen after the staticpro call,  
whereas now the ordering is inconsistent.  That might be more  
enforceable, because I can make staticpro and the like complain if  
they see anything other than all-bits-zero, which implies that the  
code tried to store the desired value (other than integer-zero)  
first.  I'd still have to patch up anything using bzero to follow it  
up with explicit initialization of some fields.

It's a bit annoying that the unexec setup basically prohibits the use  
of static initializers for Lisp_Object variables because they might  
become read-only; otherwise static initialization of V* and Q*  
variables with a macro expanding to a valid object representation  
would be an option.

I was figuring on pushing this work a bit further along, and having  
something I could show off better, to make a stronger case for  
integrating the guile-emacs work, before trying to argue for such  
changes in the main Emacs code base.  (Even if the decision eventually  
went against integrating Guile specifically, I might be able to make a  
case for going through a little pain to better isolate the Lisp engine  
so it could perhaps be replaced someday by something else.)  And in  
the meantime, I'd prefer to keep it easier to resync with upstream  
changes, by not rewriting all that code, just as long as I know  
roughly what needs to be fixed later.

But, I digress. :-)

My own changes are, in part, to insulate the C Lisp implementation in  
Emacs as much as possible from the rest of Emacs, and in part, to  
replace the most fundamental layer -- representation, allocation and  
GC -- with Guile.  Whether this project eventually leads to replacing  
the Lisp evaluator itself, I don't know; some people seem to think it  
would be a great idea, and some seem to think it would be a bad idea.   
I'm on the fence until I can see some performance numbers and serious  
testing, and that requires a more or less complete implementation;  
there's been some encouraging work happening on the Guile side, but  
it's not done yet.  But it's appealing to think we might someday be  
able to have elisp available as an extension language for other  
programs, via Guile; and if that happens, do we really need two  
implementations?  (And if we go with only one for both Emacs and  
Guile, would it be the current Guile one, or taken from Emacs and  
dropped into Guile?  Dunno.)

I'm not worrying about things like multithreading, but my changes will  
need to ensure that symbol value lookups and updates are sufficiently  
isolated through macros or functions that it should be easy to slip in  
thread-specific processing.

Daniel Kraft and others are working on the Guile elisp implementation,  
which in part requires learning the specs of how elisp functions in  
various corner cases as well as normal usage.  There has been some  
discussion of multithreading, but as far as I know there's currently  
no implementation of buffer-local variables.

Daniel's work is using Guile's string and symbol representations.  I  
started with the "smob" application-defined-object handles so I could  
store pointers to Lisp_String and Lisp_Symbol and so forth, and not  
have to rewrite all that code right away; that's coming up.  So  
there's a bit of work needed before Daniel's work and mine can  
possibly work together.

> Ken> I've written similar elisp code for doing transformations of  
> patterns
> Ken> within the Emacs code -- mostly more localized things like "XCONS
> Ken> (expr)->car" to "XCAR (expr)", but with support for somewhat  
> complex
> Ken> values of "expr" that have to have balanced parens, etc.
>
> If you still have these, I would appreciate a copy, so that I don't  
> have
> to reinvent them.  Are they in your git repository?

No, but I've got them floating around somewhere, and I'll send you a  
copy.
They're not pretty, but they get the job done.

> I will have to think about this.  This would imply removing all those
> slots from struct buffer; I suppose my concern would be that the  
> result
> would be too inefficient.

Not necessarily.  With Lisp_Misc_Buffer_Objfwd, one of the existing  
fields is the offset into the buffer structure.  Maybe that could be  
where the thread-local object handle is stored.

> I've also been considering a similar thing for the Vfoo globals:  
> remove
> them and have the C code always refer to them via SYMBOL_VALUE.

I think that might also simplify some things for my work.

Ken




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-26 15:31   ` Tom Tromey
@ 2009-08-26 19:18     ` Stefan Monnier
  2009-09-18 22:59       ` Tom Tromey
  0 siblings, 1 reply; 54+ messages in thread
From: Stefan Monnier @ 2009-08-26 19:18 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Emacs development discussions

> I'm trying to properly implement per-thread let binding in the presence
> of buffer-local variables.

The problem with that is that we first need to figure out what its
semantics should be.  And to me the semantics of a let-bound
buffer-local variable is very much unclear in the presence of threads
(it's already pretty messy even without threads).

So I'd rather disallow other threads from accessing this buffer's
variable while the let-binding is active.

> I was planning to do this by inserting a thread-based lookup anywhere a
> buffer-local was accessed.  However, to do this, I need to insert a
> function call anywhere a field corresponding to a DEFVAR_PER_BUFFER is
> used.

> So, e.g., I would like to change:

b-> major_mode = Qfundamental_mode;

> to:

>     BUFFER_MAJOR_MODE (b) = Qfundamental_mode;

> Doing this transform for all 54 DEFVAR_PER_BUFFER fields is a big pain,
> though, so I thought I'd ask about it first.

This may have a very significant performance impact.  Now, maybe we'll
have to bite the bullet sooner or later.  But I'd rather not yet.
This said, I'd accept a patch that turns all

     .... b->major_mode ...
into
     .... PER_BUFFER_VAR (b, major_mode) ...

or even with two different macros (one for lvalue, and one for rvalue).


        Stefan




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-26 18:50     ` Ken Raeburn
@ 2009-08-27  3:12       ` Stefan Monnier
  2009-08-27  6:28         ` Ken Raeburn
  0 siblings, 1 reply; 54+ messages in thread
From: Stefan Monnier @ 2009-08-27  3:12 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: Tom Tromey, Emacs development discussions

> Oh, right... I meant to ask you at some point if there was a reason for that
> other than streamlining performance a little.

It has nothing to do with performance, and everything to do with code
cleanliness and robustness.  Using Lisp_Symbol* rather than Lisp_Object
makes it clear (both to the reader and to the type-checker) that the
object received (or returned) can only be a symbol.

> Now, with the GC work in progress, it's possible that during conservative
> stack scanning, the pointer to the big structure might be  enough to cause
> it to not get freed up; I'm not that familiar with the  new code.  But the
> conservative approach seems to be to keep the SCM  (Lisp_Object) values live
> as long as the pointed-to data is needed.

Emacs's stack scanning already has to check both Lisp_Object values
(i.e. tagged pointers) and plain direct untagged pointers.  This was
needed IIRC because even if the C code appears to hold on to
a Lisp_Object value, the optimizer may get rid of it and only keep the
untagged pointer.

So, I think Guile's stack scanning will have to do that as well, I think
(regardless of Emacs integration).

> However, there's also the little matter that eventually I want to make Emacs
> use Guile symbols for its own symbols, for better interaction  between the
> languages.  That means that "struct Lisp_Symbol" would go  away.  If it's
> part of the internal function interfaces, that means  the Guile work has to
> have greater divergence from the upstream code.

We'll cross that bridge when we get there.  I think we'll find that the
particular interface used by the function will be a very minor issue
(the whole function will probably need to be rewritten).


        Stefan




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-26 18:50     ` Ken Raeburn
@ 2009-08-27  5:07       ` Miles Bader
  2009-08-27  6:39         ` Ken Raeburn
  0 siblings, 1 reply; 54+ messages in thread
From: Miles Bader @ 2009-08-27  5:07 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: Tom Tromey, Emacs development discussions

Ken Raeburn <raeburn@raeburn.org> writes:
> in part, to replace the most fundamental layer -- representation,
> allocation and GC -- with Guile.

Do we actually want to do this?  How is guile regarded these days (back
in the day, it was a horrid bloated mess)?

-Miles

-- 
The trouble with most people is that they think with their hopes or
fears or wishes rather than with their minds.  -- Will Durant




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-27  3:12       ` Stefan Monnier
@ 2009-08-27  6:28         ` Ken Raeburn
  2009-08-27 17:02           ` Stefan Monnier
  0 siblings, 1 reply; 54+ messages in thread
From: Ken Raeburn @ 2009-08-27  6:28 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Tom Tromey, Emacs development discussions

On Aug 26, 2009, at 23:12, Stefan Monnier wrote:
> Emacs's stack scanning already has to check both Lisp_Object values
> (i.e. tagged pointers) and plain direct untagged pointers.  This was
> needed IIRC because even if the C code appears to hold on to
> a Lisp_Object value, the optimizer may get rid of it and only keep the
> untagged pointer.

Does that mean that GC_USE_GCPROS_AS_BEFORE doesn't work reliably?  If  
so, maybe we should get rid of it.  (Though, it appears to be the  
default.)

>> [...getting rid of struct Lisp_Symbol...]
>
> We'll cross that bridge when we get there.  I think we'll find that  
> the
> particular interface used by the function will be a very minor issue
> (the whole function will probably need to be rewritten).

Agreed.  It wasn't particularly even important to bring up, except  
that I think Tom may be looking at changing related code.

Ken




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-27  5:07       ` Miles Bader
@ 2009-08-27  6:39         ` Ken Raeburn
  2009-08-27  6:50           ` Miles Bader
  0 siblings, 1 reply; 54+ messages in thread
From: Ken Raeburn @ 2009-08-27  6:39 UTC (permalink / raw)
  To: Miles Bader; +Cc: Tom Tromey, Emacs development discussions

On Aug 27, 2009, at 01:07, Miles Bader wrote:
> Ken Raeburn <raeburn@raeburn.org> writes:
>> in part, to replace the most fundamental layer -- representation,
>> allocation and GC -- with Guile.
>
> Do we actually want to do this?  How is guile regarded these days  
> (back
> in the day, it was a horrid bloated mess)?

I still think of this project partly as being in the "let's see how it  
works out and decide if we want to keep it" stage, or even "let's try  
this big application and see what problems we find in Guile".  So I'm  
not quite ready to answer -- or ask -- if we want to do it.  With a  
bit more polish, and some more intense testing, and performance  
analysis, maybe...

I can't really speak to how Guile is regarded; I do much more stuff in  
the Emacs and Guile internals than with ordinary applications that  
might use it, and I'm by no stretch of the imagination any kind of  
Scheme expert.  But I don't think how Guile is regarded should be as  
important as how Guile *is*.  If there are real problems with using it  
in Emacs -- as opposed to everyone just remembering how it *used* to  
be considered a "horrid bloated mess" -- then we can try to fix them  
on the Guile side, or decide to drop the project.

It's had performance problems for some time, but recent work has made  
some big improvements, putting it back in competition with some of the  
other implementations, and there's a bit of talk about compiling not  
just to VM byte codes but even to native code for some architectures  
someday.  It sounds a bit like pie-in-the-sky stuff, and some of these  
sorts of things have moved very slowly in Guile development in the  
past, but the guy doing the compiler and optimizer work right now is  
making some good progress, and I wouldn't put it past him.  There's  
also some GC system work happening, but I haven't been following that  
closely.  And if we wind up in a situation where doing such work  
benefits both Guile and Emacs because one is using the code from the  
other, it *could* be good for both projects.  (And, of course, if it  
goes badly, it could make it harder to improve things all around.)   
Thread support is another example -- if Emacs were already using Guile  
underneath the Lisp engine, thread support would probably be quite a  
bit easier.

My reasoning for trying this is in some ways political as well as  
technical.  Guile is touted as the GNU project's extension language.   
Yet one of the highest-profile, most-extensible and most-extended  
programs GNU ships doesn't use it, but instead uses a separate,  
private implementation of a rather similar language.  If "GNU's  
extension language" isn't good enough for this application, and can't  
be made good enough, then maybe we should declare it a failure as  
"GNU's extension language" and either do something else or drop the  
idea entirely.  But I don't think we've gotten to that point.

And on the technical side, I'm trying to keep most of the work in the  
Emacs "application-level" code non-specific to Guile, so if someone  
decides to replace the Lisp engine with something other than Guile, my  
changes to isolate the implementation details and assumptions made may  
still not be wasted.

BTW, if anyone is interested in helping on the Guile-Emacs work, I'd  
love to have some help.  There's quite a number of pieces still to be  
tackled, some purely on the Emacs side, others having to do with  
making the interaction between the two work better....

Ken




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-27  6:39         ` Ken Raeburn
@ 2009-08-27  6:50           ` Miles Bader
  2009-08-28 20:48             ` Juri Linkov
  0 siblings, 1 reply; 54+ messages in thread
From: Miles Bader @ 2009-08-27  6:50 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: Tom Tromey, Emacs development discussions

Ken Raeburn <raeburn@raeburn.org> writes:
>  But I don't think how Guile is regarded should be as
> important as how Guile *is*.

How important is guile?

15 years ago there were grand plans, but... dunno about now.
It's a different world in many ways.

-miles

-- 
=====
(^o^;
(()))
*This is the cute octopus virus, please copy it into your sig so it can spread.




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-27  6:28         ` Ken Raeburn
@ 2009-08-27 17:02           ` Stefan Monnier
  0 siblings, 0 replies; 54+ messages in thread
From: Stefan Monnier @ 2009-08-27 17:02 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: Tom Tromey, Emacs development discussions

>> Emacs's stack scanning already has to check both Lisp_Object values
>> (i.e. tagged pointers) and plain direct untagged pointers.  This was
>> needed IIRC because even if the C code appears to hold on to
>> a Lisp_Object value, the optimizer may get rid of it and only keep the
>> untagged pointer.
> Does that mean that GC_USE_GCPROS_AS_BEFORE doesn't work reliably?

It's very little tested, but it should work reliably.  The reason it
works reliably is that the GCPRO macros cause the Lisp_Object variables
to be accessed via "&" and their address is stored in a globally
accessible data structure, so the compiler cannot optimize those
variables away, or even keep them in registers.


        Stefan




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-27  6:50           ` Miles Bader
@ 2009-08-28 20:48             ` Juri Linkov
  2009-08-28 22:15               ` Miles Bader
  0 siblings, 1 reply; 54+ messages in thread
From: Juri Linkov @ 2009-08-28 20:48 UTC (permalink / raw)
  To: Miles Bader; +Cc: Tom Tromey, Ken Raeburn, Emacs development discussions

> How important is guile?
>
> 15 years ago there were grand plans, but... dunno about now.
> It's a different world in many ways.

AFAIK, Guile and Scheme as a whole still flourish these days,
and the only serious contender is Clojure that could integrate
with Emacs the same way as it does with Java.

-- 
Juri Linkov
http://www.jurta.org/emacs/




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-28 20:48             ` Juri Linkov
@ 2009-08-28 22:15               ` Miles Bader
  2009-08-28 23:27                 ` Juri Linkov
  2009-08-29 20:21                 ` Richard Stallman
  0 siblings, 2 replies; 54+ messages in thread
From: Miles Bader @ 2009-08-28 22:15 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Tom Tromey, Ken Raeburn, Emacs development discussions

Juri Linkov <juri@jurta.org> writes:
>> 15 years ago there were grand plans, but... dunno about now.
>> It's a different world in many ways.
>
> AFAIK, Guile and Scheme as a whole still flourish these days,

There are a huge number of scheme implementations now; even thinking
just about scheme, is guile still competitive?

> and the only serious contender is Clojure that could integrate
> with Emacs the same way as it does with Java.

Why?  There are tons of random little languages around now, some very
popular (i.e., javascript), many not so much.  Clojure is not scheme, so
why is it any better than those?  [Compatibility with the java runtime
is important for some people, but AFAIK, not for Emacs!]

-Miles

-- 
.Numeric stability is probably not all that important when you're guessing.




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-28 22:15               ` Miles Bader
@ 2009-08-28 23:27                 ` Juri Linkov
  2009-08-28 23:54                   ` Miles Bader
  2009-08-29 20:21                 ` Richard Stallman
  1 sibling, 1 reply; 54+ messages in thread
From: Juri Linkov @ 2009-08-28 23:27 UTC (permalink / raw)
  To: Miles Bader; +Cc: Tom Tromey, Ken Raeburn, Emacs development discussions

>>> 15 years ago there were grand plans, but... dunno about now.
>>> It's a different world in many ways.
>>
>> AFAIK, Guile and Scheme as a whole still flourish these days,
>
> There are a huge number of scheme implementations now; even thinking
> just about scheme, is guile still competitive?

Among all Scheme implementations Guile is in the same position
as bzr among all DVCSs - it is the "official" selection for the
GNU project.

>> and the only serious contender is Clojure that could integrate
>> with Emacs the same way as it does with Java.
>
> Why?  There are tons of random little languages around now,

Clojure is a little language with a big impact.

> some very popular (i.e., javascript), many not so much.

JavaScript is not Lisp.

> Clojure is not scheme, so why is it any better than those?

Clojure is not Scheme, but Clojure is Lisp, like Emacs Lisp is.

> [Compatibility with the java runtime is important for some people, but
> AFAIK, not for Emacs!]

True, but I thought about replacing its Java VM part with Emacs.
Anyway, this point is moot, since Clojure concurrency relies on
Java threads, but Emacs has no threads yet.  At least, Clojure
is a good example how concurrency with STM, agent, atoms and
dynamic var systems could be implemented in Emacs.

-- 
Juri Linkov
http://www.jurta.org/emacs/




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-28 23:27                 ` Juri Linkov
@ 2009-08-28 23:54                   ` Miles Bader
  0 siblings, 0 replies; 54+ messages in thread
From: Miles Bader @ 2009-08-28 23:54 UTC (permalink / raw)
  To: Juri Linkov; +Cc: Tom Tromey, Ken Raeburn, Emacs development discussions

On Sat, Aug 29, 2009 at 8:27 AM, Juri Linkov<juri@jurta.org> wrote:
>> There are a huge number of scheme implementations now; even thinking
>> just about scheme, is guile still competitive?
>
> Among all Scheme implementations Guile is in the same position
> as bzr among all DVCSs - it is the "official" selection for the
> GNU project.

I'm not asking about labels, I'm asking about merit.

>>> and the only serious contender is Clojure that could integrate
>>> with Emacs the same way as it does with Java.
>>
>> Why?  There are tons of random little languages around now,
>
> Clojure is a little language with a big impact.

Clojure has been very hyped, but it's still far from clear it will
have any lasting impact.

Anyway, clojure (or at least its engine) has merit, but it seems very
premature to call it "the only serious contender."

-Miles

-- 
Do not taunt Happy Fun Ball.




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-26  4:38 advice needed for multi-threading patch Tom Tromey
  2009-08-26  7:06 ` Ken Raeburn
  2009-08-26 15:02 ` Stefan Monnier
@ 2009-08-29  0:28 ` Giuseppe Scrivano
  2009-08-29  4:57   ` Tom Tromey
  2 siblings, 1 reply; 54+ messages in thread
From: Giuseppe Scrivano @ 2009-08-29  0:28 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Emacs development discussions

Hello Tom,

I only now saw this thread and multi-threaded Emacs is still in my
wish-list :-)  Do you already have some working code?  I was expecting
the final migration to BZR before start working again on it.
Last time that I rebased my patch, approximately two months ago, it was
still working and I think something can be re-used from it.

In my work, I didn't consider threads local storage for two reasons the
first and most important is that elisp packages (yet?) don't know about
it and wouldn't use; the second reason is that it adds a lot of
complexity while I don't see much benefits so I chose simplicity.
Probably threads local storage can be useful when the cooperative model
will be changed to something more serious, but that is another story :-)

Cheers,
Giuseppe



Tom Tromey <tromey@redhat.com> writes:

> I was inspired by Giuseppe Scrivano's work from last year:
>
> http://lists.gnu.org/archive/html/emacs-devel/2008-11/msg01067.html
>
> ... so I started working on my own patch to implement multi-threading in
> Emacs.  I've tried to follow Stefan's advice as given in that thread.
> In particular I've (initially) implemented cooperative multi-threading.
>
> Some background for my particular question:
>
> My implementation of dynamic binding uses a structure like so:
>
>     struct Lisp_ThreadLocal
>       {
>         enum Lisp_Misc_Type type : 16;	/* = Lisp_Misc_ThreadLocal */
>         unsigned gcmarkbit : 1;
>         int spacer : 15;
>         Lisp_Object global;
>         Lisp_Object thread_alist;
>       };
>
> ... the idea being that a let-bound variable will be on 'thread_alist'
> (keyed by the thread), and other threads will see the value in 'global'.
> These objects are found in symbol value slots.
>
> I managed to handle the V* global variables by writing some elisp that
> changed every declaration of a variable mentioned in a DEFVAR_LISP from
> Vfoo to impl_Vfoo and also emitted a new header with a lot of:
>
>     #define Vfoo *find_variable_location (&impl_Vfoo)
>
> This was pretty simple and non-intrusive, in the sense that it is
> totally automated, so I can easily reapply it as Emacs changes.
>
> ... which brings me to my problem.  I'd also like to apply a similar
> treatment to buffer-local variables.  However, those do not have
> convenient accessor macros, and before starting the laborious task of
> wrapping all buffer field accesses, I thought I'd ask for advice.  Is
> this a sane way to proceed?  Should I do something different?  Could I
> get such a patch in before the rest of this work, just to make my local
> divergence smaller?
>
> I'll also note that the above approach does not work for DEFVAR_INT.  I
> have a plan for those but I fear it is somewhat expensive.  If you have
> an idea...
>
> Tom




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-29  0:28 ` Giuseppe Scrivano
@ 2009-08-29  4:57   ` Tom Tromey
  0 siblings, 0 replies; 54+ messages in thread
From: Tom Tromey @ 2009-08-29  4:57 UTC (permalink / raw)
  To: Giuseppe Scrivano; +Cc: Emacs development discussions

>>>>> "Giuseppe" == Giuseppe Scrivano <gscrivano@gnu.org> writes:

Giuseppe> I only now saw this thread and multi-threaded Emacs is still
Giuseppe> in my wish-list :-) Do you already have some working code?

Yeah.  Well, I did ... it is not working today because I am in the
middle of changing the variable binding implementation and implementing
buffer locking.

Giuseppe> In my work, I didn't consider threads local storage for two
Giuseppe> reasons the first and most important is that elisp packages
Giuseppe> (yet?) don't know about it and wouldn't use; the second reason
Giuseppe> is that it adds a lot of complexity while I don't see much
Giuseppe> benefits so I chose simplicity.

I suspect we may be talking about different things.  When I say
thread-local storage, I just mean having 'let' bindings work properly
when two different threads use the same symbol name.

In case not: my goal was to write the smallest patch that would yield a
usefully multi-threaded Emacs.  It seemed to me that the binding issue
had to be dealt with somehow, because ignoring it would mean that the
resulting Emacs could not run any real programs.

As I saw it, the choices were either to undo and redo all the bindings
at every context switch, or implement thread-local bindings.  I looked
into both a bit, and thread-local bindings did not seem too hard, except
for defining the semantics of the interaction between multiple threads
and buffer-local variables.

Right now I have something similar to your patch (except using a single
thread-local current_thread pointer instead of arrays); plus changes to
the GC and to make DEFVAR_LISP work.

Tom




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-28 22:15               ` Miles Bader
  2009-08-28 23:27                 ` Juri Linkov
@ 2009-08-29 20:21                 ` Richard Stallman
  1 sibling, 0 replies; 54+ messages in thread
From: Richard Stallman @ 2009-08-29 20:21 UTC (permalink / raw)
  To: Miles Bader; +Cc: juri, tromey, raeburn, emacs-devel

    There are a huge number of scheme implementations now; even thinking
    just about scheme, is guile still competitive?

Guile is the GNU Scheme implementation; unless it is so
inadequate that we should drop it entirely, it should be the
one we use in Emacs (if we use one).




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-08-26 19:18     ` Stefan Monnier
@ 2009-09-18 22:59       ` Tom Tromey
  2009-09-19  0:09         ` Stephen J. Turnbull
                           ` (2 more replies)
  0 siblings, 3 replies; 54+ messages in thread
From: Tom Tromey @ 2009-09-18 22:59 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Emacs development discussions

Tom> I'm trying to properly implement per-thread let binding in the presence
Tom> of buffer-local variables.

Stefan> The problem with that is that we first need to figure out what its
Stefan> semantics should be.  And to me the semantics of a let-bound
Stefan> buffer-local variable is very much unclear in the presence of threads
Stefan> (it's already pretty messy even without threads).

Stefan> So I'd rather disallow other threads from accessing this buffer's
Stefan> variable while the let-binding is active.

I thought I'd post a status report on the multi-threading patch.

First, thanks to Giuseppe, it is all hosted on Gitorious:

    http://gitorious.org/emacs-mt

'mt' is the branch I've been working on, he's done some additional fixes
and changes on g-exp.  (I am behind on pulling from him... and we don't
agree about everything, hence two branches :-)

What works:

* You can start a new thread with run-in-thread.  The exact use differs
  between the branches.  Threads are cooperative, you can yield with an
  explicit call to yield.

* The GC handles multiple threads.

* Many, but not all, of the 9 kinds of variables that Emacs implements
  work properly with threads.  In particular, working ones are
  defvaralias, objfwd, and ordinary.  These all should do the right
  thing in all cases.  Buffer-local and buffer objfwd mostly work,
  because we do buffer locking.  (However, I think make-local-variable
  doesn't work properly with let-binding and multiple threads.)  Not
  working on intfwd, boolfwd, keyboard-local and frame-local.

* Buffer locking.


There are also a number of problem areas.

* Buffer locking is actually quite a pain.

  If you have a background thread locking some buffer, you can't switch
  to that buffer.  Emacs will just pause.  I don't think we allow
  interrupting a lock acquisition (clearly a bug).

* Giuseppe implemented minibuffer exclusion.  But really the keyboard
  should only be available to one thread at a time.

* I think there are some V* variables that probably should always be
  per-thread.  My notes say Vsignaling_function, but I know I've run
  into other ones.  (What is noteworthy about this is that it implies
  that a big audit of the C code is necessary..)

* I/O is also an unsolved problem.  Right now it is easy to make emacs
  appear to hang by running a process filter in one thread while a
  different thread owns the buffer lock.  (Probably, if a thread owns a
  buffer lock, then only that thread should be able to run associated
  process filters.)

I think Giuseppe probably knows of more problems.

Also, there are tons more problems if you want preemptive
multithreading... redisplay probably needs work, regex is not reentrant,
the GC needs a bit more work, you need lisp-level locks, etc.


Sometimes I wonder whether it would be better to just fork a second
emacs and communicate with it using pipes + princ + read.  This uses
more memory but the implementation would be a lot simpler and (I think)
it would suffice for the one case that seems most important: Gnus.


Anyway, give it a try.  We welcome your advice and input.


Finally, we've been doing all our discussions privately on irc.  I'd
prefer we discuss everything in the open.  Is it ok to use emacs-devel
for this?  If not we'll set up a new mailing list somewhere.

Tom




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-18 22:59       ` Tom Tromey
@ 2009-09-19  0:09         ` Stephen J. Turnbull
  2009-09-19  0:32         ` Chong Yidong
  2009-09-21 21:19         ` Stefan Monnier
  2 siblings, 0 replies; 54+ messages in thread
From: Stephen J. Turnbull @ 2009-09-19  0:09 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Stefan Monnier, Emacs development discussions

Tom Tromey writes:

 > Sometimes I wonder whether it would be better to just fork a second
 > emacs and communicate with it using pipes + princ + read.

Everybody at XEmacs who has thought about the problem has come to that
conclusion, although the specifics of how the communication would take
place vary.  (Except for those people who think that changing the Lisp
engine to something with sane semantics for a threading environment
should come first; they usually have a multithreaded implementation of
Scheme in mind anyway.)







^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-18 22:59       ` Tom Tromey
  2009-09-19  0:09         ` Stephen J. Turnbull
@ 2009-09-19  0:32         ` Chong Yidong
  2009-09-21 21:19         ` Stefan Monnier
  2 siblings, 0 replies; 54+ messages in thread
From: Chong Yidong @ 2009-09-19  0:32 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Stefan Monnier, Emacs development discussions

Tom Tromey <tromey@redhat.com> writes:

> Finally, we've been doing all our discussions privately on irc.  I'd
> prefer we discuss everything in the open.  Is it ok to use emacs-devel
> for this?  If not we'll set up a new mailing list somewhere.

Yes, discussing this on emacs-devel is fine.




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-18 22:59       ` Tom Tromey
  2009-09-19  0:09         ` Stephen J. Turnbull
  2009-09-19  0:32         ` Chong Yidong
@ 2009-09-21 21:19         ` Stefan Monnier
  2009-09-21 21:50           ` Tom Tromey
  2 siblings, 1 reply; 54+ messages in thread
From: Stefan Monnier @ 2009-09-21 21:19 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Emacs development discussions

> * Many, but not all, of the 9 kinds of variables that Emacs implements
>   work properly with threads.  In particular, working ones are
>   defvaralias, objfwd, and ordinary.  These all should do the right
>   thing in all cases.  Buffer-local and buffer objfwd mostly work,
>   because we do buffer locking.  (However, I think make-local-variable
>   doesn't work properly with let-binding and multiple threads.)  Not
>   working on intfwd, boolfwd, keyboard-local and frame-local.

How do you handle objfwd objects?  Do you swap them in&out during
context switches?

> * Buffer locking is actually quite a pain.
>   If you have a background thread locking some buffer, you can't switch
>   to that buffer.  Emacs will just pause.  I don't think we allow
>   interrupting a lock acquisition (clearly a bug).

Yes, we may have to relax the locking somehow.  E.g. we should clearly
allow to display a buffer in any window, if the buffer is "locked" by
a thread.  I.e. things like switch-to-buffer should not take the
buffer's lock.

Of course, if the buffer is locked by a thread, we also need to be
careful what we do if the user then types a command in it (should we
wait for the thread to yield or should we signal an erreur?)

> * Giuseppe implemented minibuffer exclusion.  But really the keyboard
>   should only be available to one thread at a time.

You mean "each keyboard", right?

> Also, there are tons more problems if you want preemptive
> multithreading... redisplay probably needs work, regex is not
> reentrant, the GC needs a bit more work, you need lisp-level
> locks, etc.

Yes, lots of fun stuff, indeed.

> Sometimes I wonder whether it would be better to just fork a second
> emacs and communicate with it using pipes + princ + read.  This uses
> more memory but the implementation would be a lot simpler and (I think)
> it would suffice for the one case that seems most important: Gnus.

But you can already do that right now, so it's a different "solution".


        Stefan




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-21 21:19         ` Stefan Monnier
@ 2009-09-21 21:50           ` Tom Tromey
  2009-09-22 14:24             ` Stefan Monnier
  0 siblings, 1 reply; 54+ messages in thread
From: Tom Tromey @ 2009-09-21 21:50 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Emacs development discussions

>>>>> "Stefan" == Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

Tom> * Many, but not all, of the 9 kinds of variables that Emacs implements
Tom> work properly with threads.  In particular, working ones are
Tom> defvaralias, objfwd, and ordinary.  These all should do the right
Tom> thing in all cases.  Buffer-local and buffer objfwd mostly work,
Tom> because we do buffer locking.  (However, I think make-local-variable
Tom> doesn't work properly with let-binding and multiple threads.)  Not
Tom> working on intfwd, boolfwd, keyboard-local and frame-local.

Stefan> How do you handle objfwd objects?  Do you swap them in&out during
Stefan> context switches?

We have a script to edit the Emacs source.  In the end all DEFUN_LISP
variables are defined like:

#define Vafter_change_functions *find_variable_location (&impl_Vafter_change_functions)

Then, find_variable_location understands Lisp_ThreadLocal binding.
A Lisp_ThreadLocal is put into an impl_V* by specbind.

This works great as long as the C code follows lispy rules.  However, I
don't think that is always the case -- there are places doing direct
assignment to some of these variables where, really, a per-thread
assignment is meant.

We don't swap anything in and out during a context switch.  I've tried
to make all the decisions with an eye on the long term: preemptive
threading.  Ultimately I'd like to get rid of the global lock and have
all threads run free.

Tom> * Buffer locking is actually quite a pain.
Tom> If you have a background thread locking some buffer, you can't switch
Tom> to that buffer.  Emacs will just pause.  I don't think we allow
Tom> interrupting a lock acquisition (clearly a bug).

Stefan> Yes, we may have to relax the locking somehow.  E.g. we should clearly
Stefan> allow to display a buffer in any window, if the buffer is "locked" by
Stefan> a thread.  I.e. things like switch-to-buffer should not take the
Stefan> buffer's lock.

Stefan> Of course, if the buffer is locked by a thread, we also need to be
Stefan> careful what we do if the user then types a command in it (should we
Stefan> wait for the thread to yield or should we signal an erreur?)

Giuseppe has some code to let a thread acquire a buffer without locking.
But, this is done in an unsafe way; I think it is just a hack to let him
experiment with Gnus a bit.

Right now when a thread yields it does not release its buffer lock.
The only way to do that is to set-buffer to another buffer.

One way forward would be to work out the semantics properly, and
eliminate buffer locking.  Some of the semantics seems tricky.  And, the
work itself is hard, because it means adding tons of accessor macros and
then updating a lot of source code to use them.  (I did this, once, for
a lot of Emacs, thinking to implement a software write barrier.  It is
really quite painful.)

Tom> * Giuseppe implemented minibuffer exclusion.  But really the keyboard
Tom> should only be available to one thread at a time.

Stefan> You mean "each keyboard", right?

Yes.

Locking a keyboard will probably have strange effects.  There are some
things here that I have not thought through; like, what is the right
behavior of debug-on-error?  Under what conditions would the main thread
ever release the keyboard?

Tom> Sometimes I wonder whether it would be better to just fork a second
Tom> emacs and communicate with it using pipes + princ + read.  This uses
Tom> more memory but the implementation would be a lot simpler and (I think)
Tom> it would suffice for the one case that seems most important: Gnus.

Stefan> But you can already do that right now, so it's a different "solution".

Yeah.  I just wonder why nobody has done it and whether it would not be
a better approach.

Tom




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-21 21:50           ` Tom Tromey
@ 2009-09-22 14:24             ` Stefan Monnier
  2009-09-22 23:59               ` Ken Raeburn
                                 ` (3 more replies)
  0 siblings, 4 replies; 54+ messages in thread
From: Stefan Monnier @ 2009-09-22 14:24 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Emacs development discussions

Stefan> How do you handle objfwd objects?  Do you swap them in&out during
Stefan> context switches?

> We have a script to edit the Emacs source.  In the end all DEFUN_LISP
> variables are defined like:

> #define Vafter_change_functions *find_variable_location (&impl_Vafter_change_functions)

Oh, right, I remember now, sorry.

> This works great as long as the C code follows lispy rules.  However, I
> don't think that is always the case -- there are places doing direct
> assignment to some of these variables where, really, a per-thread
> assignment is meant.

I'm not sure what you mean.  Are you still talking about objfwd
variables?

> We don't swap anything in and out during a context switch.  I've tried
> to make all the decisions with an eye on the long term: preemptive
> threading.  Ultimately I'd like to get rid of the global lock and have
> all threads run free.

That was the motivation for my question, indeed.

> Right now when a thread yields it does not release its buffer lock.

I think it should, unless some of the buffer-local variables are
let-bound by the thread.

> One way forward would be to work out the semantics properly, and
> eliminate buffer locking.

Yes, although the result of this may end up requiring some form of
buffer-locking, still.

> Some of the semantics seems tricky.

Oh, yes.

Stefan> You mean "each keyboard", right?

> Yes.
> Locking a keyboard will probably have strange effects.  There are some
> things here that I have not thought through; like, what is the right
> behavior of debug-on-error?  Under what conditions would the main thread
> ever release the keyboard?

Maybe another way to look at all these problems is to take an "agent"
point of view: rather than threads moving around, we could consider each
keyboard and each buffer as an active object (i.e. with its own thread),
which communicate among each other.  I.e. a buffer-thread never leaves
its buffer, instead it does an RPC to another buffer-thread, or to
a keyboard-thread, ...

> Yeah.  I just wonder why nobody has done it and whether it would not be
> a better approach.

IIUC people do it all the time, tho not with another Emacs process: with
an hexl process, a shell process, an openssl process, ...
Emacs currently is not very good at using stdin/stdout so running an
inferior Emacs process is poorly supported.


        Stefan




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-22 14:24             ` Stefan Monnier
@ 2009-09-22 23:59               ` Ken Raeburn
  2009-09-23  3:11                 ` Stefan Monnier
  2009-09-23 15:53                 ` Chong Yidong
  2009-09-23  3:16               ` Tom Tromey
                                 ` (2 subsequent siblings)
  3 siblings, 2 replies; 54+ messages in thread
From: Ken Raeburn @ 2009-09-22 23:59 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Tom Tromey, Emacs development discussions

On Sep 22, 2009, at 10:24, Stefan Monnier wrote:
>> Yeah.  I just wonder why nobody has done it and whether it would  
>> not be
>> a better approach.
>
> IIUC people do it all the time, tho not with another Emacs process:  
> with
> an hexl process, a shell process, an openssl process, ...
> Emacs currently is not very good at using stdin/stdout so running an
> inferior Emacs process is poorly supported.

I've sometimes thought a command-line option to provide a REPL (read- 
eval-print loop) interface would be handy.  Either directly in Emacs,  
or via the client/server interface... much like interactive emacs lisp  
mode, but purely on the command line.

Ken




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-22 23:59               ` Ken Raeburn
@ 2009-09-23  3:11                 ` Stefan Monnier
  2009-09-23 15:53                 ` Chong Yidong
  1 sibling, 0 replies; 54+ messages in thread
From: Stefan Monnier @ 2009-09-23  3:11 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: Tom Tromey, Emacs development discussions

> I've sometimes thought a command-line option to provide a REPL (read-
> eval-print loop) interface would be handy.  Either directly in Emacs, or via
> the client/server interface... much like interactive emacs lisp  mode, but
> purely on the command line.

Actually --batch isn't far from that.


        Stefan




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-22 14:24             ` Stefan Monnier
  2009-09-22 23:59               ` Ken Raeburn
@ 2009-09-23  3:16               ` Tom Tromey
  2009-09-24 17:25                 ` Stefan Monnier
  2009-09-23 18:43               ` Giuseppe Scrivano
  2009-09-28  7:44               ` Lynbech Christian
  3 siblings, 1 reply; 54+ messages in thread
From: Tom Tromey @ 2009-09-23  3:16 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Emacs development discussions

Tom> This works great as long as the C code follows lispy rules.  However, I
Tom> don't think that is always the case -- there are places doing direct
Tom> assignment to some of these variables where, really, a per-thread
Tom> assignment is meant.

Stefan> I'm not sure what you mean.  Are you still talking about objfwd
Stefan> variables?

Yeah.  What I meant here is that specbind has a little extra code in it
to install a Lisp_ThreadLocal object when needed.  So, if the C code
uses specbind to do let-like binding, everything will work fine.  If the
C code does not do this, then things will break.

For example, I am not certain that Vquit_flag is handled in a "safe"
way.  It is directly assigned to in a number of places, but those
assignments should probably be thread-local.  (This isn't the greatest
example, maybe, because Vquit_flag is also bound up in keyboard locking
and maybe other issues.)

Tom> Right now when a thread yields it does not release its buffer lock.

Stefan> I think it should, unless some of the buffer-local variables are
Stefan> let-bound by the thread.

I've been thinking about this a bit.  It is trickier than it seems,
because a thread can actually have let-bindings for buffer-locals from
multiple buffers at the same time.  There's an example of this in the
elisp manual.  (This is also an area the threading code does not handle
well yet.)

I think this means it does not suffice to keep a simple per-thread count
of buffer-local bindings.

While thinking about this I realized that (I think) the current code
does the wrong thing if one thread let-binds a variable and then another
thread calls make-variable-buffer-local on it.

Stefan> Maybe another way to look at all these problems is to take an
Stefan> "agent" point of view: rather than threads moving around, we
Stefan> could consider each keyboard and each buffer as an active object
Stefan> (i.e. with its own thread), which communicate among each other.
Stefan> I.e. a buffer-thread never leaves its buffer, instead it does an
Stefan> RPC to another buffer-thread, or to a keyboard-thread, ...

I had considered the agent model -- that, plus a discussion on irc, is
actually what lead me to ask about running a second Emacs as a
subprocess.

It is hard for me to see how this could be done in a compatible way.
Right now elisp operates with few constraints; an elisp program can call
select-frame, which seems to imply that per-frame or per-keyboard
threads can't be done.

Tom> Yeah.  I just wonder why nobody has done it and whether it would not be
Tom> a better approach.

Stefan> IIUC people do it all the time, tho not with another Emacs
Stefan> process: with an hexl process, a shell process, an openssl
Stefan> process, ...  Emacs currently is not very good at using
Stefan> stdin/stdout so running an inferior Emacs process is poorly
Stefan> supported.

If I were doing it "for real" I might consider coming up with a
higher-bandwidth way to transfer an entire buffer between processes.
But, a princ/read approach could be done without modifying Emacs, by
having the parent Emacs make a server socket, and then passing the port
number to the subprocess as an argument.  This avoids the stdin/stdout
difficulties.

One thing that would help me is having a concrete idea of what subset of
features would make this work be actually useful.  I mostly implemented
it because it was cool, and because Giuseppe's initial patch convinced
me that it was possible (before that I'd written it off as totally
impractical).  Now that a proof of concept works it would be nice to
have a concrete goal.

Tom




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-22 23:59               ` Ken Raeburn
  2009-09-23  3:11                 ` Stefan Monnier
@ 2009-09-23 15:53                 ` Chong Yidong
  1 sibling, 0 replies; 54+ messages in thread
From: Chong Yidong @ 2009-09-23 15:53 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: Tom Tromey, Stefan Monnier, Emacs development discussions

Ken Raeburn <raeburn@raeburn.org> writes:

> I've sometimes thought a command-line option to provide a REPL (read-
> eval-print loop) interface would be handy.  Either directly in Emacs,
> or via the client/server interface... much like interactive emacs lisp
> mode, but purely on the command line.

  emacs --eval "(while t (print (eval (read))))" --batch




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-22 14:24             ` Stefan Monnier
  2009-09-22 23:59               ` Ken Raeburn
  2009-09-23  3:16               ` Tom Tromey
@ 2009-09-23 18:43               ` Giuseppe Scrivano
  2009-09-24 17:29                 ` Stefan Monnier
  2009-09-28  7:44               ` Lynbech Christian
  3 siblings, 1 reply; 54+ messages in thread
From: Giuseppe Scrivano @ 2009-09-23 18:43 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Tom Tromey, Emacs development discussions

Hello,


Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

>> Right now when a thread yields it does not release its buffer lock.
>
> I think it should, unless some of the buffer-local variables are
> let-bound by the thread.

I think actually this is one of the most important decision to take, it
will have a direct influence on buffer-local variables semantic.  In my
opinion, it is better to have few constraints and allow switch as often
as possible.


As Tom said, I was experimenting with gnus and it made me quite
optimistic; in fact these commands are completed successfully:

  (run-in-thread '(gnus) t) ;; with t the thread doesn't attempt to get
                            ;; a lock on the buffer.
  (while (yield)) ;; yield returns nil when there are not other
                  ;; threads -- simulate join.

The nolock argument in run-in-thread is just a hack to get things
working and see quickly some results.  Acquiring always the lock when
accessing the buffer is too restrictive IMHO as too often the buffer is
already locked.

Following your advice to don't allow a switch only when buffer-local
variables are let-bound by the thread, how many times it happens than a
thread let-bound these variables?  Let's say on 100 times, how many
times approximately do you think a switch will not be allowed and the
calling thread blocked?

Cheers,
Giuseppe




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-23  3:16               ` Tom Tromey
@ 2009-09-24 17:25                 ` Stefan Monnier
  2009-09-24 17:57                   ` Tom Tromey
  2009-09-27 20:59                   ` Tom Tromey
  0 siblings, 2 replies; 54+ messages in thread
From: Stefan Monnier @ 2009-09-24 17:25 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Emacs development discussions

> Yeah.  What I meant here is that specbind has a little extra code in it
> to install a Lisp_ThreadLocal object when needed.  So, if the C code
> uses specbind to do let-like binding, everything will work fine.  If the
> C code does not do this, then things will break.

I see, yes of course it's a problem.  And it's worse than that: the same
holds for *all* global variables, whether they are exported to Lisp
or not.

Stefan> I think it should, unless some of the buffer-local variables are
Stefan> let-bound by the thread.

> I've been thinking about this a bit.  It is trickier than it seems,
> because a thread can actually have let-bindings for buffer-locals from
> multiple buffers at the same time.  There's an example of this in the
> elisp manual.  (This is also an area the threading code does not handle
> well yet.)

> I think this means it does not suffice to keep a simple per-thread count
> of buffer-local bindings.

Indeed.  The lock should probably be on the buffer-local binding itself
(i.e. the combination of the buffer and the variable).

> While thinking about this I realized that (I think) the current code
> does the wrong thing if one thread let-binds a variable and then another
> thread calls make-variable-buffer-local on it.

Calling make-variable-buffer-local or make-local-variable when the
variable is let-bound is a serious problem, yes.  IIRC we already have
bugs in such cases in the current code.
AFAICT, the only good answer is to disallow such things (e.g. signal an
error in make-variable-buffer-local and make-local-variable when the var
is let-bound).
I already took a tiny step in that direction when I added a warning to
defvar when called while the variable is let-bound.

> It is hard for me to see how this could be done in a compatible way.

Agreed.

> Right now elisp operates with few constraints; an elisp program can call
> select-frame, which seems to imply that per-frame or per-keyboard
> threads can't be done.

The way I think of it is that select-frame would send a message to the
relevant frame, along with a function to run there, and the destination
to which to send the result when the function is done.

But how to link it with the dynamic and foo-local scoping of
let-bindings is still far from clear.

> One thing that would help me is having a concrete idea of what subset of
> features would make this work be actually useful.  I mostly implemented
> it because it was cool, and because Giuseppe's initial patch convinced
> me that it was possible (before that I'd written it off as totally
> impractical).  Now that a proof of concept works it would be nice to
> have a concrete goal.

Some goals could be:
- run Gnus in its own thread.  This should be easy-ish since Gnus
  shouldn't interact with pretty much anything else.
- split Gnus into several threads (e.g. in my case, the most important
  one would be a thread to do the "g", i.e. refresh the *Group* buffer,
  which with IMAP boxes can takes ages).
  This is a lot more difficult since this thread would need to interact
  with the main Gnus thread.
- move the jit-lock-context to a thread.  Might be non-trivial, but at
  least the code is small.
- move some VC operations to threads (e.g. vc-checkin).
- run some of the buffer-parsing code in threads (e.g. the one in
  CEDET's semantic, or the one in js2-mode).


        Stefan




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-23 18:43               ` Giuseppe Scrivano
@ 2009-09-24 17:29                 ` Stefan Monnier
  2009-09-24 18:53                   ` Giuseppe Scrivano
  0 siblings, 1 reply; 54+ messages in thread
From: Stefan Monnier @ 2009-09-24 17:29 UTC (permalink / raw)
  To: Giuseppe Scrivano; +Cc: Tom Tromey, Emacs development discussions

> As Tom said, I was experimenting with gnus and it made me quite
> optimistic; in fact these commands are completed successfully:

>   (run-in-thread '(gnus) t) ;; with t the thread doesn't attempt to get
>                             ;; a lock on the buffer.
>   (while (yield)) ;; yield returns nil when there are not other
>                   ;; threads -- simulate join.

That's wonderful.  Does that mean that Gnus really runs in its own
thread while you can do normal editing in other buffers?

> Following your advice to don't allow a switch only when buffer-local
> variables are let-bound by the thread, how many times it happens than a
> thread let-bound these variables?  Let's say on 100 times, how many
> times approximately do you think a switch will not be allowed and the
> calling thread blocked?

I have no idea.  I don't think the number of such situations (counted
dynamically) is very important.  What matters is the number of places in
the source code where this is problematic.


        Stefan




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-24 17:25                 ` Stefan Monnier
@ 2009-09-24 17:57                   ` Tom Tromey
  2009-09-27 20:59                   ` Tom Tromey
  1 sibling, 0 replies; 54+ messages in thread
From: Tom Tromey @ 2009-09-24 17:57 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Emacs development discussions

>>>>> "Stefan" == Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

Tom> Yeah.  What I meant here is that specbind has a little extra code in it
Tom> to install a Lisp_ThreadLocal object when needed.  So, if the C code
Tom> uses specbind to do let-like binding, everything will work fine.  If the
Tom> C code does not do this, then things will break.

Stefan> I see, yes of course it's a problem.  And it's worse than that: the same
Stefan> holds for *all* global variables, whether they are exported to Lisp
Stefan> or not.

Yes.  We move a bunch of globals into a "struct thread_state" -- specpdl
stuff, gcprolist, catchlist, etc.  I haven't yet done an audit of
globals to see whether we caught them all.  These are also redefined
using the preprocessor, e.g.:

  /* Recording what needs to be marked for gc.  */
  struct gcpro *m_gcprolist;
#define gcprolist (current_thread->m_gcprolist)

Stefan> Some goals could be:
[...]

Thanks.  That is very helpful.

I will think about your other points and reply later.

Tom




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-24 17:29                 ` Stefan Monnier
@ 2009-09-24 18:53                   ` Giuseppe Scrivano
  2009-09-24 20:04                     ` Tom Tromey
  0 siblings, 1 reply; 54+ messages in thread
From: Giuseppe Scrivano @ 2009-09-24 18:53 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Tom Tromey, Emacs development discussions

Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

>>   (run-in-thread '(gnus) t) ;; with t the thread doesn't attempt to get
>>                             ;; a lock on the buffer.
>>   (while (yield)) ;; yield returns nil when there are not other
>>                   ;; threads -- simulate join.
>
> That's wonderful.  Does that mean that Gnus really runs in its own
> thread while you can do normal editing in other buffers?

Yes, it does (except some errors).  I am concentrating all my efforts on
gnus, I think that if threads work well for gnus they will work quite
well with any other package.
At the moment it takes a lot to load folder, because there are not
enough yield on the other thread and probably gnus switch buffers too
often (causing a yield).  Still there is much to do but some results
are already visible.

Cheers,
Giuseppe




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-24 18:53                   ` Giuseppe Scrivano
@ 2009-09-24 20:04                     ` Tom Tromey
  2009-09-24 21:59                       ` Stefan Monnier
                                         ` (4 more replies)
  0 siblings, 5 replies; 54+ messages in thread
From: Tom Tromey @ 2009-09-24 20:04 UTC (permalink / raw)
  To: Giuseppe Scrivano; +Cc: Stefan Monnier, Emacs development discussions

>>>>> "Giuseppe" == Giuseppe Scrivano <gscrivano@gnu.org> writes:

>> That's wonderful.  Does that mean that Gnus really runs in its own
>> thread while you can do normal editing in other buffers?

Giuseppe> Yes, it does (except some errors).  I am concentrating all my
Giuseppe> efforts on gnus, I think that if threads work well for gnus
Giuseppe> they will work quite well with any other package.

This is awesome.

Giuseppe> At the moment it takes a lot to load folder, because there are
Giuseppe> not enough yield on the other thread and probably gnus switch
Giuseppe> buffers too often (causing a yield).

I think we need to yield when a thread is waiting for I/O.  And, we
probably need a way to associate a process filter with a thread, so that
whatever input Gnus gets is processed in the right thread.

Tom




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-24 20:04                     ` Tom Tromey
@ 2009-09-24 21:59                       ` Stefan Monnier
  2009-09-24 22:23                       ` Giuseppe Scrivano
                                         ` (3 subsequent siblings)
  4 siblings, 0 replies; 54+ messages in thread
From: Stefan Monnier @ 2009-09-24 21:59 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Giuseppe Scrivano, Emacs development discussions

>>> That's wonderful.  Does that mean that Gnus really runs in its own
>>> thread while you can do normal editing in other buffers?
Giuseppe> Yes, it does (except some errors).  I am concentrating all my
Giuseppe> efforts on gnus, I think that if threads work well for gnus
Giuseppe> they will work quite well with any other package.
> This is awesome.

Indeed.

Giuseppe> At the moment it takes a lot to load folder, because there are
Giuseppe> not enough yield on the other thread and probably gnus switch
Giuseppe> buffers too often (causing a yield).
> I think we need to yield when a thread is waiting for I/O.  And, we
> probably need a way to associate a process filter with a thread, so that
> whatever input Gnus gets is processed in the right thread.

Since process filters are currently processed "asynchronously", it would
seem like a natural idea would be to create a thread for each process,
and let that thread run all the process's filters and sentinels.

While I'm here, there's of course another relevant test case: open Emacs
on several ttys, and run some long-running commands like indent-region
in each (in different buffers at first, and then in the same one, but
on different parts of the text, ...).


        Stefan




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-24 20:04                     ` Tom Tromey
  2009-09-24 21:59                       ` Stefan Monnier
@ 2009-09-24 22:23                       ` Giuseppe Scrivano
  2009-09-24 22:47                       ` Ken Raeburn
                                         ` (2 subsequent siblings)
  4 siblings, 0 replies; 54+ messages in thread
From: Giuseppe Scrivano @ 2009-09-24 22:23 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Stefan Monnier, Emacs development discussions

Tom Tromey <tromey@redhat.com> writes:

> I think we need to yield when a thread is waiting for I/O.  And, we
> probably need a way to associate a process filter with a thread, so that
> whatever input Gnus gets is processed in the right thread.

I did some changes today.  Now a thread exits from the global lock
before calls `select' and it enters again immediately after `select'
returns, leaving other threads free to do their job.

Blocking operations affect only the caller thread.  As direct effect,
now this is enough:

  (run-in-thread '(gnus))

and gnus will be loaded in the background, without explicitly call
`yield'.

Cheers,
Giuseppe




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-24 20:04                     ` Tom Tromey
  2009-09-24 21:59                       ` Stefan Monnier
  2009-09-24 22:23                       ` Giuseppe Scrivano
@ 2009-09-24 22:47                       ` Ken Raeburn
  2009-09-28 14:52                       ` Ted Zlatanov
  2009-10-05  6:02                       ` joakim
  4 siblings, 0 replies; 54+ messages in thread
From: Ken Raeburn @ 2009-09-24 22:47 UTC (permalink / raw)
  To: Tom Tromey
  Cc: Emacs development discussions, Giuseppe Scrivano, Stefan Monnier

On Sep 24, 2009, at 16:04, Tom Tromey wrote:
>>>>>> "Giuseppe" == Giuseppe Scrivano <gscrivano@gnu.org> writes:
>
>>> That's wonderful.  Does that mean that Gnus really runs in its own
>>> thread while you can do normal editing in other buffers?
>
> Giuseppe> Yes, it does (except some errors).  I am concentrating all  
> my
> Giuseppe> efforts on gnus, I think that if threads work well for gnus
> Giuseppe> they will work quite well with any other package.
>
> This is awesome.

Yes!

It was this very problem that initially got me thinking about threads  
(and from that, it was just a hop, skip and a jump to Guile) years ago.

> Giuseppe> At the moment it takes a lot to load folder, because there  
> are
> Giuseppe> not enough yield on the other thread and probably gnus  
> switch
> Giuseppe> buffers too often (causing a yield).
>
> I think we need to yield when a thread is waiting for I/O.

Yes, I think that needs to happen pretty much automatically.  Perhaps  
it would be sufficient to make the Lisp functions that can cause  
process filters to be run also yield to other threads.

>  And, we
> probably need a way to associate a process filter with a thread, so  
> that
> whatever input Gnus gets is processed in the right thread.

Yes, and this is an area where Gnus could be changed to take advantage  
of it once the facility is a bit more stabilized.  The output from one  
NNTP server can be processed into a list of newsgroups in one thread,  
while another thread converts IMAP output into a list of mailboxes, a  
third thread talks to yet another IMAP server, etc.

It might be interesting to look at Apple's Grand Central model, and  
see if something like that is practical to use in elisp with dynamic  
bindings...

Ken




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-24 17:25                 ` Stefan Monnier
  2009-09-24 17:57                   ` Tom Tromey
@ 2009-09-27 20:59                   ` Tom Tromey
  2009-09-27 23:05                     ` Stefan Monnier
  1 sibling, 1 reply; 54+ messages in thread
From: Tom Tromey @ 2009-09-27 20:59 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Emacs development discussions

>>>>> "Stefan" == Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

[ releasing the buffer lock when yielding ]

Tom> I think this means it does not suffice to keep a simple per-thread count
Tom> of buffer-local bindings.

Stefan> Indeed.  The lock should probably be on the buffer-local binding itself
Stefan> (i.e. the combination of the buffer and the variable).

I looked into this a bit; I think it can lead to deadlock too easily:
 Thread A acquires V1 and requests V2
 Thread B acquires V2 and requests V1

Instead, I think we could remove the buffer lock.  Because we currently
use cooperative threading, most buffer operations are atomic with
respect to thread switches.  So, it seems that if we fix the bindings
problem, we can probably just remove the buffer lock.

What do you think of that?  Are there problems I've missed?

I wrote some elisp to modify the Emacs sources to use buffer accessor
macros everywhere (it handles like 90% of the references, a few tweaks
by hand are also needed).  The only thing remaining is to fix up the
swap_in_symval_forwarding logic, which we have to do anyway.

Tom




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-27 20:59                   ` Tom Tromey
@ 2009-09-27 23:05                     ` Stefan Monnier
  2009-09-28  4:27                       ` Tom Tromey
  0 siblings, 1 reply; 54+ messages in thread
From: Stefan Monnier @ 2009-09-27 23:05 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Emacs development discussions

Stefan> Indeed.  The lock should probably be on the buffer-local binding itself
Stefan> (i.e. the combination of the buffer and the variable).

> I looked into this a bit; I think it can lead to deadlock too easily:
>  Thread A acquires V1 and requests V2
>  Thread B acquires V2 and requests V1

> Instead, I think we could remove the buffer lock.  Because we currently
> use cooperative threading, most buffer operations are atomic with
> respect to thread switches.  So, it seems that if we fix the bindings
> problem, we can probably just remove the buffer lock.

Removing locks sounds like a wonderful solution, but it's dangerous.
I think you understand the danger and refer to it as "the bindings
problem".  But since I'm not sure I'll state what I think is the
problem:

thread T1 goes into buffer B and does a dynamic let-binding of
buffer-local variable X with value V1, then thread T2 does the same
thing with value V2.
What should that mean?

What should T1 see when it looks at X, V1 or V2?
What should T2 see when it looks at X, V1 or V2?
What did T2 see when it looked at X before let-binding it, V1 or V0?
What should T1 see when it looks at X after T2 ends its let-binding, V1 or V0?
What should T2 see when it looks at X after T1 ends its let-binding, V2 or V0?

You have to consider those cases and then look at existing code and see
what that code would expect.  A good variable to start with is probably
default-directory (one of the most common buffer-local-and-let-bound
variables I know of), but others need to be considered as well (I'm not
sure they'll all agree on the behavior they expect).


        Stefan


PS: Of course, similar questions arise with let-binding frame-local and
terminal-local variables, but I think these are much less common, so
it's probably OK to be less careful with them and just fix up the places
that break using explicit locks or things like that.




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-27 23:05                     ` Stefan Monnier
@ 2009-09-28  4:27                       ` Tom Tromey
  2009-09-29  0:27                         ` Stefan Monnier
  0 siblings, 1 reply; 54+ messages in thread
From: Tom Tromey @ 2009-09-28  4:27 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Emacs development discussions

Stefan> Removing locks sounds like a wonderful solution, but it's dangerous.
Stefan> I think you understand the danger and refer to it as "the bindings
Stefan> problem".  But since I'm not sure I'll state what I think is the
Stefan> problem:

Yes.  I forgot to write something important in that message, which is
what I think should happen.

Stefan> thread T1 goes into buffer B and does a dynamic let-binding of
Stefan> buffer-local variable X with value V1, then thread T2 does the same
Stefan> thing with value V2.
Stefan> What should that mean?

In my view, a let-binding should always be thread-local, and I think
buffer-localness shouldn't affect this.  This is enough of a rule to
answer your questions -- but it is just one choice, we could make
others, I suppose.

The primary reason I like this particular choice is that it seems least
susceptible to races when running ordinary lisp code in parallel.  Also,
it is simple to understand and consistent with the behavior of
non-buffer-local let-bindings.

Stefan> You have to consider those cases and then look at existing code and see
Stefan> what that code would expect.  A good variable to start with is probably
Stefan> default-directory (one of the most common buffer-local-and-let-bound
Stefan> variables I know of), but others need to be considered as well (I'm not
Stefan> sure they'll all agree on the behavior they expect).

I don't think existing code could have an expectation, simply because
existing code can't run multi-threaded.  The closest thing are process
filters, but I am not so sure that they are a good analogy in this case.

There are some oddities implied by making buffer-local let-bindings also
be thread-specific.  For example, some buffer-locals affect redisplay,
so what the user sees will depend on the thread in which redisplay is
run.

Tom




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-22 14:24             ` Stefan Monnier
                                 ` (2 preceding siblings ...)
  2009-09-23 18:43               ` Giuseppe Scrivano
@ 2009-09-28  7:44               ` Lynbech Christian
  3 siblings, 0 replies; 54+ messages in thread
From: Lynbech Christian @ 2009-09-28  7:44 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Tom Tromey, Emacs development discussions

>>>>> "Stefan" == Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

Stefan> Maybe another way to look at all these problems is to take an "agent"
Stefan> point of view: rather than threads moving around, we could consider each
Stefan> keyboard and each buffer as an active object (i.e. with its own thread),
Stefan> which communicate among each other.  I.e. a buffer-thread never leaves
Stefan> its buffer, instead it does an RPC to another buffer-thread, or to
Stefan> a keyboard-thread, ...

This seems like a really clever idea, but I didn't see any response to
it. Has anybody thought more about this?

Everything in Emacs is centered around buffers anyway and I guess that a
lot of the RPC (at least wrt. keyboards) would look a lot like the
events comming in from X anyway.

The biggest problem I see here is that you can have a large number of
buffers. I do not know what the practical limit on the number of threads
are on modern systems, but if that is a concern one could instead tie
the threads to processes/filters/sentinels (which aren't really
interactive anyway) and windows/frames which all user interaction goes
through.


------------------------+-----------------------------------------------------
Christian Lynbech       | christian #\@ defun #\. dk
------------------------+-----------------------------------------------------
Hit the philistines three times over the head with the Elisp reference manual.
                                        - petonic@hal.com (Michael A. Petonic)




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-24 20:04                     ` Tom Tromey
                                         ` (2 preceding siblings ...)
  2009-09-24 22:47                       ` Ken Raeburn
@ 2009-09-28 14:52                       ` Ted Zlatanov
  2009-10-05  6:02                       ` joakim
  4 siblings, 0 replies; 54+ messages in thread
From: Ted Zlatanov @ 2009-09-28 14:52 UTC (permalink / raw)
  To: emacs-devel

On Thu, 24 Sep 2009 14:04:22 -0600 Tom Tromey <tromey@redhat.com> wrote: 

Tom> I think we need to yield when a thread is waiting for I/O.  And, we
Tom> probably need a way to associate a process filter with a thread, so that
Tom> whatever input Gnus gets is processed in the right thread.

On Thu, 24 Sep 2009 18:47:16 -0400 Ken Raeburn <raeburn@raeburn.org> wrote: 

KR> Yes, and this is an area where Gnus could be changed to take advantage
KR> of it once the facility is a bit more stabilized.  The output from one
KR> NNTP server can be processed into a list of newsgroups in one thread,
KR> while another thread converts IMAP output into a list of mailboxes, a
KR> third thread talks to yet another IMAP server, etc.

The complications from gnus-agent, the gnus-registry, and other Gnus
elements that assume single-threading can be quite nasty.  It would
probably be productive to involve the Gnus developers (Ding Mailing List
<ding@gnus.org>).

Ted





^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-28  4:27                       ` Tom Tromey
@ 2009-09-29  0:27                         ` Stefan Monnier
  2009-09-29  2:26                           ` Ken Raeburn
  2009-09-29  2:30                           ` Tom Tromey
  0 siblings, 2 replies; 54+ messages in thread
From: Stefan Monnier @ 2009-09-29  0:27 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Emacs development discussions

> In my view, a let-binding should always be thread-local, and I think
> buffer-localness shouldn't affect this.  This is enough of a rule to
> answer your questions -- but it is just one choice, we could make
> others, I suppose.

So what should happen in the following case:
Thread A, running in buffer B1, runs the following code:

  (let ((default-directory "/foo"))
    (with-current-buffer B2 default-directory))

You seem to say that it should return "/foo", but currently it returns
something else.  Maybe we should try to come up with a run-time test to
catch such cases in current Lisp code.  A related case is when a process
filter or a sentinel is run via accept-process-output: we'd need to be
careful to make sure the code is run in the same thread as the code that
called accept-process-output.

> There are some oddities implied by making buffer-local let-bindings
> also be thread-specific.  For example, some buffer-locals affect
> redisplay, so what the user sees will depend on the thread in which
> redisplay is run.

Redisplay should be run in a completely separate thread (at least
conceptually).


        Stefan




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-29  0:27                         ` Stefan Monnier
@ 2009-09-29  2:26                           ` Ken Raeburn
  2009-09-29  3:20                             ` Stefan Monnier
  2009-09-29  3:33                             ` Tom Tromey
  2009-09-29  2:30                           ` Tom Tromey
  1 sibling, 2 replies; 54+ messages in thread
From: Ken Raeburn @ 2009-09-29  2:26 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Tom Tromey, Emacs development discussions


On Sep 28, 2009, at 20:27, Stefan Monnier wrote:

>> In my view, a let-binding should always be thread-local, and I think
>> buffer-localness shouldn't affect this.  This is enough of a rule to
>> answer your questions -- but it is just one choice, we could make
>> others, I suppose.
>
> So what should happen in the following case:
> Thread A, running in buffer B1, runs the following code:
>
>  (let ((default-directory "/foo"))
>    (with-current-buffer B2 default-directory))
>
> You seem to say that it should return "/foo", but currently it returns
> something else.  Maybe we should try to come up with a run-time test  
> to
> catch such cases in current Lisp code.

I suspect that any sensible approach we come up with is going to  
involve a change in behavior that may affect some existing code.  So  
coming up with ways to detect code that changes meaning is probably  
going to be a good idea.

>  A related case is when a process
> filter or a sentinel is run via accept-process-output: we'd need to be
> careful to make sure the code is run in the same thread as the code  
> that
> called accept-process-output.

Not necessarily; two threads could each be running helper programs in  
subprocesses (or using network connections), setting up let-bound  
variables, and calling accept-process-output, expecting the process  
filters to have access to the let-bound variables.  We might want to,  
by default, bind the filters to run only in the thread that originally  
created the process, so long as it exists.  It could be less  
efficient, but I think it might easily preserve more of the current  
behavior of packages written for single-threaded Emacs, even if they  
get run concurrently (but independently) in multiple threads.  And we  
could make it easy for code to allow other threads to process the  
output too.

>> There are some oddities implied by making buffer-local let-bindings
>> also be thread-specific.  For example, some buffer-locals affect
>> redisplay, so what the user sees will depend on the thread in which
>> redisplay is run.
>
> Redisplay should be run in a completely separate thread (at least
> conceptually).

I think it's less likely, but a package might also let-bind some  
variables that affect the display (e.g., truncate-lines, selective- 
display, show-trailing-whitespace, all of which are buffer-local, or  
anything referenced via mode-line) and then call y-or-n-p or read-file- 
name or some other routine that will trigger redisplay and prompt the  
user for some info that may depend on what's displayed....  Be that as  
it may, I think making it conceptually a separate thread is probably  
the right approach.  And this minor incompatibility is something we  
can test for now, for the most part -- if redisplay examines a Lisp  
variable, it should check for the presence of that variable in specpdl  
and cause a warning to be issued later if it's found.  (Uses of  
":eval" in mode-line-format are probably too expensive to process.)

The other approach that came to my mind was, use the context of the  
thread that's currently taking the keyboard input if there is one, to  
try to approximate the "right thing" for any code already doing what I  
described above.  (If one thread is prompting the user for input, and  
then another thread triggers redisplay but doesn't prompt for input, I  
suspect seeing what's intended by the prompting thread is probably  
more important.)  Of course that would mean that when switching which  
thread "owns" the current keyboard input, you might need to redisplay  
everything because of the change of context, or at least redisplay the  
affected buffers, which could be many of them, depending on the  
behavior of such code as:

  (let ((default-directory foo))
     (with-current buffer buf1
       (let ((default-directory bar))
          (with-current-buffer buf2
             ...repeat ad nauseam...

So... yeah, I think I like the conceptually-separate-thread approach  
better, even if it could break existing code.  I'm not certain we  
couldn't do better in terms of backwards compatibility, but it's  
simple and clean.

Ken




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-29  0:27                         ` Stefan Monnier
  2009-09-29  2:26                           ` Ken Raeburn
@ 2009-09-29  2:30                           ` Tom Tromey
  1 sibling, 0 replies; 54+ messages in thread
From: Tom Tromey @ 2009-09-29  2:30 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Emacs development discussions

Stefan> So what should happen in the following case:
Stefan> Thread A, running in buffer B1, runs the following code:

Stefan>   (let ((default-directory "/foo"))
Stefan>     (with-current-buffer B2 default-directory))

Stefan> You seem to say that it should return "/foo", but currently it returns
Stefan> something else.

I didn't mean to imply that.  I've been too terse, I'll try to expand a
bit more.

First, I think it is clear that the case where there is just a single
thread running should work exactly as elisp does today.  So, the above
will continue to work -- it has to for compatibility.

To this end, I've written a bindings test suite that is on the branch.
It is incomplete but it does test things like the above.  I'm happy to
add any tests you think appropriate to catch more possible problems.
(This is also the one piece that could probably go into trunk
immediately.)

The way ordinary variables work on the branch is, in the base case, just
like current elisp: the value is stored in Lisp_Symbol::value.  Then, if
a thread let-binds the variable, we create a struct Lisp_ThreadLocal.
This has a slot for the global (un-shadowed) value, and also an alist of
thread-local values, keyed by thread.

There are 8 other kinds of variable bindings in Emacs:

* defvaralias.  These work exactly like ordinary bindings, they
  require no change.

* objfwd.  These work exactly as above, because we wrote that "semantic
  patch" to add #defines which indirect through the Lisp_ThreadLocal,
  when needed.

* intfwd
* boolfwd.  These are not done yet.  I think I will write another
  semantic patch to handle these, like we discussed earlier.  Exactly
  what approach I'll use, I don't know... maybe make them exactly like
  objfwd and put a flag bit into Lisp_Objfwd, or keep the same structs
  and change the value's field type.

* buffer-local
* buffer-objfwd.
  Right now each of these has a single conceptual "value" field.
  (Where this is stored and how it is accessed is different in the two
  cases, but that doesn't matter.)  What I propose to do is allow the
  same sort of thread-local indirection where this value is stored, so
  that a buffer-local will have a global value and then a separate
  per-thread value in each thread that has let-bound the variable.
  I wrote the big part of this patch already (adding accessors and
  updating all the C code), all that remains is fixing up symval
  forwarding and whatnot.

* keyboard-local
* frame-local
  I haven't looked into these yet, but I assume we'll end up wanting to
  do the same as buffer-locals.

Stefan> A related case is when a process filter or a sentinel is run via
Stefan> accept-process-output: we'd need to be careful to make sure the
Stefan> code is run in the same thread as the code that called
Stefan> accept-process-output.

Yes, good point.

Tom> There are some oddities implied by making buffer-local let-bindings
Tom> also be thread-specific.  For example, some buffer-locals affect
Tom> redisplay, so what the user sees will depend on the thread in which
Tom> redisplay is run.

Stefan> Redisplay should be run in a completely separate thread (at least
Stefan> conceptually).

Yeah, that would be nice.  I don't know much about redisplay, so I don't
have much idea of how hard this would be, or what problems might arise.

Tom




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-29  2:26                           ` Ken Raeburn
@ 2009-09-29  3:20                             ` Stefan Monnier
  2009-09-29  3:57                               ` Ken Raeburn
  2009-09-29  3:33                             ` Tom Tromey
  1 sibling, 1 reply; 54+ messages in thread
From: Stefan Monnier @ 2009-09-29  3:20 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: Tom Tromey, Emacs development discussions

>> You seem to say that it should return "/foo", but currently it returns
>> something else.  Maybe we should try to come up with a run-time test to
>> catch such cases in current Lisp code.

> I suspect that any sensible approach we come up with is going to
> involve a change in behavior that may affect some existing code.  So  coming
> up with ways to detect code that changes meaning is probably  going to
> be a good idea.

Yes, that's what I meant.

>> A related case is when a process filter or a sentinel is run via
>> accept-process-output: we'd need to be careful to make sure the code
>> is run in the same thread as the code that called
>> accept-process-output.

> Not necessarily; two threads could each be running helper programs in
> subprocesses (or using network connections), setting up let-bound
> variables, and calling accept-process-output, expecting the process filters
> to have access to the let-bound variables.

I think you're thinking of the case where accept-process-output is
called without specifying any particular process to wait for, whereas
I was thinking of the case where accept-process-output is called with
a process argument.

>> Redisplay should be run in a completely separate thread (at least
>> conceptually).

> I think it's less likely, but a package might also let-bind some variables
> that affect the display (e.g., truncate-lines, selective- 
> display, show-trailing-whitespace, all of which are buffer-local, or
> anything referenced via mode-line) and then call y-or-n-p or read-file- 
> name or some other routine that will trigger redisplay and prompt the user
> for some info that may depend on what's displayed....

Yes, I know this happens with things like cursor-in-echo-area, tho this
is a global variable.  Not sure how often (or even if) this happens with
buffer-local vars. 

> So... yeah, I think I like the conceptually-separate-thread approach better,
> even if it could break existing code.  I'm not certain we couldn't do
> better in terms of backwards compatibility, but it's simple and clean.

It's improtant to maximize backward compatibility, but it's also to try
and avoid getting locked in overly complex semantics, especially in the
long run.


        Stefan




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-29  2:26                           ` Ken Raeburn
  2009-09-29  3:20                             ` Stefan Monnier
@ 2009-09-29  3:33                             ` Tom Tromey
  2009-09-29  4:07                               ` Ken Raeburn
  1 sibling, 1 reply; 54+ messages in thread
From: Tom Tromey @ 2009-09-29  3:33 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: Stefan Monnier, Emacs development discussions

>>>>> "Ken" == Ken Raeburn <raeburn@raeburn.org> writes:

Ken> I suspect that any sensible approach we come up with is going to
Ken> involve a change in behavior that may affect some existing code.  So
Ken> coming up with ways to detect code that changes meaning is probably
Ken> going to be a good idea.

It is worth noting that we don't have to solve all the problems up
front.  Since threading is a new feature, I think it is ok to say that
code running in a "secondary" thread might have to follow some special
rules, or that some things (e.g., let-binding something then redisplay)
may only work in the "main" thread.  These restrictions could then maybe
be lifted later.

Ken> We might want to, by default, bind the filters to run only in the
Ken> thread that originally created the process, so long as it exists.

We can also add a new process attribute controlling this.

Tom




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-29  3:20                             ` Stefan Monnier
@ 2009-09-29  3:57                               ` Ken Raeburn
  0 siblings, 0 replies; 54+ messages in thread
From: Ken Raeburn @ 2009-09-29  3:57 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Tom Tromey, Emacs development discussions

On Sep 28, 2009, at 23:20, Stefan Monnier wrote:
> I think you're thinking of the case where accept-process-output is
> called without specifying any particular process to wait for, whereas
> I was thinking of the case where accept-process-output is called with
> a process argument.

True.  Well, more specifically, if the just-this-one flag is set, too,  
then my concern goes away.  Just specifying the process doesn't mean  
that output from another process won't get, uh, processed, during a  
call.  Given the single-threaded nature of elisp now, I doubt most  
uses are likely to set the flag.  In fact a quick grep over the top- 
level lisp sources shows most calls there just specify the process and  
timeout.

(Oh... hm, timers.  Same issues, also probably unlikely to be a  
problem in most cases.)

Ken




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-29  3:33                             ` Tom Tromey
@ 2009-09-29  4:07                               ` Ken Raeburn
  0 siblings, 0 replies; 54+ messages in thread
From: Ken Raeburn @ 2009-09-29  4:07 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Stefan Monnier, Emacs development discussions

On Sep 28, 2009, at 23:33, Tom Tromey wrote:
> It is worth noting that we don't have to solve all the problems up
> front.  Since threading is a new feature, I think it is ok to say that
> code running in a "secondary" thread might have to follow some special
> rules, or that some things (e.g., let-binding something then  
> redisplay)
> may only work in the "main" thread.  These restrictions could then  
> maybe
> be lifted later.

True.  And as long as it's not yet folded into an Emacs release, we  
can also alter behavior, impose new restrictions, etc., as it gets  
exercised and we learn better about compatibility issues we might've  
overlooked.

Ken




^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: advice needed for multi-threading patch
  2009-09-24 20:04                     ` Tom Tromey
                                         ` (3 preceding siblings ...)
  2009-09-28 14:52                       ` Ted Zlatanov
@ 2009-10-05  6:02                       ` joakim
  4 siblings, 0 replies; 54+ messages in thread
From: joakim @ 2009-10-05  6:02 UTC (permalink / raw)
  To: Tom Tromey
  Cc: Emacs development discussions, Giuseppe Scrivano, Stefan Monnier

Tom Tromey <tromey@redhat.com> writes:

>>>>>> "Giuseppe" == Giuseppe Scrivano <gscrivano@gnu.org> writes:
>
>>> That's wonderful.  Does that mean that Gnus really runs in its own
>>> thread while you can do normal editing in other buffers?
>
> Giuseppe> Yes, it does (except some errors).  I am concentrating all my
> Giuseppe> efforts on gnus, I think that if threads work well for gnus
> Giuseppe> they will work quite well with any other package.
>
> This is awesome.
>
> Giuseppe> At the moment it takes a lot to load folder, because there are
> Giuseppe> not enough yield on the other thread and probably gnus switch
> Giuseppe> buffers too often (causing a yield).
>
> I think we need to yield when a thread is waiting for I/O.  And, we
> probably need a way to associate a process filter with a thread, so that
> whatever input Gnus gets is processed in the right thread.

How will the threading patch work for something like Eshell and Dired?
Non blocking file operations would be a major improvement IMHO.



> Tom
>
-- 
Joakim Verona




^ permalink raw reply	[flat|nested] 54+ messages in thread

end of thread, other threads:[~2009-10-05  6:02 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-26  4:38 advice needed for multi-threading patch Tom Tromey
2009-08-26  7:06 ` Ken Raeburn
2009-08-26 14:52   ` Stefan Monnier
2009-08-26 18:50     ` Ken Raeburn
2009-08-27  3:12       ` Stefan Monnier
2009-08-27  6:28         ` Ken Raeburn
2009-08-27 17:02           ` Stefan Monnier
2009-08-26 16:08   ` Tom Tromey
2009-08-26 18:50     ` Ken Raeburn
2009-08-27  5:07       ` Miles Bader
2009-08-27  6:39         ` Ken Raeburn
2009-08-27  6:50           ` Miles Bader
2009-08-28 20:48             ` Juri Linkov
2009-08-28 22:15               ` Miles Bader
2009-08-28 23:27                 ` Juri Linkov
2009-08-28 23:54                   ` Miles Bader
2009-08-29 20:21                 ` Richard Stallman
2009-08-26 15:02 ` Stefan Monnier
2009-08-26 15:31   ` Tom Tromey
2009-08-26 19:18     ` Stefan Monnier
2009-09-18 22:59       ` Tom Tromey
2009-09-19  0:09         ` Stephen J. Turnbull
2009-09-19  0:32         ` Chong Yidong
2009-09-21 21:19         ` Stefan Monnier
2009-09-21 21:50           ` Tom Tromey
2009-09-22 14:24             ` Stefan Monnier
2009-09-22 23:59               ` Ken Raeburn
2009-09-23  3:11                 ` Stefan Monnier
2009-09-23 15:53                 ` Chong Yidong
2009-09-23  3:16               ` Tom Tromey
2009-09-24 17:25                 ` Stefan Monnier
2009-09-24 17:57                   ` Tom Tromey
2009-09-27 20:59                   ` Tom Tromey
2009-09-27 23:05                     ` Stefan Monnier
2009-09-28  4:27                       ` Tom Tromey
2009-09-29  0:27                         ` Stefan Monnier
2009-09-29  2:26                           ` Ken Raeburn
2009-09-29  3:20                             ` Stefan Monnier
2009-09-29  3:57                               ` Ken Raeburn
2009-09-29  3:33                             ` Tom Tromey
2009-09-29  4:07                               ` Ken Raeburn
2009-09-29  2:30                           ` Tom Tromey
2009-09-23 18:43               ` Giuseppe Scrivano
2009-09-24 17:29                 ` Stefan Monnier
2009-09-24 18:53                   ` Giuseppe Scrivano
2009-09-24 20:04                     ` Tom Tromey
2009-09-24 21:59                       ` Stefan Monnier
2009-09-24 22:23                       ` Giuseppe Scrivano
2009-09-24 22:47                       ` Ken Raeburn
2009-09-28 14:52                       ` Ted Zlatanov
2009-10-05  6:02                       ` joakim
2009-09-28  7:44               ` Lynbech Christian
2009-08-29  0:28 ` Giuseppe Scrivano
2009-08-29  4:57   ` Tom Tromey

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).