From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Philipp Stephani
On 10/04/2015 01:57 AM, Philipp Stephani wrote:
> Daniel Colascione <dancol@dancol.org <mailto:dancol@dancol.org>> schrieb
> am So., 15. Feb. 2015 um 21:21 Uhr:
>
>=C2=A0 =C2=A0 =C2=A0Here's a broad outline of what I have in mind.<= br> >
>
> Thanks, that looks really good. Just a few minor issues that I
> encountered over the last couple of weeks.
>
>
>=C2=A0 =C2=A0 =C2=A0Thread-local environments
>=C2=A0 =C2=A0 =C2=A0-------------------------
>
>=C2=A0 =C2=A0 =C2=A0The `get_environment' member lets us do anythin= g else interesting. As
>=C2=A0 =C2=A0 =C2=A0in Java, environments are thread-local. We only sup= port one thread for
>=C2=A0 =C2=A0 =C2=A0the moment, so this constraint is easy to enforce. = (Just abort if we
>=C2=A0 =C2=A0 =C2=A0use an emacs_env off the main thread.)
>
>
> Would you really abort, or rather use the error handling functions? We=
> should be able to make the error values thread-local so that calling a=
> function from the wrong thread would be the equivalent of raising a
> signal, giving the caller a chance to react. Otherwise the burden of > remembering the correct thread would be on the caller's side.
If we abort, thread mismatch is a programming error, and we can omit
optionally the check for performance. If we fail in some recoverable
way, we have to perform the thread check every time, since it's now
contractual.
>
>
>=C2=A0 =C2=A0 =C2=A0 =C2=A0typedef struct emacs_value_tag* emacs_value;=
>
>
> I think it's important that this is a pointer to a struct (for typ= e
> safety and size correctness) rather than just an arbitrary type.
A typedef is exactly as typesafe. The question of whether to use a
struct or a typedef is aesthetic. I strongly prefer a typedef, just like
pthreads, and I believe that the people who advocate using structs
directly are simply wrong.
= >=C2=A0 =C2=A0 =C2=A0Modules can use make_global_reference to allocate a= global reference
>=C2=A0 =C2=A0 =C2=A0(i.e., a GC root) for any emacs_value; modules must= then free these
>=C2=A0 =C2=A0 =C2=A0references explicitly.
>
>=C2=A0 =C2=A0 =C2=A0All routines (except make_global_reference) that re= turn emacs_value
>=C2=A0 =C2=A0 =C2=A0values return local references.=C2=A0 It's up t= o modules to register
>=C2=A0 =C2=A0 =C2=A0long-lived references explicitly.
>
>
> In which cases would global references be necessary?
Any time you want to hold onto a lisp value outside the dynamic extent
of your emacs_env.
>=C2=A0 =C2=A0 =C2=A0Like JNI, we can just declare that it's illegal= to call all but a few
>=C2=A0 =C2=A0 =C2=A0specially-marked functions (like global reference d= eregistration) with
>=C2=A0 =C2=A0 =C2=A0a pending error.
>
>
> What's the behavior if other functions are called? abort()?
abort in check mode; unspecified when optimizing for performance.OK, makes sense. Probably it should be abort() i= n all cases right now, the test should be really fast.=C2=A0= div> --047d7b5d5896db09880521443248--=
>
>
>=C2=A0 =C2=A0 =C2=A0If Lisp signals or throws, `funcall' returns NU= LL.
>
>
> Hmm, with the current implementation emacs_value is just the same as > Lisp_Object, i.e. not a real pointer, so NULL doesn't have specifi= c
> semantics. Should it return Qnil instead and force the user to use
> check_error?
I thought we make Qnil equal zero. In any case, I *don't* like the idea=
of Lisp_Object being emacs_value. I'd much rather emacs_value be a
pointer to a Lisp_Object, solving this problem completely.I agree with you, but that's how it's currently= implemented.=C2=A0
>=C2=A0 =C2=A0 =C2=A03) How exactly do we represent catch/throw values?<= br> >
>
> I've thought about this a bit, and I think it would be simplest to= add a
> new function env->set_throw and have get_error and check_error retu= rn an
> enum { normal, signal, throw }. One could come up with something like<= br> > creating a list (error-kind error-tag error-value), but it looks like<= br> > the module implementation would create such lists only for the module<= br> > code to convert them back, so it's simpler to represent the two ki= nds of
> non-local exits directly in the interface.
I'm fine with a list; keep in mind that we'll need to handle OOM
somehow, so I'd suggest an opaque type.=I think OOM is currently handled by doing the equivalent of=C2=A0(apply #'signal memory-signal-data)
=so it would be part of the normal signal handling. Using a list = would be possible, but then the distinction between error tag and data coul= d be removed from the module code. But I think the 'magic lists' id= iom common in Emacs is more of an antipattern and we should try to avoid it= in the module interface, thus the suggestion to use an enum.=C2= =A0
>=C2=A0 =C2=A0 =C2=A04) Do we need to use int64_t for integers?
>
>
> Maybe just intmax_t and a static check that that is larger than an Eli= sp
> integer?
Why make the behavior vary depending on what intmax_t is? At least
int64_t is nice and explicit.
True. The time when Emacs integers wil= l be larger than 64 bits is probably far in the future.=C2=A0