From: Colin M. <co...@ch...> - 2009-07-24 09:30:52
|
Alexandre asked for some comments on the SF 'artifact' comment stream, but SF then decided to close the 'artifact' for further comments, so I'm moving it here. My proposal: I would like a [chan rename $oldname $newname] command, which renamed a channel. This would be useful to avoid bugs (admittedly, caused by other bugs) where an open channel name is stored in one data structure, perhaps in a coro, thread or interp, and the channel is closed before the channel name can be removed from those data structures. The current effect of such uncoordinated storage is that either a delay in closing the channel must be suffered while all copies of the name are updated, or that a stale chan name is held somewhere, and causes a new chan (usually a socket) with the same name as the old (and now closed) chan to be manipulated in error. This problem arises, essentially, because tcl reuses chan names frequently, and chooses them from a very compact set. By enabling arbitrarily named chans, at construction time, chan name conflict could be completely avoided by an application. Alexandre's response: Hmmm, there are two separate issues here: (1) removing the carpet under a coro/thread feet and (2) too fast reuse. I fail to see how this would solve (1), but for (2) it is clear. Can you clarify on (1) ? Regarding (2), the "compact set" arises from Tcl's direct use of OS handles/fd, and on unix fds are a compact set. On Windows AFAIK handles are not reused (correct m if I'm wrong). So, an alternative way of solving this issue, without any intervention from the script writer, would be to insert an indirection in Tcl, with an intentionally compact set managed by Tcl, but extended with generation counts, so that no reuse occurs: typedef struct { HANDLE_OR_INT fd; int gencount; } UniqueHandle; UniqueHandle *compactArrayOfFds; The idea, then, is to have automatic channel names of the form sock3g1 which can be looked up from string in two steps: 3 is the index in compactArrayOfFds 1 is the gencount for verification This way, even if slot 3 of the array is reused, it will have a gencount of at least 2, hence any stale reference to sock3g1 will generate an error instead of wreaking havoc by unwanted IO on another channel. Note that this works well with the Channel intrep too, assuming we add the gencount to the structure. Then the gencount verification is just an extra integer comparison. Reactions ? My Response: I've thought of a new good reason to do this: by renaming, one could introduce some application-specific encoding into the names, for example "connected_$ipaddress_$count" and get connection counting for free. I also thought of a new distinct area of a program which may contain chan names: the event system (fileevents and such) Now, to clarify: if you have a coro which is in the process of handling fileevents on a socket (socket10, let's say) and you decide you want to not handle events on that socket for a few seconds, so you schedule an [after] event to trigger to enable you to re-establish the [fileevent $sock] ... you must store the socket name (socket10) in the variable sock, which may be a coro variable, hence inaccessible to other coros. If a different processing stream, or coro, decides it wants to close socket10, it can't safely do that until and unless it has notified the first coro of its intention, so that it can (a) forget about socket10 - cancel any [after] events it may have scheduled. If this sounds like a contrived example, it's not. I have almost exactly this problem in adding input throttling to Wub right now, and anyone writing a producer/consumer pair with buffering where the two parts make use of modern Tcl facilities such as coros or [apply] or even [interp] will have similar problems. The amount of data which needs to be shared between the distinct processing elements is too great, and is imposed entirely by the rapid cycling of chan names. It is true that one could fix the cycling, but the idea of encoding names with significant information also appeals to me. Colin. |