manpagez: man pages & more
man Tcl_DecrRefCount(3)
Home | html | info | man
Tcl_Obj(3)                  Tcl Library Procedures                  Tcl_Obj(3)



______________________________________________________________________________


NAME

       Tcl_NewObj,   Tcl_DuplicateObj,   Tcl_IncrRefCount,   Tcl_DecrRefCount,
       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)

       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

       This man page presents an overview of Tcl values (called  Tcl_Objs  for
       historical  reasons)  and how they are used.  It also describes generic
       procedures for managing Tcl values.  These procedures are used to  cre-
       ate  and  copy  values, and increment and decrement the count of refer-
       ences (pointers) to values.  The procedures  are  used  in  conjunction
       with  ones that operate on specific types of values such as Tcl_GetInt-
       FromObj and Tcl_ListObjAppendElement.  The  individual  procedures  are
       described along with the data structures they manipulate.

       Tcl's  dual-ported values provide a general-purpose mechanism for stor-
       ing 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 manipu-
       lated 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  representation  is  immediately
       available.   The  compiler itself uses Tcl values to cache the instruc-
       tion 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 representa-
       tion 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 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 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_GetStringFro-
       mObj 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
       significantly reduces storage requirements because some values 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 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_Obj {
                  int refCount;
                  char *bytes;
                  int 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;
                  } internalRep;
              } Tcl_Obj;

       The bytes and the length members together hold a value'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_Get-
       String to get a value's string representation.  If bytes is  NULL,  the
       string representation is invalid.

       A value's type manages its internal representation.  The member typePtr
       points to the Tcl_ObjType structure that describes the type.  If  type-
       Ptr 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 num-
       ber,  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, 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  a  value's
       storage.   It holds the count of active references to the value.  Main-
       taining the correct reference count is a key responsibility  of  exten-
       sion  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  directly; 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_New-
       StringObj respectively.  A value's string value is gotten with Tcl_Get-
       StringFromObj  or  Tcl_GetString and changed with Tcl_SetStringObj.  If
       the value is later passed to a procedure  like  Tcl_GetIntFromObj  that
       requires  a specific internal representation, the procedure will create
       one and set the value's typePtr.  The internal representation  is  com-
       puted  from  the  string representation.  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_GetStringFromObj  or  Tcl_Get-
       String 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_GetBooleanFro-
       mObj  or  Tcl_ListObjIndex.  Programmers that implement their own value
       types must check for invalid representations and  mark  representations
       invalid  when necessary.  The procedure Tcl_InvalidateStringRep is used
       to mark a value's string representation invalid and to free any storage
       associated with the old string representation.

       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  ele-
       ment  from the value.  The same value holding the same string value can
       have several different internal  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 concerned 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 type-
       Ptr.  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_GetIntFromObj.   This procedure checks whether the value is already
       an integer value.  Since it is not, it converts the  value  by  setting
       the  value's internal 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 representation.

              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 deter-
       mine when a value is no longer needed and can safely be freed.  A value
       just  created  by  Tcl_NewObj  or Tcl_NewStringObj has refCount 0.  The
       macro Tcl_IncrRefCount increments the reference count when a new refer-
       ence  to  the  value is created.  The macro Tcl_DecrRefCount decrements
       the count when a reference is no longer needed and, if the value's ref-
       erence  count drops to zero, frees its storage.  A value shared by dif-
       ferent code or data structures has refCount greater than 1.  Increment-
       ing  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
       assigns the call's argument values 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  refer-
       ence count.  When a value'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 a
       value's value immediately and do not retain  a  pointer  to  the  value
       after  they return.  However, if they do retain a pointer to a value 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 values such as those for lap-
       pend 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  lin-
       sert.   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
       variable's  value  is  shared  before  incrementing  the integer in its
       internal representation.  If it is shared, it needs  to  duplicate  the
       value  in  order  to  avoid  accidentally changing values in other data
       structures.


SEE ALSO

       Tcl_ConvertToType(3),    Tcl_GetIntFromObj(3),    Tcl_ListObjAppendEle-
       ment(3),  Tcl_ListObjIndex(3),  Tcl_ListObjReplace(3), Tcl_RegisterObj-
       Type(3)


KEYWORDS

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



Tcl                                   8.5                           Tcl_Obj(3)

tcl 8.6.8 - Generated Sat Jan 6 09:17:56 CST 2018
© manpagez.com 2000-2024
Individual documents may contain additional copyright information.