Extension globals

Introduction to globals in a PHP extension

In a language such as C, a "global" variable is a variable that can be
accessed from any function without any extra declaration. These traditional
globals have a few drawbacks:

Barring any special options passed to the compiler, a global variable can
be accessed and changed by any piece of code anywhere in the program,
whether or not that code should be doing so.

A typical global variable is not thread safe.

The names of global variables are as global as the variables themselves.

A PHP extension's globals are more properly called the "extension state",
since most modules must remember what they're doing between function calls.
The "counter" extension is a perfect example of this need: The basic
interface calls for a counter with a persistent value. A programmer new to
Zend and PHP might do something like this in counter.c
to store that value:

On the surface this appears a viable solution, and indeed in a simple test
it would function correctly. However, there are a number of situations in
which more than one copy of PHP is running in the same thread, which means
more than one instance of the counter module. Suddenly these multiple
threads are sharing the same counter value, which is clearly undesirable.
Another problem shows itself when considering that another extension might
someday happen to have a global with the same name, and due to the rules of
C scoping, this has the potential to cause a compile failure, or worse, a
runtime error. Something more elaborate is needed, and so exists Zend's
support for thread-safe per-module globals.

Declaring module globals

Whether a module uses only a single global or dozens, they must be defined
in a structure, and that structure must be declared. There are some macros
that assist with doing so in a way that avoids name conflicts between
modules: ZEND_BEGIN_MODULE_GLOBALS(),
ZEND_END_MODULE_GLOBALS(), and
ZEND_DECLARE_MODULE_GLOBALS(). All three take as a
parameter the short name of the module, which in the case of the counter
module is simply "counter". Here is the global structure
declaration from php_counter.h:

Accessing module globals

As discussed above, per-module globals are declared inside a C structure
whose name is obscured by Zend macros. As a result, the ideal way to access
members of this structure is by the use of further macros. Accordingly, most
if not all extensions which have globals have a declaration like this
somewhere in their header file:

Nota:
This could have been generalized into a macro of its own by the Zend API,
but as of PHP 5.3 (and PHP 6 at the time of this writing), that hasn't
happened. The global accessor construct is written into the header by
ext_skel and thus is generally left alone by extension
writers, unless they wish to change the name of the accessor macro.

Nota:
COUNTER_G was the name given to the macro by
ext_skel, but it's not necessary for it to have that
name and could just as easily be called FOO instead.

Any code in the counter extension that accesses a global must thus wrap it
in the macro COUNTER_G.

Avviso

Any function which accesses globals must either be declared by Zend macros,
have TSRMLS_DC as its last argument, or call the macro
TSRMLS_FETCH before accessing the globals. See
the TSRM documentation for
more information.

So with all of that in mind, here is our new version of the
counter_get():