Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
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 re-
				     sult 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 al-
       ways 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_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
       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  re-
       claim 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 al-
       ways have a null	byte after the last data byte, at offset length;  this
       allows string representations to	be treated as conventional null-termi-
       nated C strings.	 C programs use	Tcl_GetStringFromObj and Tcl_GetString
       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 ar-
       bitrary 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 re-
       fCount 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  se-
       quence 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 in-
       ternal  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 af-
       ter 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  in-
       ternal  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)

NAME | SYNOPSIS | ARGUMENTS | INTRODUCTION | THE TCL_OBJ STRUCTURE | EXAMPLE OF THE LIFETIME OF A VALUE | STORAGE MANAGEMENT OF VALUES | SEE ALSO | KEYWORDS

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=Tcl_DecrRefCount.tcl86&sektion=3&manpath=FreeBSD+13.0-RELEASE+and+Ports>

home | help