Clause-Local Variables
You can also define D variables whose storage is reused for each D
program clause. Clause-local variables are similar to automatic variables in a C, C++,
or Java language program that are active during each invocation of a function. Like
all D program variables, clause-local variables are created on their first assignment. These
variables can be referenced and assigned by applying the -> operator to the
special identifier this:
BEGIN
{
this->secs = timestamp / 1000000000;
...
}
If you want to explicitly declare a clause-local variable before using it, you
can do so using the this keyword:
this int x; /* an integer clause-local variable */
this char c; /* a character clause-local variable */
BEGIN
{
this->x = 123;
this->c = 'D';
}
Clause-local variables are only active for the lifetime of a given probe clause.
After DTrace performs the actions associated with your clauses for a given probe,
the storage for all clause-local variables is reclaimed and reused for the next
clause. For this reason, clause-local variables are the only D variables that are
not initially filled with zeroes. Note that if your program contains multiple clauses
for a single probe, any clause-local variables will remain intact as the clauses
are executed, as shown in the following example:
Example 3-2 clause.d: Clause-local Variables
int me; /* an integer global variable */
this int foo; /* an integer clause-local variable */
tick-1sec
{
/*
* Set foo to be 10 if and only if this is the first clause executed.
*/
this->foo = (me % 3 == 0) ? 10 : this->foo;
printf("Clause 1 is number %d; foo is %d\n", me++ % 3, this->foo++);
}
tick-1sec
{
/*
* Set foo to be 20 if and only if this is the first clause executed.
*/
this->foo = (me % 3 == 0) ? 20 : this->foo;
printf("Clause 2 is number %d; foo is %d\n", me++ % 3, this->foo++);
}
tick-1sec
{
/*
* Set foo to be 30 if and only if this is the first clause executed.
*/
this->foo = (me % 3 == 0) ? 30 : this->foo;
printf("Clause 3 is number %d; foo is %d\n", me++ % 3, this->foo++);
}
Because the clauses are always executed in program order, and because clause-local variables
are persistent across different clauses enabling the same probe, running the above program
will always produce the same output:
# dtrace -q -s clause.d
Clause 1 is number 0; foo is 10
Clause 2 is number 1; foo is 11
Clause 3 is number 2; foo is 12
Clause 1 is number 0; foo is 10
Clause 2 is number 1; foo is 11
Clause 3 is number 2; foo is 12
Clause 1 is number 0; foo is 10
Clause 2 is number 1; foo is 11
Clause 3 is number 2; foo is 12
Clause 1 is number 0; foo is 10
Clause 2 is number 1; foo is 11
Clause 3 is number 2; foo is 12
^C
While clause-local variables are persistent across clauses enabling the same probe, their values
are undefined in the first clause executed for a given probe. Be sure
to assign each clause-local variable an appropriate value before using it, or your
program may have unexpected results.
Clause-local variables can be defined using any scalar variable type, but associative arrays
may not be defined using clause-local scope. The scope of clause-local variables only
applies to the corresponding variable data, not to the name and type identity
defined for the variable. Once a clause-local variable is defined, this name and
type signature may be used in any subsequent D program clause. You cannot
rely on the storage location to be the same across different clauses.
You can use clause-local variables to accumulate intermediate results of calculations or as
temporary copies of other variables. Access to a clause-local variable is much faster
than access to an associative array. Therefore, if you need to reference an
associative array value multiple times in the same D program clause, it is
more efficient to copy it into a clause-local variable first and then reference
the local variable repeatedly.