Provided by: tcl8.5-doc_8.5.19-4_all bug

NAME

       Tcl_NewObj,    Tcl_DuplicateObj,    Tcl_IncrRefCount,    Tcl_DecrRefCount,   Tcl_IsShared,
       Tcl_InvalidateStringRep - manipulate Tcl objects

SYNOPSIS

       #include <tcl.h>

       Tcl_Obj *
       Tcl_NewObj()

       Tcl_Obj *
       Tcl_DuplicateObj(objPtr)

       Tcl_IncrRefCount(objPtr)

       Tcl_DecrRefCount(objPtr)

       int
       Tcl_IsShared(objPtr)

       Tcl_InvalidateStringRep(objPtr)

ARGUMENTS

       Tcl_Obj *objPtr (in)          Points to an object; must have been the result of a previous
                                     call to Tcl_NewObj.
_________________________________________________________________________________________________

INTRODUCTION

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

       Tcl's dual-ported objects 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  objects
       behave  like strings but also hold an internal representation that can be manipulated more
       efficiently.  For example, a Tcl list is now represented  as  an  object  that  holds  the
       list's  string representation as well as an array of pointers to the objects for each list
       element.  Dual-ported objects avoid most runtime type conversions.  They also improve  the
       speed  of  many  operations  since an appropriate representation is immediately available.
       The compiler itself uses Tcl objects 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  computed  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 constantly convert between integers and strings.  Only when it  needs  a
       string representing the variable's value, say to print it, will the program regenerate the
       string  representation  from  the  integer.   Although   objects   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 object will be reflected in that string when the
       object's  string  representation  is fetched.  Because of this representation invalidation
       and regeneration, it is dangerous for extension writers to access Tcl_Obj fields directly.
       It  is better to access Tcl_Obj information using procedures like Tcl_GetStringFromObj and
       Tcl_GetString.

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

       Tcl objects are typed.  An object'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 object is represented by a Tcl_Obj structure which is defined as follows.
              typedef struct Tcl_Obj {
                      int refCount;
                      char *bytes;
                      int length;
                      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;
                      } internalRep;
              } Tcl_Obj;
       The  bytes  and  the length members together hold an object's UTF-8 string representation,
       which is a counted string not containing null  bytes  (UTF-8  null  characters  should  be
       encoded  as  a two byte sequence: 192, 128.)  bytes points to the first byte of the string
       representation.  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-terminated C strings.  C  programs  use
       Tcl_GetStringFromObj and Tcl_GetString to get an object's string representation.  If bytes
       is NULL, the string representation is invalid.

       An object'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 an object'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 object's type to represent the object, a  Tcl_WideInt
       integer,  two  arbitrary  pointers,  or  a  pair made up of an unsigned long integer and a
       pointer.

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

       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  directly;  they  should  use  macros  such  as
       Tcl_IncrRefCount and Tcl_IsShared instead.

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

       Representations are recomputed lazily for efficiency.  A change to one representation 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 object types must check for invalid representations
       and mark representations invalid when necessary.  The procedure Tcl_InvalidateStringRep is
       used  to mark an object's string representation invalid and to free any storage associated
       with the old string representation.

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

EXAMPLE OF THE LIFETIME OF AN OBJECT

       As an example of the lifetime of an object, consider the following sequence of commands:
              set x 123
       This  assigns  to  x  an untyped object whose bytes member points to 123 and length member
       contains 3.  The object'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 object by calling Tcl_GetIntFromObj.  This
       procedure checks whether the object is already an integer object.  Since  it  is  not,  it
       converts  the  object  by setting the object's internalRep.longValue member to the integer
       123 and setting the object's typePtr to point to the integer Tcl_ObjType structure.   Both
       representations   are   now   valid.    incr  increments  the  object's  integer  internal
       representation    then    invalidates    its    string    representation    (by    calling
       Tcl_InvalidateStringRep)  since  the  string  representation  no longer corresponds to the
       internal representation.
              puts "x is now $x"
       The string representation  of  x's  object  is  needed  and  is  recomputed.   The  string
       representation is now 124 and both representations are again valid.

STORAGE MANAGEMENT OF OBJECTS

       Tcl objects are allocated on the heap and are shared as much as possible to reduce storage
       requirements.  Reference counting is used to determine when an object is no longer  needed
       and  can  safely  be  freed.  An object just created by Tcl_NewObj or Tcl_NewStringObj has
       refCount 0.  The  macro  Tcl_IncrRefCount  increments  the  reference  count  when  a  new
       reference  to the object is created.  The macro Tcl_DecrRefCount decrements the count when
       a reference is no longer needed and, if the object's reference count drops to zero,  frees
       its  storage.   An object shared by different code or data structures has refCount greater
       than 1.  Incrementing an object'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 objects between calling and called
       Tcl procedures to avoid having to copy objects.  It assigns the call's argument objects to
       the  procedure's  formal  parameter  variables.  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 an object's reference
       count  drops  less  than  or  equal  to zero, Tcl_DecrRefCount reclaims its storage.  Most
       command procedures do not have to be concerned about reference counting since they use  an
       object's  value  immediately  and do not retain a pointer to the object after they return.
       However, if they do retain a pointer to an object  in  a  data  structure,  they  must  be
       careful to increment its reference count since the retained pointer is a new reference.

       Command procedures that directly modify objects such as those for lappend and linsert must
       be careful to copy a shared object before changing it.  They must first check whether  the
       object  is  shared  by  calling  Tcl_IsShared.  If the object is shared they must copy the
       object by using Tcl_DuplicateObj; this returns a new duplicate of the original object that
       has  refCount 0.  If the object is not shared, the command procedure “owns” the object and
       can safely modify it directly.  For example, the following code  appears  in  the  command
       procedure  that  implements linsert.  This procedure modifies the list object 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 variable's  object  is
       shared  before  incrementing the integer in its internal representation.  If it is shared,
       it needs to duplicate the object in order to avoid accidentally changing values  in  other
       data structures.

SEE ALSO

       Tcl_ConvertToType(3tcl),      Tcl_GetIntFromObj(3tcl),     Tcl_ListObjAppendElement(3tcl),
       Tcl_ListObjIndex(3tcl), Tcl_ListObjReplace(3tcl), Tcl_RegisterObjType(3tcl)

KEYWORDS

       internal representation, object, object creation, object type, reference counting,  string
       representation, type conversion