home | help
Tcl_Obj(3)		     Tcl Library Procedures		      Tcl_Obj(3)

________________________________________________________________________________

NAME
     Tcl_NewObj,     Tcl_DuplicateObj,	  Tcl_IncrRefCount,    Tcl_DecrRefCount,
     Tcl_BounceRefCount, Tcl_IsShared, Tcl_InvalidateStringRep - manipulate  Tcl
     values

SYNOPSIS
     #include <tcl.h>

     Tcl_Obj *
     Tcl_NewObj()

     Tcl_Obj *
     Tcl_DuplicateObj(objPtr)

     Tcl_IncrRefCount(objPtr)

     Tcl_DecrRefCount(objPtr)

     Tcl_BounceRefCount(objPtr)

     int
     Tcl_IsShared(objPtr)

     Tcl_InvalidateStringRep(objPtr)

ARGUMENTS
     Tcl_Obj *objPtr (in)	   Points  to a value; must have been the result
				   of a previous call to Tcl_NewObj.
________________________________________________________________________________

INTRODUCTION
     N.B. Refer to the Tcl_UniChar documentation page for a description  of  the
     TUTF-8 encoding and related terms referenced here.

     This  man page presents an overview of Tcl values (called Tcl_Objs for his-
     torical reasons) and how they are used.  It also describes  generic  proce-
     dures  for  managing  Tcl	values.  These procedures are used to create and
     copy values, and increment and decrement the count of references (pointers)
     to values.  The procedures are used in conjunction with ones  that  operate
     on specific types of values such as Tcl_GetIntFromObj and Tcl_ListObjAppen-
     dElement.	 The  individual  procedures  are  described along with the data
     structures they manipulate.

     Tcl's dual-ported values provide a general-purpose  mechanism  for  storing
     and exchanging Tcl values.  They largely replace the use of strings in Tcl.
     For  example,  they  are  used to store variable values, command arguments,
     command results, and scripts.  Tcl values behave like strings but also hold
     an internal representation that can be manipulated more  efficiently.   For
     example,  a  Tcl  list  is now represented as a value that holds the list's
     string representation as well as an array of pointers  to	the  values  for
     each list element.  Dual-ported values avoid most runtime type conversions.
     They  also improve the speed of many operations since an appropriate repre-
     sentation is immediately available.  The compiler itself uses Tcl values to
     cache the instruction bytecodes resulting from compiling scripts.

     The two representations are a cache of each other and are computed  lazily.
     That  is,	each  representation is only computed when necessary, it is com-
     puted from the other representation, and, once computed, it is  saved.   In
     addition,	a change in one representation invalidates the other one.  As an
     example, a Tcl program doing integer calculations can operate directly on a
     variable's internal machine integer representation without having	to  con-
     stantly  convert between integers and strings.  Only when it needs a string
     representing the variable's value, say to print it, will the program regen-
     erate the string representation from the integer.	Although values  contain
     an  internal  representation,  their  semantics  are  defined  in	terms of
     strings: an up-to-date string can always be obtained, and any change to the
     value will be reflected in that string when the value's string  representa-
     tion is fetched.  Because of this representation invalidation and regenera-
     tion,  it	is  dangerous for extension writers to access Tcl_Obj fields di-
     rectly.  It is better to access Tcl_Obj information using	procedures  like
     Tcl_GetStringFromObj and Tcl_GetString.

     Values  are  allocated  on  the  heap and are referenced using a pointer to
     their Tcl_Obj structure.  Values are shared as much as possible.  This sig-
     nificantly reduces storage requirements because some values  such	as  long
     lists  are very large.  Also, most Tcl values are only read and never modi-
     fied.  This is especially true for procedure arguments, which can be shared
     between the caller and the called procedure.  Assignment and argument bind-
     ing is done by simply assigning a pointer to the value.  Reference counting
     is used to determine when it is safe to reclaim a value's storage.

     Tcl values are typed.  A value's internal representation is  controlled  by
     its  type.  Several types are predefined in the Tcl core including integer,
     double, list, and bytecode.  Extension writers can extend the set of  types
     by defining their own Tcl_ObjType structs.

THE TCL_OBJ STRUCTURE
     Each  Tcl	value  is represented by a Tcl_Obj structure which is defined as
     follows.

	    typedef struct {
		Tcl_Size refCount;
		char *bytes;
		Tcl_Size length;
		const Tcl_ObjType *typePtr;
		union {
		    long longValue;
		    double doubleValue;
		    void *otherValuePtr;
		    Tcl_WideInt wideValue;
		    struct {
			void *ptr1;
			void *ptr2;
		    } twoPtrValue;
		    struct {
			void *ptr;
			unsigned long value;
		    } ptrAndLongRep;
		    struct {
			void *ptr;
			Tcl_Size size;
		    } ptrAndSize;
		} internalRep;
	    } Tcl_Obj;

     The bytes and the length members together hold a value's  TUTF-8  byte  se-
     quence representation.  bytes points to the first byte of the string repre-
     sentation.   The  length  member gives the number of bytes.  The byte array
     must always have a null byte after the last data byte,  at  offset  length;
     this  allows string representations to be treated as conventional null-ter-
     minated C strings.  C programs use Tcl_GetStringFromObj  and  Tcl_GetString
     to  get a value's string representation.  If bytes is NULL, the string rep-
     resentation is invalid.

     A value's type manages its internal  representation.   The  member  typePtr
     points to the Tcl_ObjType structure that describes the type.  If typePtr is
     NULL, the internal representation is invalid.

     The internalRep union member holds a value's internal representation.  This
     is  either  a  (long)  integer, a double-precision floating-point number, a
     pointer to a value containing additional information needed by the  value's
     type to represent the value, a Tcl_WideInt integer, two arbitrary pointers,
     a pair made up of a pointer and an unsigned long integer, or a pair made up
     of a pointer and Tcl_Size which is a signed integer type capable of holding
     the maximum lengths permitted in Tcl.

     The refCount member is used to tell when it is safe to free a value's stor-
     age.   It	holds  the count of active references to the value.  Maintaining
     the correct reference count is a key responsibility of  extension	writers.
     Reference	counting is discussed below in the section STORAGE MANAGEMENT OF
     VALUES.

     Although extension writers can directly access the  members  of  a  Tcl_Obj
     structure,  it is much better to use the appropriate procedures and macros.
     For example, extension writers should never read  or  update  refCount  di-
     rectly;  they  should  use macros such as Tcl_IncrRefCount and Tcl_IsShared
     instead.

     A key property of Tcl values is that  they  hold  two  representations.   A
     value  typically  starts out containing only a string representation: it is
     untyped and has a NULL typePtr.  A value containing an empty  string  or  a
     copy  of a specified string is created using Tcl_NewObj or Tcl_NewStringObj
     respectively.  A value's string value is gotten  with  Tcl_GetStringFromObj
     or  Tcl_GetString and changed with Tcl_SetStringObj.  If the value is later
     passed to a procedure like Tcl_GetIntFromObj that requires a  specific  in-
     ternal  representation,  the  procedure will create one and set the value's
     typePtr.  The internal representation is computed from the string represen-
     tation.  A value's two representations are duals  of  each  other:  changes
     made  to  one  are reflected in the other.  For example, Tcl_ListObjReplace
     will modify a value's internal representation and the next call to Tcl_Get-
     StringFromObj or Tcl_GetString will reflect that change.

     Representations are recomputed lazily for efficiency.  A change to one rep-
     resentation made by a procedure such as Tcl_ListObjReplace is not reflected
     immediately in the other representation.  Instead, the other representation
     is marked invalid so that it is only regenerated if  it  is  needed  later.
     Most  C  programmers  never  have to be concerned with how this is done and
     simply use procedures such as  Tcl_GetBooleanFromObj  or  Tcl_ListObjIndex.
     Programmers  that	implement  their  own value types must check for invalid
     representations and mark representations invalid when necessary.  The  pro-
     cedure Tcl_InvalidateStringRep is used to mark a value's string representa-
     tion  invalid and to free any storage associated with the old string repre-
     sentation.

     Values usually remain one type over their life, but  occasionally	a  value
     must be converted from one type to another.  For example, a C program might
     build  up	a  string in a value with repeated calls to Tcl_AppendToObj, and
     then call Tcl_ListObjIndex to extract a list element from the  value.   The
     same  value holding the same string value can have several different inter-
     nal representations at different times.  Extension writers can also force a
     value to be converted from one type to another using the  Tcl_ConvertToType
     procedure.   Only	programmers  that create new value types need to be con-
     cerned about how this is done.  A procedure defined as part  of  the  value
     type's implementation creates a new internal representation for a value and
     changes  its  typePtr.  See the man page for Tcl_RegisterObjType to see how
     to create a new value type.

EXAMPLE OF THE LIFETIME OF A VALUE
     As an example of the lifetime of a value, consider the  following	sequence
     of commands:

	    set x 123

     This  assigns  to	x  an untyped value whose bytes member points to 123 and
     length member contains 3.	The value's typePtr member is NULL.

	    puts "x is $x"

     x's string representation is valid (since bytes is non-NULL) and is fetched
     for the command.

	    incr x

     The incr command first gets an integer from x's value by  calling	Tcl_Get-
     IntFromObj.   This procedure checks whether the value is already an integer
     value.  Since it is not, it converts the value by setting the  value's  in-
     ternal representation to the integer 123 and setting the value's typePtr to
     point  to	the integer Tcl_ObjType structure.  Both representations are now
     valid.  incr increments the value's integer  internal  representation  then
     invalidates  its string representation (by calling Tcl_InvalidateStringRep)
     since the string representation no longer corresponds to the internal  rep-
     resentation.

	    puts "x is now $x"

     The  string  representation  of x's value is needed and is recomputed.  The
     string representation is now 124 and both representations are again valid.

STORAGE MANAGEMENT OF VALUES
     Tcl values are allocated on the heap and are shared as much as possible  to
     reduce  storage requirements.  Reference counting is used to determine when
     a value is no longer needed and can safely be freed.  A value just  created
     by  Tcl_NewObj, Tcl_NewStringObj, or any Abstract List command or function,
     has refCount 0, meaning that the object can often be given  to  a	function
     like  Tcl_SetObjResult,  Tcl_ListObjAppendElement,  or Tcl_DictObjPut (as a
     value) without explicit reference management, all of which are  common  use
     cases.  (The latter two require that the target list or dictionary be well-
     formed, but that is often easy to arrange when the value is being initially
     constructed.)  The macro Tcl_IncrRefCount increments  the	reference  count
     when  a  new reference to the value is created.  The macro Tcl_DecrRefCount
     decrements the count when a reference is no longer needed. If  the  value's
     reference count drops to zero, frees its storage.	The macro Tcl_BounceRef-
     Count will check if the value has no references (i.e. in a "new" state) and
     free  the	value.	 A value shared by different code or data structures has
     refCount greater than 1.  Incrementing a value's  reference  count  ensures
     that it will not be freed too early or have its value change accidentally.

     As  an  example,  the  bytecode  interpreter shares argument values between
     calling and called Tcl procedures to avoid having to copy values.	 It  as-
     signs  the call's argument values to the procedure's formal parameter vari-
     ables.  In doing so, it calls Tcl_IncrRefCount to increment  the  reference
     count  of	each  argument since there is now a new reference to it from the
     formal parameter.	When the called procedure returns, the interpreter calls
     Tcl_DecrRefCount to decrement each  argument's  reference	count.	 When  a
     value's  reference count drops less than or equal to zero, Tcl_DecrRefCount
     reclaims its storage.

     Most command procedures have not been concerned  about  reference	counting
     since they use a value immediately and do not retain a pointer to the value
     after  they  return.   However, there are some procedures that may return a
     new value, with a refCount of 0. In this situation, it is the caller's  re-
     sponsibility  to  free  the value before the procedure returns.  One way to
     cover this is to always call Tcl_IncrRefCount before using the value,  then
     call  Tcl_DecrRefCount before returning. The other way is to use Tcl_Bounc-
     eRefCount after the value is no longer needed  or	referenced.  This  macro
     will free the value if there are no other references to the value. When re-
     taining  a  pointer  to  a  value in a data structure the procedure must be
     careful to increment its reference count since the retained  pointer  is  a
     new reference. Examples of procedures that return new values are Tcl_NewIn-
     tObj, and commands like lseq, which creates an Abstract List, and an lindex
     on this list may return a new Obj with a refCount of 0.

     Command  procedures  that	directly modify values such as those for lappend
     and linsert must be careful to copy a  shared  value  before  changing  it.
     They  must first check whether the value is shared by calling Tcl_IsShared.
     If the value is shared they must copy the value by using  Tcl_DuplicateObj;
     this returns a new duplicate of the original value that has refCount 0.  If
     the  value  is  not  shared, the command procedure "owns" the value and can
     safely modify it directly.  For example, the following code appears in  the
     command  procedure  that  implements  linsert.  This procedure modifies the
     list value passed to it in objv[1] by inserting objc-3 new elements  before
     index.

	    listPtr = objv[1];
	    if (Tcl_IsShared(listPtr)) {
		listPtr = Tcl_DuplicateObj(listPtr);
	    }
	    result = Tcl_ListObjReplace(interp, listPtr, index, 0,
		    (objc-3), &(objv[3]));

     As  another  example, incr's command procedure must check whether the vari-
     able's value is shared before incrementing the integer in its internal rep-
     resentation.  If it is shared, it needs to duplicate the value in order  to
     avoid accidentally changing values in other data structures.

     In  cases	where a value is obtained, used, and not retained, the value can
     be freed using Tcl_BounceRefCount. This is functionally equivalent to call-
     ing Tcl_IncrRefCount followed Tcl_DecrRefCount.

SEE ALSO
     Tcl_ConvertToType(3),  Tcl_GetIntFromObj(3),   Tcl_ListObjAppendElement(3),
     Tcl_ListObjIndex(3), Tcl_ListObjReplace(3), Tcl_RegisterObjType(3)

KEYWORDS
     internal  representation,	value,	value  creation,  value  type, reference
     counting, string representation, type conversion

Tcl				       8.5			      Tcl_Obj(3)

home | help