* Lisp object that refers to a C struct @ 2012-10-15 21:24 Eli Zaretskii 2012-10-16 1:07 ` Stefan Monnier 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2012-10-15 21:24 UTC (permalink / raw) To: emacs-devel What is the recommended method of getting a Lisp object that represents a C struct? It seems like a pseudo-vector is used for this, but in my case it looks like an overkill: my struct has no Lisp members. All I need is a Lisp object that will serve as descriptor for the struct, and that can be used to extract a pointer to the struct, for C code to access that struct. There's Lisp_Save_Value, which looks very promising, but why does its documentation say it's for record_unwind_protect? Is there anything in it which would preclude its use outside unwinding? ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-15 21:24 Lisp object that refers to a C struct Eli Zaretskii @ 2012-10-16 1:07 ` Stefan Monnier 2012-10-16 3:53 ` Eli Zaretskii 0 siblings, 1 reply; 39+ messages in thread From: Stefan Monnier @ 2012-10-16 1:07 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel > It seems like a pseudo-vector is used for this, but in my case it > looks like an overkill: my struct has no Lisp members. You can use either a pseudo-vector, or s Lisp_Misc. > There's Lisp_Save_Value, which looks very promising, Lisp_Save_Value is a Lisp_Misc. > but why does its documentation say it's for record_unwind_protect? > Is there anything in it which would preclude its use > outside unwinding? It doesn't look very pretty when printed, so it's generally better not to expose it to users too much. If your value will usually not be visible to Elisp code, then Lisp_Save_Value is perfectly fine. Otherwise, better define your own type so that its printed representation can be more helpful, indicating what it's used for (I presume it's for a file-watch-descriptor). Stefan ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-16 1:07 ` Stefan Monnier @ 2012-10-16 3:53 ` Eli Zaretskii 2012-10-16 13:11 ` Stefan Monnier 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2012-10-16 3:53 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: emacs-devel@gnu.org > Date: Mon, 15 Oct 2012 21:07:21 -0400 > > > There's Lisp_Save_Value, which looks very promising, > > Lisp_Save_Value is a Lisp_Misc. > > > but why does its documentation say it's for record_unwind_protect? > > Is there anything in it which would preclude its use > > outside unwinding? > > It doesn't look very pretty when printed, so it's generally better not > to expose it to users too much. If your value will usually not be > visible to Elisp code, then Lisp_Save_Value is perfectly fine. OK. > Otherwise, better define your own type so that its printed > representation can be more helpful, indicating what it's used for How do I define my own type? In particular, what to do with gcmarkbit in Lisp_Misc? > (I presume it's for a file-watch-descriptor). Yes. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-16 3:53 ` Eli Zaretskii @ 2012-10-16 13:11 ` Stefan Monnier 2012-10-16 17:22 ` Eli Zaretskii 0 siblings, 1 reply; 39+ messages in thread From: Stefan Monnier @ 2012-10-16 13:11 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel >> Otherwise, better define your own type so that its printed >> representation can be more helpful, indicating what it's used for > How do I define my own type? Either by adding one more lisp_misc or one more pseudovector. For either of them, you need to add the corresponding new tag to their enumeration (Lisp_Misc_Type or pvec_type). For lisp_misc you additionally need to add your entry to the union type (but make sure the first word has the same structure as the others, starting with a 16bit type and a 1bit markbit) and make sure the overall size of the union type is not increased. Then you need to add the corresponding switch branches in print.c and in alloc.c. > In particular, what to do with gcmarkbit in Lisp_Misc? The markbit represents whether or not the object you created was found by the tracing GC, so just set it like we do for the other types. The other question is "when should we free the C struct to which this new lisp_misc points"? And that depends. You could have the GC free it when it finds your lisp_misc can be freed, or you could have instead a notion of "deleted file-watcher" (like we have for buffers/windows/...) which is when the underlying C struct has been freed (but of course, this state needs to be represented, e.g. by setting the pointer to NULL, which means that you need to be able to enumerate all the file-watcher objects (or the only one, if you enforce there can only be one) corresponding to a particular C struct). Stefan ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-16 13:11 ` Stefan Monnier @ 2012-10-16 17:22 ` Eli Zaretskii 2012-10-16 21:43 ` Stefan Monnier 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2012-10-16 17:22 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: emacs-devel@gnu.org > Date: Tue, 16 Oct 2012 09:11:25 -0400 > > >> Otherwise, better define your own type so that its printed > >> representation can be more helpful, indicating what it's used for > > How do I define my own type? > > Either by adding one more lisp_misc or one more pseudovector. > For either of them, you need to add the corresponding new tag to their > enumeration (Lisp_Misc_Type or pvec_type). For lisp_misc you > additionally need to add your entry to the union type (but make sure > the first word has the same structure as the others, starting with > a 16bit type and a 1bit markbit) and make sure the overall size of the > union type is not increased. > > Then you need to add the corresponding switch branches in print.c and in > alloc.c. Can I just use PVEC_OTHER instead? In any case, which one, pseudovector or misc, is better suited for this particular job, in your opinion? What would you use? > > In particular, what to do with gcmarkbit in Lisp_Misc? > > The markbit represents whether or not the object you created was found > by the tracing GC, so just set it like we do for the other types. > > The other question is "when should we free the C struct to which this > new lisp_misc points"? And that depends. You could have the GC free it > when it finds your lisp_misc can be freed, or you could have instead > a notion of "deleted file-watcher" (like we have for > buffers/windows/...) which is when the underlying C struct has been > freed (but of course, this state needs to be represented, e.g. by > setting the pointer to NULL, which means that you need to be able to > enumerate all the file-watcher objects (or the only one, if you enforce > there can only be one) corresponding to a particular C struct). This sounds dangerous in my case. The struct holds crucial data used by a separate thread which watches the changes and receives notifications. It is unthinkable to let any code outside of the one specifically written for this to free that struct, because the associated thread will go down in flames and take Emacs with it. There's special code (already written and tested) that takes care of shutting down the watcher thread and freeing the associated resources in an orderly way. That code must be run whenever the object is GC'ed, at the very least. It would be even better not to leave this to GC at all, but instead delete the object whenever the watch is canceled, since otherwise we leave behind a thread that does nothing except wasting system resources, for a time interval whose length cannot be predicted or controlled. Is there a clean way of doing that? P.S. I must say that the more I learn about the "make your own object" path the less I like it. In the case in point, it sounds like pure overhead, with no benefits at all. To do everything I need with the watcher struct, all I need is a pointer to it, which can easily be disguised as a Lisp integer. (This is how the code actually works now.) Such a "handle" will be barely visible to Lisp, its only use is to cancel an existing watch, or examine its associated file name and the details of the watch request (which _are_ Lisp objects). There's no need to manage the struct itself, as it already manages itself. But look what I need to do just to produce a first-class Lisp object from it. And I still don't see what would be the benefits. E.g., a Lisp integer prints quite nicely; something like "#<watch 12345678>" doesn't seem significantly prettier. What am I missing? ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-16 17:22 ` Eli Zaretskii @ 2012-10-16 21:43 ` Stefan Monnier 2012-10-17 4:05 ` Eli Zaretskii 2012-10-17 16:05 ` Eli Zaretskii 0 siblings, 2 replies; 39+ messages in thread From: Stefan Monnier @ 2012-10-16 21:43 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel >> Then you need to add the corresponding switch branches in print.c and in >> alloc.c. > Can I just use PVEC_OTHER instead? No, for the same reason as Lisp_Save_Value: you can't give a nice printed representation. > In any case, which one, pseudovector or misc, is better suited for > this particular job, in your opinion? What would you use? I guess I'd go with the Lisp_Misc. >> The other question is "when should we free the C struct to which this >> new lisp_misc points"? And that depends. You could have the GC free it >> when it finds your lisp_misc can be freed, or you could have instead >> a notion of "deleted file-watcher" (like we have for >> buffers/windows/...) which is when the underlying C struct has been >> freed (but of course, this state needs to be represented, e.g. by >> setting the pointer to NULL, which means that you need to be able to >> enumerate all the file-watcher objects (or the only one, if you enforce >> there can only be one) corresponding to a particular C struct). > This sounds dangerous in my case. Of course, but it's unavoidable: you want to export to Elisp a pointer to a C struct. So you have to deal with the two risks: failing to free the object, and having Elisp code use the object after it was freed. > notifications. It is unthinkable to let any code outside of the one > specifically written for this to free that struct, because the > associated thread will go down in flames and take Emacs with it. Of course. The code to free the C struct will be the one you write specifically for it, nobody else knows how to free it. > That code must be run whenever the object is GC'ed, at the very least. > It would be even better not to leave this to GC at all, but instead > delete the object whenever the watch is canceled, since otherwise we > leave behind a thread that does nothing except wasting system > resources, for a time interval whose length cannot be predicted > or controlled. If you make sure there's at most 1 file-watcher object per C struct, then you can easily zero-out its pointer-field after freeing the C struct, so you can make sure you protect yourself from dangling pointers. And if you make sure the GC calls you back when freeing the file-watcher, then you can make sure that you don't leak the C structs. > Is there a clean way of doing that? AFAIK this *is* the clean way. > pure overhead, with no benefits at all. To do everything I need with > the watcher struct, all I need is a pointer to it, which can easily be > disguised as a Lisp integer. (This is how the code actually works > now.) What happens if someone passes you this same integer some time after you've freed the C struct? Stefan ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-16 21:43 ` Stefan Monnier @ 2012-10-17 4:05 ` Eli Zaretskii 2012-10-17 6:21 ` Stephen J. Turnbull 2012-10-17 13:34 ` Stefan Monnier 2012-10-17 16:05 ` Eli Zaretskii 1 sibling, 2 replies; 39+ messages in thread From: Eli Zaretskii @ 2012-10-17 4:05 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: emacs-devel@gnu.org > Date: Tue, 16 Oct 2012 17:43:26 -0400 > > > pure overhead, with no benefits at all. To do everything I need with > > the watcher struct, all I need is a pointer to it, which can easily be > > disguised as a Lisp integer. (This is how the code actually works > > now.) > > What happens if someone passes you this same integer some time after > you've freed the C struct? It won't be found in the list of watches, so the command to remove that watch will say "Invalid watch descriptor", and Lisp-level code will not find the corresponding Lisp data structure. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-17 4:05 ` Eli Zaretskii @ 2012-10-17 6:21 ` Stephen J. Turnbull 2012-10-17 15:50 ` Eli Zaretskii 2012-10-17 13:34 ` Stefan Monnier 1 sibling, 1 reply; 39+ messages in thread From: Stephen J. Turnbull @ 2012-10-17 6:21 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Stefan Monnier, emacs-devel Eli Zaretskii writes: > > What happens if someone passes you this same integer some time after > > you've freed the C struct? More interesting, what happens if somebody chooses "I feel lucky" and passes you a random integer that happens to be a "live" watch? ISTM it fails safe (ie, doesn't crash). But it's not good. So really you want this to be entirely internal somehow. The only way to do that is to have an opaque type that you can only get a pointer to from the watch constructor. All-I-need-to-know-about-ABCs-I-learned-in-kindergarten-ly y'rs, ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-17 6:21 ` Stephen J. Turnbull @ 2012-10-17 15:50 ` Eli Zaretskii 2012-10-17 17:45 ` Stephen J. Turnbull 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2012-10-17 15:50 UTC (permalink / raw) To: Stephen J. Turnbull; +Cc: monnier, emacs-devel > From: "Stephen J. Turnbull" <stephen@xemacs.org> > Cc: Stefan Monnier <monnier@iro.umontreal.ca>, > emacs-devel@gnu.org > Date: Wed, 17 Oct 2012 15:21:40 +0900 > > Eli Zaretskii writes: > > > > What happens if someone passes you this same integer some time after > > > you've freed the C struct? > > More interesting, what happens if somebody chooses "I feel lucky" and > passes you a random integer that happens to be a "live" watch? I don't follow: what do you mean "somebody passes me a random integer"? There are only 2 APIs that expose this integer to Lisp: one that starts watching for file changes, and another that cancels an existing watch. The former returns the integer we are talking about, the latter accepts that integer and uses it to access the underlying C struct, shut down the thread that was doing the watch, and delete the struct and all the other resources the watch was using. So if they pass me the integer that happens to reference a live watch, they can only do that through the "remove" API, in which case the watch will stop. Or did you mean something else? > ISTM it fails safe (ie, doesn't crash). It's fail-safe, yes (well, barring bugs ;-). > But it's not good. Why not? If a luser asked to shut down a watch, and just "happened" to specify a live one, she gets what she asked for. It's not like Emacs _needs_ those watches for some of its internal workings. > So really you want this to be entirely internal somehow. The only > way to do that is to have an opaque type that you can only get a > pointer to from the watch constructor. I don't think we have opaque data types in Emacs. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-17 15:50 ` Eli Zaretskii @ 2012-10-17 17:45 ` Stephen J. Turnbull 0 siblings, 0 replies; 39+ messages in thread From: Stephen J. Turnbull @ 2012-10-17 17:45 UTC (permalink / raw) To: Eli Zaretskii; +Cc: monnier, emacs-devel Eli Zaretskii writes: > I don't follow: what do you mean "somebody passes me a random > integer"? [...] > So if they pass me the integer that happens to reference a live watch, > they can only do that through the "remove" API, in which case the > watch will stop. You got it. > Why not? If a luser asked to shut down a watch, and just "happened" > to specify a live one, she gets what she asked for. It's not like > Emacs _needs_ those watches for some of its internal workings. It doesn't now, no. > > So really you want this to be entirely internal somehow. The only > > way to do that is to have an opaque type that you can only get a > > pointer to from the watch constructor. > > I don't think we have opaque data types in Emacs. Of course we do. Starting with `cons'. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-17 4:05 ` Eli Zaretskii 2012-10-17 6:21 ` Stephen J. Turnbull @ 2012-10-17 13:34 ` Stefan Monnier 2012-10-17 16:08 ` Eli Zaretskii 1 sibling, 1 reply; 39+ messages in thread From: Stefan Monnier @ 2012-10-17 13:34 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel >> What happens if someone passes you this same integer some time after >> you've freed the C struct? > It won't be found in the list of watches, so the command to remove > that watch will say "Invalid watch descriptor", and Lisp-level code > will not find the corresponding Lisp data structure. So the integer doesn't encode the pointer, instead it's an index into a table of C structs. Like POSIX file-descriptors. That would work, of course. Stefan ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-17 13:34 ` Stefan Monnier @ 2012-10-17 16:08 ` Eli Zaretskii 2012-10-17 20:23 ` Stefan Monnier 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2012-10-17 16:08 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel > From: Stefan Monnier <monnier@IRO.UMontreal.CA> > Cc: emacs-devel@gnu.org > Date: Wed, 17 Oct 2012 09:34:40 -0400 > > >> What happens if someone passes you this same integer some time after > >> you've freed the C struct? > > It won't be found in the list of watches, so the command to remove > > that watch will say "Invalid watch descriptor", and Lisp-level code > > will not find the corresponding Lisp data structure. > > So the integer doesn't encode the pointer, instead it's an index into > a table of C structs. No, I have no table right now. I could add one, of course. Right now, the struct is allocated and its pointer is put into an alist as a Lisp integer, and also returned, as a Lisp integer, to the caller of the "start-watching" API. The caller is supposed to manage her watches, and pass the right integer when she wants to cancel a watch. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-17 16:08 ` Eli Zaretskii @ 2012-10-17 20:23 ` Stefan Monnier 2012-10-17 20:46 ` Eli Zaretskii 0 siblings, 1 reply; 39+ messages in thread From: Stefan Monnier @ 2012-10-17 20:23 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel > Right now, the struct is allocated and its pointer is put into an > alist as a Lisp integer, How do you convert the integer into the C struct pointer? Stefan ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-17 20:23 ` Stefan Monnier @ 2012-10-17 20:46 ` Eli Zaretskii 2012-10-17 22:08 ` Paul Eggert 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2012-10-17 20:46 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: emacs-devel@gnu.org > Date: Wed, 17 Oct 2012 16:23:19 -0400 > > > Right now, the struct is allocated and its pointer is put into an > > alist as a Lisp integer, > > How do you convert the integer into the C struct pointer? struct foo *pwatch = (struct foo *)XLI (watch_descriptor); where watch_descriptor is a Lisp integer. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-17 20:46 ` Eli Zaretskii @ 2012-10-17 22:08 ` Paul Eggert 2012-10-18 0:22 ` Stefan Monnier 2012-10-18 4:50 ` Eli Zaretskii 0 siblings, 2 replies; 39+ messages in thread From: Paul Eggert @ 2012-10-17 22:08 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel On 10/17/2012 01:46 PM, Eli Zaretskii wrote: >> How do you convert the integer into the C struct pointer? > struct foo *pwatch = (struct foo *)XLI (watch_descriptor); > > where watch_descriptor is a Lisp integer. Won't this have problems on platforms where (EMACS_INT) pwatch < MOST_NEGATIVE_FIXNUM, or where MOST_POSITIVE_FIXNUM < (EMACS_INT) pwatch? Also, suppose someone makes up a random integer and then passes it as the watch descriptor -- wouldn't Emacs dump core? ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-17 22:08 ` Paul Eggert @ 2012-10-18 0:22 ` Stefan Monnier 2012-10-18 3:43 ` Stephen J. Turnbull 2012-10-18 4:50 ` Eli Zaretskii 1 sibling, 1 reply; 39+ messages in thread From: Stefan Monnier @ 2012-10-18 0:22 UTC (permalink / raw) To: Paul Eggert; +Cc: Eli Zaretskii, emacs-devel > Also, suppose someone makes up a random integer > and then passes it as the watch descriptor -- > wouldn't Emacs dump core? That's what I was getting at. Stefan ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-18 0:22 ` Stefan Monnier @ 2012-10-18 3:43 ` Stephen J. Turnbull 0 siblings, 0 replies; 39+ messages in thread From: Stephen J. Turnbull @ 2012-10-18 3:43 UTC (permalink / raw) To: Stefan Monnier; +Cc: Eli Zaretskii, Paul Eggert, emacs-devel Stefan Monnier writes: > > Also, suppose someone makes up a random integer > > and then passes it as the watch descriptor -- > > wouldn't Emacs dump core? > > That's what I was getting at. I inferred that Eli is already checking it against a list of active watches (ie, will "fail safe"); otherwise, you could dump core on a double free anyway. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-17 22:08 ` Paul Eggert 2012-10-18 0:22 ` Stefan Monnier @ 2012-10-18 4:50 ` Eli Zaretskii 2012-10-18 7:20 ` Paul Eggert 2012-10-18 8:52 ` Juanma Barranquero 1 sibling, 2 replies; 39+ messages in thread From: Eli Zaretskii @ 2012-10-18 4:50 UTC (permalink / raw) To: Paul Eggert; +Cc: emacs-devel > Date: Wed, 17 Oct 2012 15:08:52 -0700 > From: Paul Eggert <eggert@cs.ucla.edu> > CC: emacs-devel@gnu.org > > On 10/17/2012 01:46 PM, Eli Zaretskii wrote: > >> How do you convert the integer into the C struct pointer? > > struct foo *pwatch = (struct foo *)XLI (watch_descriptor); > > > > where watch_descriptor is a Lisp integer. > > Won't this have problems on platforms where > (EMACS_INT) pwatch < MOST_NEGATIVE_FIXNUM, > or where MOST_POSITIVE_FIXNUM < (EMACS_INT) pwatch? Given what XLI does, I don't see how this could happen, with watch_descriptor being a Lisp integer. > Also, suppose someone makes up a random integer > and then passes it as the watch descriptor -- > wouldn't Emacs dump core? No, because, like Stephen says, the descriptor is first validated against a list of known ones. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-18 4:50 ` Eli Zaretskii @ 2012-10-18 7:20 ` Paul Eggert 2012-10-18 11:09 ` Eli Zaretskii 2012-10-18 8:52 ` Juanma Barranquero 1 sibling, 1 reply; 39+ messages in thread From: Paul Eggert @ 2012-10-18 7:20 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel On 10/17/2012 09:50 PM, Eli Zaretskii wrote: >> Won't this have problems on platforms where >> > (EMACS_INT) pwatch < MOST_NEGATIVE_FIXNUM, >> > or where MOST_POSITIVE_FIXNUM < (EMACS_INT) pwatch? > Given what XLI does, I don't see how this could happen To be honest I haven't followed all the back-and-forth on this, but in general it's not safe to convert a pointer to an Emacs fixnum, as this can lose information: the payload of an Emacs fixnum is typically narrower than a pointer. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-18 7:20 ` Paul Eggert @ 2012-10-18 11:09 ` Eli Zaretskii 2012-10-18 16:42 ` Paul Eggert 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2012-10-18 11:09 UTC (permalink / raw) To: Paul Eggert; +Cc: emacs-devel > Date: Thu, 18 Oct 2012 00:20:11 -0700 > From: Paul Eggert <eggert@cs.ucla.edu> > CC: emacs-devel@gnu.org > > On 10/17/2012 09:50 PM, Eli Zaretskii wrote: > >> Won't this have problems on platforms where > >> > (EMACS_INT) pwatch < MOST_NEGATIVE_FIXNUM, > >> > or where MOST_POSITIVE_FIXNUM < (EMACS_INT) pwatch? > > > Given what XLI does, I don't see how this could happen > > To be honest I haven't followed all the back-and-forth on this, > but in general it's not safe to convert a pointer to > an Emacs fixnum, as this can lose information: the payload > of an Emacs fixnum is typically narrower than a pointer. A pointer that is properly aligned has no problem with this. After all, that's how we produce every Lisp object out of a pointer. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-18 11:09 ` Eli Zaretskii @ 2012-10-18 16:42 ` Paul Eggert 2012-10-18 17:21 ` Eli Zaretskii 0 siblings, 1 reply; 39+ messages in thread From: Paul Eggert @ 2012-10-18 16:42 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel On 10/18/2012 04:09 AM, Eli Zaretskii wrote: >> but in general it's not safe to convert a pointer to >> > an Emacs fixnum, as this can lose information: the payload >> > of an Emacs fixnum is typically narrower than a pointer. > A pointer that is properly aligned has no problem with this. It can have problems on hosts where USE_LSB_TAG is 0, because the conversion to Emacs fixnum can lose high-order bits in the pointer. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-18 16:42 ` Paul Eggert @ 2012-10-18 17:21 ` Eli Zaretskii 0 siblings, 0 replies; 39+ messages in thread From: Eli Zaretskii @ 2012-10-18 17:21 UTC (permalink / raw) To: Paul Eggert; +Cc: emacs-devel > Date: Thu, 18 Oct 2012 09:42:14 -0700 > From: Paul Eggert <eggert@cs.ucla.edu> > CC: emacs-devel@gnu.org > > On 10/18/2012 04:09 AM, Eli Zaretskii wrote: > >> but in general it's not safe to convert a pointer to > >> > an Emacs fixnum, as this can lose information: the payload > >> > of an Emacs fixnum is typically narrower than a pointer. > > A pointer that is properly aligned has no problem with this. > > It can have problems on hosts where USE_LSB_TAG is 0, > because the conversion to Emacs fixnum can lose high-order > bits in the pointer. We are talking about Windows-specific code, so I don't think this danger is real. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-18 4:50 ` Eli Zaretskii 2012-10-18 7:20 ` Paul Eggert @ 2012-10-18 8:52 ` Juanma Barranquero 2012-10-18 11:17 ` Eli Zaretskii 1 sibling, 1 reply; 39+ messages in thread From: Juanma Barranquero @ 2012-10-18 8:52 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Paul Eggert, emacs-devel On Thu, Oct 18, 2012 at 6:50 AM, Eli Zaretskii <eliz@gnu.org> wrote: > No, because, like Stephen says, the descriptor is first validated > against a list of known ones. In that case, wouldn't it be better to have the integer be an index into a table, like Stefan suggested? It's faster to check that it is in range than compare it with an arbitrarily long list of known pointers. Juanma ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-18 8:52 ` Juanma Barranquero @ 2012-10-18 11:17 ` Eli Zaretskii 2012-10-18 12:33 ` Stefan Monnier 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2012-10-18 11:17 UTC (permalink / raw) To: Juanma Barranquero; +Cc: eggert, emacs-devel > From: Juanma Barranquero <lekktu@gmail.com> > Date: Thu, 18 Oct 2012 10:52:21 +0200 > Cc: Paul Eggert <eggert@cs.ucla.edu>, emacs-devel@gnu.org > > On Thu, Oct 18, 2012 at 6:50 AM, Eli Zaretskii <eliz@gnu.org> wrote: > > > No, because, like Stephen says, the descriptor is first validated > > against a list of known ones. > > In that case, wouldn't it be better to have the integer be an index > into a table, like Stefan suggested? It's easy to do that (of course, at a price of some slightly more complicated memory management), but I think Stefan still prefers the "new object" solution. > It's faster to check that it is in range than compare it with an > arbitrarily long list of known pointers. That's not what the code does. It calls Fassoc_quit to find the descriptor in the list of known live watches (which will still be needed under the table suggestion), and then validates the pointer itself, just in case (which is also independent of the table suggestion). ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-18 11:17 ` Eli Zaretskii @ 2012-10-18 12:33 ` Stefan Monnier 2012-10-18 17:16 ` Eli Zaretskii 0 siblings, 1 reply; 39+ messages in thread From: Stefan Monnier @ 2012-10-18 12:33 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Juanma Barranquero, eggert, emacs-devel >> In that case, wouldn't it be better to have the integer be an index >> into a table, like Stefan suggested? > It's easy to do that (of course, at a price of some slightly more > complicated memory management), I don't understand why the memory management would care about which integer you use to represent file-watcher descriptors. > but I think Stefan still prefers the "new object" solution. I generally like stronger types, so you're probably right, but an "index into a table" doesn't necessarily sound so terribly bad, if you have such a table anyway (BTW, is this table usable by Lisp, e.g. can they get the list of current file-watchers?). >> It's faster to check that it is in range than compare it with an >> arbitrarily long list of known pointers. > That's not what the code does. It calls Fassoc_quit to find the > descriptor in the list of known live watches (which will still be > needed under the table suggestion), Isn't Fassoc_quit going to "compare it with an arbitrarily long list"? To me this "list of known live watches" sounds exactly like the "table" I mention above. > and then validates the pointer itself, just in case (which is also > independent of the table suggestion). What means "validate"? Stefan ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-18 12:33 ` Stefan Monnier @ 2012-10-18 17:16 ` Eli Zaretskii 2012-10-18 22:09 ` Stefan Monnier 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2012-10-18 17:16 UTC (permalink / raw) To: Stefan Monnier; +Cc: lekktu, eggert, emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: Juanma Barranquero <lekktu@gmail.com>, eggert@cs.ucla.edu, emacs-devel@gnu.org > Date: Thu, 18 Oct 2012 08:33:59 -0400 > > >> In that case, wouldn't it be better to have the integer be an index > >> into a table, like Stefan suggested? > > It's easy to do that (of course, at a price of some slightly more > > complicated memory management), > > I don't understand why the memory management would care about which > integer you use to represent file-watcher descriptors. It doesn't. I meant the need to manage the table itself, grow it when needed, etc. > > but I think Stefan still prefers the "new object" solution. > > I generally like stronger types, so you're probably right, but an "index > into a table" doesn't necessarily sound so terribly bad, if you have > such a table anyway I don't have a table. What I have is an association list. I used the same method as Rüdiger in his inotify patch. > (BTW, is this table usable by Lisp, e.g. can they get the list of > current file-watchers?). Yes, it's an alist. But it currently isn't exposed to Lisp, neither as a variable nor via an API. It could be, of course. But since Rüdiger didn't, and since we didn't discuss in detail how this feature will be used from Lisp, I didn't want to introduce APIs whose necessity is not clear. > >> It's faster to check that it is in range than compare it with an > >> arbitrarily long list of known pointers. > > That's not what the code does. It calls Fassoc_quit to find the I meant Fassoc, of course. > > descriptor in the list of known live watches (which will still be > > needed under the table suggestion), > > Isn't Fassoc_quit going to "compare it with an arbitrarily long list"? > To me this "list of known live watches" sounds exactly like the "table" > I mention above. Yes, but since it's an alist, I get its memory management for free. > > and then validates the pointer itself, just in case (which is also > > independent of the table suggestion). > > What means "validate"? Call w32_valid_pointer_p, and in addition verify that the struct pointed to by it has the correct magic signature. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-18 17:16 ` Eli Zaretskii @ 2012-10-18 22:09 ` Stefan Monnier 2012-10-19 7:14 ` Eli Zaretskii 0 siblings, 1 reply; 39+ messages in thread From: Stefan Monnier @ 2012-10-18 22:09 UTC (permalink / raw) To: Eli Zaretskii; +Cc: lekktu, eggert, emacs-devel > It doesn't. I meant the need to manage the table itself, grow it when > needed, etc. To me "table" doesn't imply "array". It's just some kind of data-structure that keeps the elements at hand. It can be a list, an array, a tree, a has-table, you name it. >> (BTW, is this table usable by Lisp, e.g. can they get the list of >> current file-watchers?). > Yes, it's an alist. But it currently isn't exposed to Lisp, neither > as a variable nor via an API. It could be, of course. But since > Rüdiger didn't, and since we didn't discuss in detail how this feature > will be used from Lisp, I didn't want to introduce APIs whose > necessity is not clear. Note that if we use integers instead of a new type, we can't free those structs when the Lisp code loses the last reference to the file-watcher. > Call w32_valid_pointer_p, and in addition verify that the struct > pointed to by it has the correct magic signature. Why is that needed? Can you give a precise description of your alist? Stefan ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-18 22:09 ` Stefan Monnier @ 2012-10-19 7:14 ` Eli Zaretskii 2012-10-19 14:44 ` Stefan Monnier 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2012-10-19 7:14 UTC (permalink / raw) To: Stefan Monnier; +Cc: lekktu, eggert, emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: lekktu@gmail.com, eggert@cs.ucla.edu, emacs-devel@gnu.org > Date: Thu, 18 Oct 2012 18:09:46 -0400 > > > It doesn't. I meant the need to manage the table itself, grow it when > > needed, etc. > > To me "table" doesn't imply "array". It's just some kind of > data-structure that keeps the elements at hand. It can be a list, an > array, a tree, a has-table, you name it. If we use a Lisp data structure, then the same issue of putting a bare pointer into that started this thread it pops up again, doesn't it? Anyway, a Lisp data structure is what I have now. > >> (BTW, is this table usable by Lisp, e.g. can they get the list of > >> current file-watchers?). > > Yes, it's an alist. But it currently isn't exposed to Lisp, neither > > as a variable nor via an API. It could be, of course. But since > > Rüdiger didn't, and since we didn't discuss in detail how this feature > > will be used from Lisp, I didn't want to introduce APIs whose > > necessity is not clear. > > Note that if we use integers instead of a new type, we can't free > those structs when the Lisp code loses the last reference to the > file-watcher. The list is maintained by 2 primitives, which take care of that. And the list itself is statically protected from GC. If some disaster strikes and the list is somehow thrashed or released by some evil magic, then all we have is a bunch of threads watching file-change notifications that no one can hear, threads which can only be stopped by shutting down Emacs. Not too bad, considering the doomsday scenario under which it can happen. > > Call w32_valid_pointer_p, and in addition verify that the struct > > pointed to by it has the correct magic signature. > > Why is that needed? To make sure we never dereference a pointer that doesn't point to the watch object. Since the remove-watch API accepts a Lisp integer, it could be called with any arbitrary integer value. IOW, I don't want to crash, even if somehow a bad pointer is found in the alist described below. > Can you give a precise description of your alist? It's an alist of cons cells like this: (DESCRIPTOR . CALLBACK) where DESCRIPTOR is a pointer to the C struct as a Lisp integer, and CALLBACK is a function to call when the file notification event comes in. A single cons cell describes a single file-change notification request; each such request allocates another C struct (and thus gets another DESCRIPTOR) and starts another thread. As I wrote, the reason for this design of the alist was to be 100% compatible with what Rüdiger did. Otherwise, I could keep CALLBACK in the C struct as well, for example. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-19 7:14 ` Eli Zaretskii @ 2012-10-19 14:44 ` Stefan Monnier 2012-10-19 18:54 ` Eli Zaretskii 0 siblings, 1 reply; 39+ messages in thread From: Stefan Monnier @ 2012-10-19 14:44 UTC (permalink / raw) To: Eli Zaretskii; +Cc: lekktu, eggert, emacs-devel >> > It doesn't. I meant the need to manage the table itself, grow it when >> > needed, etc. >> To me "table" doesn't imply "array". It's just some kind of >> data-structure that keeps the elements at hand. It can be a list, an >> array, a tree, a has-table, you name it. > If we use a Lisp data structure, then the same issue of putting a bare > pointer into that started this thread it pops up again, doesn't it? > Anyway, a Lisp data structure is what I have now. In any case, the code now does keep a table of those C structs, and they are not reclaimed when the Lisp code loses the last "handle". Instead they are only reclaimed when the Lisp code calls remove-watch explicitly. This design means we don't need a "finalizer" (i.e. code in gc_sweep that calls us back to free the C struct), but it also means that we may "leak" those C structs if the Lisp code just forgets to `remove-watch'. I think that's OK for now. >> > Call w32_valid_pointer_p, and in addition verify that the struct >> > pointed to by it has the correct magic signature. >> Why is that needed? > To make sure we never dereference a pointer that doesn't point to the > watch object. Since the remove-watch API accepts a Lisp integer, it > could be called with any arbitrary integer value. But as long as the table is not corrupted, there's no risk of such a thing happening anyway. > IOW, I don't want to crash, even if somehow a bad pointer is found in > the alist described below. OK, so it's just done out of paranoia. That's fine, but please make it clear in the code, e.g. by placing it in an eassert. > As I wrote, the reason for this design of the alist was to be 100% > compatible with what Rüdiger did. Otherwise, I could keep CALLBACK in > the C struct as well, for example. I think it's OK. Encoding C pointers in Lisp integers is pretty ugly, so we should make sure that no part of the design depends on it (so it can be changed in the future) and we should also make it very clear in the doc that Elisp code should not rely on those handles being integers (treat them as black boxes instead). Stefan ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-19 14:44 ` Stefan Monnier @ 2012-10-19 18:54 ` Eli Zaretskii 2012-10-19 21:35 ` Stefan Monnier 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2012-10-19 18:54 UTC (permalink / raw) To: Stefan Monnier; +Cc: lekktu, eggert, emacs-devel > From: Stefan Monnier <monnier@IRO.UMontreal.CA> > Cc: lekktu@gmail.com, eggert@cs.ucla.edu, emacs-devel@gnu.org > Date: Fri, 19 Oct 2012 10:44:32 -0400 > > >> > It doesn't. I meant the need to manage the table itself, grow it when > >> > needed, etc. > >> To me "table" doesn't imply "array". It's just some kind of > >> data-structure that keeps the elements at hand. It can be a list, an > >> array, a tree, a has-table, you name it. > > If we use a Lisp data structure, then the same issue of putting a bare > > pointer into that started this thread it pops up again, doesn't it? > > Anyway, a Lisp data structure is what I have now. > > In any case, the code now does keep a table of those C structs, and they > are not reclaimed when the Lisp code loses the last "handle". > Instead they are only reclaimed when the Lisp code calls > remove-watch explicitly. That's true. The reason is that the C struct cannot be reclaimed as long as the watcher thread runs, because that thread constantly dereferences a pointer to the struct. The remove-watch API takes care of orderly shutting down the thread (which is not trivial, because it is mostly stuck in a system call), and then frees the struct. > This design means we don't need a "finalizer" (i.e. code in gc_sweep > that calls us back to free the C struct), but it also means that we may > "leak" those C structs if the Lisp code just forgets to `remove-watch'. Correct. > I think that's OK for now. I concur. > >> > Call w32_valid_pointer_p, and in addition verify that the struct > >> > pointed to by it has the correct magic signature. > >> Why is that needed? > > To make sure we never dereference a pointer that doesn't point to the > > watch object. Since the remove-watch API accepts a Lisp integer, it > > could be called with any arbitrary integer value. > > But as long as the table is not corrupted, there's no risk of such > a thing happening anyway. Right. > > IOW, I don't want to crash, even if somehow a bad pointer is found in > > the alist described below. > > OK, so it's just done out of paranoia. That's fine, but please make it > clear in the code, e.g. by placing it in an eassert. Will do. > > As I wrote, the reason for this design of the alist was to be 100% > > compatible with what Rüdiger did. Otherwise, I could keep CALLBACK in > > the C struct as well, for example. > > I think it's OK. Encoding C pointers in Lisp integers is pretty ugly, > so we should make sure that no part of the design depends on it (so it > can be changed in the future) Well, the way to get the pointer to the struct given the descriptor and vice versa _will_ have to change if the design changes. Other than that, nothing depends on that. > and we should also make it very clear in the doc that Elisp code > should not rely on those handles being integers (treat them as black > boxes instead). They are documented as "descriptors". I will see if there's a place to make the point you want to drive home. Anyway, I guess I'm waiting for Rüdiger to install his changes, is that right? ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-19 18:54 ` Eli Zaretskii @ 2012-10-19 21:35 ` Stefan Monnier 2012-10-19 22:35 ` Eli Zaretskii 0 siblings, 1 reply; 39+ messages in thread From: Stefan Monnier @ 2012-10-19 21:35 UTC (permalink / raw) To: Eli Zaretskii; +Cc: lekktu, eggert, emacs-devel > Anyway, I guess I'm waiting for Rüdiger to install his changes, is > that right? I don't think he has access rights yet. So we're waiting for someone to install his patch. But I'm beginning to feel like it's late for 24.3, because I don't have time to devote to it right now. Stefan ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-19 21:35 ` Stefan Monnier @ 2012-10-19 22:35 ` Eli Zaretskii 2012-10-20 1:52 ` Stefan Monnier 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2012-10-19 22:35 UTC (permalink / raw) To: Stefan Monnier; +Cc: lekktu, eggert, emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: lekktu@gmail.com, eggert@cs.ucla.edu, emacs-devel@gnu.org > Date: Fri, 19 Oct 2012 17:35:02 -0400 > > I'm beginning to feel like it's late for 24.3, because I don't have > time to devote to it right now. It's too bad to hear this only now, when all the work is already done. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-19 22:35 ` Eli Zaretskii @ 2012-10-20 1:52 ` Stefan Monnier 2012-10-20 8:34 ` Eli Zaretskii 0 siblings, 1 reply; 39+ messages in thread From: Stefan Monnier @ 2012-10-20 1:52 UTC (permalink / raw) To: Eli Zaretskii; +Cc: lekktu, eggert, emacs-devel >> I'm beginning to feel like it's late for 24.3, because I don't have >> time to devote to it right now. > It's too bad to hear this only now, when all the work is already done. It's not wasted, AFAIK. But if you want, you can install the inotify patch along with yours (assuming you can check that the inotify patch is OK). Otherwise, it'll have to wait for after the freeze, which shouldn't be that far in the future anyway. Stefan ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-20 1:52 ` Stefan Monnier @ 2012-10-20 8:34 ` Eli Zaretskii 0 siblings, 0 replies; 39+ messages in thread From: Eli Zaretskii @ 2012-10-20 8:34 UTC (permalink / raw) To: Stefan Monnier; +Cc: lekktu, eggert, emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: lekktu@gmail.com, eggert@cs.ucla.edu, emacs-devel@gnu.org > Date: Fri, 19 Oct 2012 21:52:33 -0400 > > >> I'm beginning to feel like it's late for 24.3, because I don't have > >> time to devote to it right now. > > It's too bad to hear this only now, when all the work is already done. > > It's not wasted, AFAIK. But if you want, you can install the inotify > patch along with yours (assuming you can check that the inotify patch is > OK). I cannot test inotify, sorry. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-16 21:43 ` Stefan Monnier 2012-10-17 4:05 ` Eli Zaretskii @ 2012-10-17 16:05 ` Eli Zaretskii 2012-10-17 16:59 ` Davis Herring 2012-10-17 20:27 ` Stefan Monnier 1 sibling, 2 replies; 39+ messages in thread From: Eli Zaretskii @ 2012-10-17 16:05 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: emacs-devel@gnu.org > Date: Tue, 16 Oct 2012 17:43:26 -0400 > > > In any case, which one, pseudovector or misc, is better suited for > > this particular job, in your opinion? What would you use? > > I guess I'd go with the Lisp_Misc. OK, thanks. > The code to free the C struct will be the one you write > specifically for it, nobody else knows how to free it. Then the code that GC's this new Lisp object will have to be entirely specific to the layout of the struct I'm using, right? It won't be suitable even for the similar-but-different inotify code, right? If so, it's too bad: I hoped I could come up with some Lisp object that could be a wrapper for an arbitrary C struct, so that any similar feature that will need to pass opaque objects to Lisp could do that, instead of adding yet another object type. If it's possible to do this in some generic way, could you please explain how? > > That code must be run whenever the object is GC'ed, at the very least. > > It would be even better not to leave this to GC at all, but instead > > delete the object whenever the watch is canceled, since otherwise we > > leave behind a thread that does nothing except wasting system > > resources, for a time interval whose length cannot be predicted > > or controlled. > > If you make sure there's at most 1 file-watcher object per C struct, > then you can easily zero-out its pointer-field after freeing the > C struct, so you can make sure you protect yourself from > dangling pointers. And if you make sure the GC calls you back when > freeing the file-watcher, then you can make sure that you don't leak the > C structs. You mean, have the free_my_object function (to be called by GC) call my own code? Or is there a more generic way? ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-17 16:05 ` Eli Zaretskii @ 2012-10-17 16:59 ` Davis Herring 2012-10-17 20:27 ` Stefan Monnier 1 sibling, 0 replies; 39+ messages in thread From: Davis Herring @ 2012-10-17 16:59 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Stefan Monnier, emacs-devel > Then the code that GC's this new Lisp object will have to be entirely > specific to the layout of the struct I'm using, right? It won't be > suitable even for the similar-but-different inotify code, right? If > so, it's too bad: I hoped I could come up with some Lisp object that > could be a wrapper for an arbitrary C struct, so that any similar > feature that will need to pass opaque objects to Lisp could do that, > instead of adding yet another object type. > > If it's possible to do this in some generic way, could you please > explain how? Python addresses this with the CObject API. (It is being supplanted by a newer Capsule API, but it's nice and simple as a comparison point.) http://docs.python.org/c-api/cobject.html Basically, you make your single new Lisp type contain a pair of pointers: the first points to your struct, and the other points to a function that frees the struct and does whatever other cleanup. This latter can also be used as a type tag (so that you can't accidentally use this to cast a eli_file_watcher_struct* to a stefan_smie_cache_struct* and turn a Lisp bug into a crash in C), although that might involve creating several wrappers for free() in the trivial case. (The CObjects use a third pointer that can be used to disambiguate; either way works.) The advantage of this approach is that the pointer marshaling code (and the object-printing code and so forth) need only be written once, and only one true Lisp type is used. The disadvantage is of course that two layers of type checking must be performed: the usual CONSP variety, and then you check the function pointer (or other tag) once you know that it's a struct-wrapper of some sort. >> If you make sure there's at most 1 file-watcher object per C struct, >> then you can easily zero-out its pointer-field after freeing the >> C struct, so you can make sure you protect yourself from >> dangling pointers. And if you make sure the GC calls you back when >> freeing the file-watcher, then you can make sure that you don't leak the >> C structs. > > You mean, have the free_my_object function (to be called by GC) call > my own code? Or is there a more generic way? Yet another approach is to make sure that your code keeps a reference to the struct-wrapper Lisp object and frees that reference only when it destroys the underlying thread. Then if the thread is alive, the struct is; you can have a field in the struct (again like the killed buffer) that means "this has no thread, so you can't use it from Lisp anymore". Then when the Lisp client gives up and drops their reference, the struct is freed. (Of course, you could do it the other way around: have GC destroy the thread when the last reference to the struct-wrapper dies. Then client Lisp merely drops their references to the wrapper when they're done, although there is some nondeterminism about when GC will happen.) Davis -- This product is sold by volume, not by mass. If it appears too dense or too sparse, it is because mass-energy conversion has occurred during shipping. ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-17 16:05 ` Eli Zaretskii 2012-10-17 16:59 ` Davis Herring @ 2012-10-17 20:27 ` Stefan Monnier 2012-10-17 21:02 ` Eli Zaretskii 1 sibling, 1 reply; 39+ messages in thread From: Stefan Monnier @ 2012-10-17 20:27 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel >> The code to free the C struct will be the one you write >> specifically for it, nobody else knows how to free it. > Then the code that GC's this new Lisp object will have to be entirely > specific to the layout of the struct I'm using, right? I said "free" not "GC's". The GC decide what to free, and takes care of freeing most of the objects in the heap. The code that frees the Lisp_Misc file-watcher will be the generic GC code. And that generic code will have to trigger your specific code that frees the C struct. > It won't be suitable even for the similar-but-different inotify code, > right? Depends, you can make it generic by having the Lisp_Misc object have 2 slots: one containing the pointer to the C struct and another pointing to the matching freeing function. Stefan ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-17 20:27 ` Stefan Monnier @ 2012-10-17 21:02 ` Eli Zaretskii 2012-10-18 0:23 ` Stefan Monnier 0 siblings, 1 reply; 39+ messages in thread From: Eli Zaretskii @ 2012-10-17 21:02 UTC (permalink / raw) To: Stefan Monnier; +Cc: emacs-devel > From: Stefan Monnier <monnier@iro.umontreal.ca> > Cc: emacs-devel@gnu.org > Date: Wed, 17 Oct 2012 16:27:39 -0400 > > >> The code to free the C struct will be the one you write > >> specifically for it, nobody else knows how to free it. > > Then the code that GC's this new Lisp object will have to be entirely > > specific to the layout of the struct I'm using, right? > > I said "free" not "GC's". The GC decide what to free, and takes care of > freeing most of the objects in the heap. The code that frees > the Lisp_Misc file-watcher will be the generic GC code. And that > generic code will have to trigger your specific code that frees the > C struct. > > > It won't be suitable even for the similar-but-different inotify code, > > right? > > Depends, you can make it generic by having the Lisp_Misc object have > 2 slots: one containing the pointer to the C struct and another pointing > to the matching freeing function. OK, but who will call this freeing function? E.g., I don't see a call to free_misc in gc_sweep, it just puts every Lisp_Misc on the free list. Do I add the call to the freeing function in gc_sweep, similar to the call to unchain_marker for markers? ^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: Lisp object that refers to a C struct 2012-10-17 21:02 ` Eli Zaretskii @ 2012-10-18 0:23 ` Stefan Monnier 0 siblings, 0 replies; 39+ messages in thread From: Stefan Monnier @ 2012-10-18 0:23 UTC (permalink / raw) To: Eli Zaretskii; +Cc: emacs-devel > OK, but who will call this freeing function? E.g., I don't see a call > to free_misc in gc_sweep, it just puts every Lisp_Misc on the free > list. Do I add the call to the freeing function in gc_sweep, similar > to the call to unchain_marker for markers? Yes, you need to add the call to gc_sweep. Stefan ^ permalink raw reply [flat|nested] 39+ messages in thread
end of thread, other threads:[~2012-10-20 8:34 UTC | newest] Thread overview: 39+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-10-15 21:24 Lisp object that refers to a C struct Eli Zaretskii 2012-10-16 1:07 ` Stefan Monnier 2012-10-16 3:53 ` Eli Zaretskii 2012-10-16 13:11 ` Stefan Monnier 2012-10-16 17:22 ` Eli Zaretskii 2012-10-16 21:43 ` Stefan Monnier 2012-10-17 4:05 ` Eli Zaretskii 2012-10-17 6:21 ` Stephen J. Turnbull 2012-10-17 15:50 ` Eli Zaretskii 2012-10-17 17:45 ` Stephen J. Turnbull 2012-10-17 13:34 ` Stefan Monnier 2012-10-17 16:08 ` Eli Zaretskii 2012-10-17 20:23 ` Stefan Monnier 2012-10-17 20:46 ` Eli Zaretskii 2012-10-17 22:08 ` Paul Eggert 2012-10-18 0:22 ` Stefan Monnier 2012-10-18 3:43 ` Stephen J. Turnbull 2012-10-18 4:50 ` Eli Zaretskii 2012-10-18 7:20 ` Paul Eggert 2012-10-18 11:09 ` Eli Zaretskii 2012-10-18 16:42 ` Paul Eggert 2012-10-18 17:21 ` Eli Zaretskii 2012-10-18 8:52 ` Juanma Barranquero 2012-10-18 11:17 ` Eli Zaretskii 2012-10-18 12:33 ` Stefan Monnier 2012-10-18 17:16 ` Eli Zaretskii 2012-10-18 22:09 ` Stefan Monnier 2012-10-19 7:14 ` Eli Zaretskii 2012-10-19 14:44 ` Stefan Monnier 2012-10-19 18:54 ` Eli Zaretskii 2012-10-19 21:35 ` Stefan Monnier 2012-10-19 22:35 ` Eli Zaretskii 2012-10-20 1:52 ` Stefan Monnier 2012-10-20 8:34 ` Eli Zaretskii 2012-10-17 16:05 ` Eli Zaretskii 2012-10-17 16:59 ` Davis Herring 2012-10-17 20:27 ` Stefan Monnier 2012-10-17 21:02 ` Eli Zaretskii 2012-10-18 0:23 ` Stefan Monnier
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.