diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2018-11-06 09:51:55 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2018-11-06 09:51:55 (GMT) |
commit | 2798a075ee62ea5ab4aa80279d614a8634ba378a (patch) | |
tree | 0a09cb9e38547d3b35e396717c0b04302eb5bd8a /generic/tclIO.c | |
parent | 5429d6aeaf940119a7a7bb0a3d54ae966c234314 (diff) | |
parent | f7dfeb706fb75bccd0aae6cd6119fccdfb6bd8d0 (diff) | |
download | tcl-2798a075ee62ea5ab4aa80279d614a8634ba378a.zip tcl-2798a075ee62ea5ab4aa80279d614a8634ba378a.tar.gz tcl-2798a075ee62ea5ab4aa80279d614a8634ba378a.tar.bz2 |
Implement TIP 445
Diffstat (limited to 'generic/tclIO.c')
-rw-r--r-- | generic/tclIO.c | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c index 10362d4..d144cbc 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -337,6 +337,22 @@ static const Tcl_ObjType chanObjType = { NULL /* setFromAnyProc */ }; +#define ChanSetIntRep(objPtr, resPtr) \ + do { \ + Tcl_ObjIntRep ir; \ + (resPtr)->refCount++; \ + ir.twoPtrValue.ptr1 = (resPtr); \ + ir.twoPtrValue.ptr2 = NULL; \ + Tcl_StoreIntRep((objPtr), &chanObjType, &ir); \ + } while (0) + +#define ChanGetIntRep(objPtr, resPtr) \ + do { \ + const Tcl_ObjIntRep *irPtr; \ + irPtr = Tcl_FetchIntRep((objPtr), &chanObjType); \ + (resPtr) = irPtr ? irPtr->twoPtrValue.ptr1 : NULL; \ + } while (0) + #define BUSY_STATE(st, fl) \ ((((st)->csPtrR) && ((fl) & TCL_READABLE)) || \ (((st)->csPtrW) && ((fl) & TCL_WRITABLE))) @@ -1515,12 +1531,12 @@ TclGetChannelFromObj( return TCL_ERROR; } - if (objPtr->typePtr == &chanObjType) { + ChanGetIntRep(objPtr, resPtr); + if (resPtr) { /* * Confirm validity of saved lookup results. */ - resPtr = (ResolvedChanName *) objPtr->internalRep.twoPtrValue.ptr1; statePtr = resPtr->statePtr; if ((resPtr->interp == interp) /* Same interp context */ /* No epoch change in channel since lookup */ @@ -1537,7 +1553,7 @@ TclGetChannelFromObj( if (chan == NULL) { if (resPtr) { - FreeChannelIntRep(objPtr); + Tcl_StoreIntRep(objPtr, &chanObjType, NULL); } return TCL_ERROR; } @@ -1548,14 +1564,10 @@ TclGetChannelFromObj( */ Tcl_Release((ClientData) resPtr->statePtr); - } else { - TclFreeIntRep(objPtr); - resPtr = (ResolvedChanName *) ckalloc(sizeof(ResolvedChanName)); - resPtr->refCount = 1; - objPtr->internalRep.twoPtrValue.ptr1 = (ClientData) resPtr; - objPtr->typePtr = &chanObjType; + resPtr->refCount = 0; + ChanSetIntRep(objPtr, resPtr); /* Overwrites, if needed */ } statePtr = ((Channel *)chan)->state; resPtr->statePtr = statePtr; @@ -11198,11 +11210,11 @@ DupChannelIntRep( register Tcl_Obj *copyPtr) /* Object with internal rep to set. Must not * currently have an internal rep.*/ { - ResolvedChanName *resPtr = srcPtr->internalRep.twoPtrValue.ptr1; + ResolvedChanName *resPtr; - resPtr->refCount++; - copyPtr->internalRep.twoPtrValue.ptr1 = resPtr; - copyPtr->typePtr = srcPtr->typePtr; + ChanGetIntRep(srcPtr, resPtr); + assert(resPtr); + ChanSetIntRep(copyPtr, resPtr); } /* @@ -11225,9 +11237,10 @@ static void FreeChannelIntRep( Tcl_Obj *objPtr) /* Object with internal rep to free. */ { - ResolvedChanName *resPtr = objPtr->internalRep.twoPtrValue.ptr1; + ResolvedChanName *resPtr; - objPtr->typePtr = NULL; + ChanGetIntRep(objPtr, resPtr); + assert(resPtr); if (resPtr->refCount-- > 1) { return; } |