summaryrefslogtreecommitdiff
path: root/apidoc-zend.txt
diff options
context:
space:
mode:
authorZeev Suraski <zeev@php.net>1999-04-24 16:57:46 +0000
committerZeev Suraski <zeev@php.net>1999-04-24 16:57:46 +0000
commit1ab3e00bc06fbe26c4d05533b9ffa61c36b15258 (patch)
tree4429dd84372f0663f021ab9f94fc57c70182d13c /apidoc-zend.txt
parentf6971f17a96643e6f1a7640a3f282793b758ce37 (diff)
downloadphp-git-1ab3e00bc06fbe26c4d05533b9ffa61c36b15258.tar.gz
Add my API letters to the CVS
Diffstat (limited to 'apidoc-zend.txt')
-rw-r--r--apidoc-zend.txt276
1 files changed, 276 insertions, 0 deletions
diff --git a/apidoc-zend.txt b/apidoc-zend.txt
new file mode 100644
index 0000000000..6472729f04
--- /dev/null
+++ b/apidoc-zend.txt
@@ -0,0 +1,276 @@
+Following is a merge of two letters I sent to php4beta@lists.php.net,
+describing the changes in API between PHP 3.0 and PHP 4.0 (Zend).
+This file is by no means thorough documentation of the PHP API,
+and is intended for developers who are familiar with the PHP 3.0 API,
+and want to port their code to PHP 4.0, or take advantage of its new
+features. For highlights about the PHP 3.0 API, consult apidoc.txt.
+
+Zeev
+
+--------------------------------------------------------------------------
+
+I'm going to try to list the important changes in API and programming
+techniques that are involved in developing modules for PHP4/Zend, as
+opposed to PHP3. Listing the whole PHP4 API is way beyond my scope here,
+it's mostly a 'diff' from the apidoc.txt, which you're all pretty familiar
+with.
+An important note that I neglected to mention yesterday - the php4 tree is
+based on the php 3.0.5 tree, plus all 3.0.6 patches hand-patched into it.
+Notably, it does NOT include any 3.0.7 patches. All of those have to be
+reapplied, with extreme care - modules should be safe to patch (mostly),
+but anything that touches the core or main.c will almost definitely require
+changes in order to work properly.
+
+[1] Symbol Tables
+
+One of the major changes in Zend involves changing the way symbols tables
+work. Zend enforces reference counting on all values and resources. This
+required changes in the semantics of the hash tables that implement symbol
+tables. Instead of storing pval in the hashes, we now store pval *. All
+of the API functions in Zend were changed in a way that this change is
+completely transparent. However, if you've used 'low level' hash functions
+to access or update elements in symbol tables, your code will require
+changes. Following are two simple examples, one demonstrates the
+difference between PHP3 and Zend when reading a symbol's value, and the
+other demonstrates the difference when writing a value.
+
+php3_read()
+{
+ pval *foo;
+
+ _php3_hash_find(ht, "foo", sizeof("foo"), &foo);
+ /* foo->type is the type and foo->value is the value */
+}
+
+
+php4_read()
+{
+ pval **foo;
+
+ _php3_hash_find(ht, "foo", sizeof("foo"), &foo);
+ /* (*foo)->type is the type and (*foo)->value is the value */
+}
+
+---
+
+php3_write()
+{
+ pval newval;
+
+ newval.type = ...;
+ newval.value = ...;
+ _php3_hash_update(ht, "bar", sizeof("bar"), &newval, sizeof(pval), NULL);
+}
+
+php4_write()
+{
+ pval *newval = (pval *) emalloc(sizeof(pval));
+
+ newval->refcount=1;
+ newval->is_ref=0;
+ newval->type = ...;
+ newval->value = ...;
+ _php3_hash_update(ht, "bar", sizeof("bar"), &newval, sizeof(pval *), NULL);
+}
+
+
+[2] Resources
+
+One of the 'cute' things about the reference counting support is that it
+completely eliminates the problem of resource leaking. A simple loop that
+included '$result = mysql_query(...)' in PHP leaked unless the user
+remembered to run mysql_free($result) at the end of the loop body, and
+nobody really did. In order to take advantage of the automatic resource
+deallocation upon destruction, there's virtually one small change you need
+to conduct. Change the result type of a resource that you want to destroy
+itself as soon as its no longer referenced (just about any resource I can
+think of) as IS_RESOURCE, instead of as IS_LONG. The rest is magic.
+
+A special treatment is required for SQL modules that follow MySQL's
+approach for having the link handle as an optional argument. Modules that
+follow the MySQL module model, store the last opened link in a global
+variable, that they use in case the user neglects to explicitly specify a
+link handle. Due to the way referenec counting works, this global
+reference is just like any other reference, and must increase that SQL link
+resource's reference count (otherwise, it will be closed prematurely).
+Simply, when you set the default link to a certain link, increase that
+link's reference count by calling zend_list_addref().
+As always, the MySQL module is the one used to demonstrate 'new
+technology'. You can look around it and look for IS_RESOURCE, as well as
+zend_list_addref(), to see a clear example of how the new API should be used.
+
+
+[3] Thread safety issues
+
+I'm not going to say that Zend was designed with thread safety in mind, but
+from some point, we've decided upon several guidelines that would make the
+move to thread safety much, much easier. Generally, we've followed the PHP
+3.1 approach of moving global variables to a structure, and encapsulating
+all global variable references within macros. There are three main
+differences:
+1. We grouped related globals in a single structure, instead of grouping
+all globals in one structure.
+2. We've used much, much shorter macro names to increase the readability
+of the source code.
+3. Regardless of whether we're compiling in thread safe mode or not, all
+global variables are *always* stored in a structure. For example, you
+would never have a global variable 'foo', instead, it'll be a property of a
+global structure, for example, compiler_globals.foo. That makes
+development much, much easier, since your code will simply not compile
+unless you remember to put the necessary macro around foo.
+
+To write code that'll be thread safe in the future (when we release our
+thread safe memory manager and work on integrating it), you can take a look
+at zend_globals.h. Essentially, two sets of macros are defined, one for
+thread safe mode, and one for thread unsafe mode. All global references
+are encapsulated within ???G(varname), where ??? is the appropriate prefix
+for your structure (for example, so far we have CG(), EG() and AG(), which
+stand for the compiler, executor and memory allocator, respectively).
+When compiling with thread safety enabled, each function that makes use of
+a ???G() macro, must obtain the pointer to its copy of the structure. It
+can do so in one of two forms:
+1. It can receive it as an argument.
+2. It can fetch it.
+
+Obviously, the first method is preferable since it's much quicker.
+However, it's not always possible to send the structure all the way to a
+particular function, or it may simply bloat the code too much in some
+cases. Functions that receive the globals as an argument, should look like
+this:
+
+rettype functioname(???LS_D) <-- a function with no arguments
+rettype functioname(type arg1, ..., type argn ???LS_DC) <-- a funciton with
+arguments
+
+Calls to such functions should look like this:
+functionname(???LS_C) <-- a function with no arguments
+functionname(arg1, ..., argn ???LS_CC) <-- a function with arguments
+
+LS stands for 'Local Storage', _C stands for Call and _CC stands for Call
+Comma, _D stands for Declaration and _DC stands for Declaration Comma.
+Note that there's NO comma between the last argument and ???LS_DC or ???LS_CC.
+
+In general, every module that makes use of globals should use this approach
+if it plans to be thread safe.
+
+
+[4] Generalized INI support
+
+The code comes to solve several issues:
+
+a. The ugly long block of code in main.c that reads values from the
+cfg_hash into php3_ini.
+b. Get rid of php3_ini. The performance penalty of copying it around all
+the time in the Apache module probably wasn't too high, but
+psychologically, it annoyed me :)
+c. Get rid of the ugly code in mod_php3.c, that also reads values from
+Apache directives and puts them into the php3_ini structure.
+d. Generalize all the code so that you only have to add an entry in one
+single place and get it automatically supported in php3.ini, Apache, Win32
+registry, runtime function ini_get() and ini_alter() and any future method
+we might have.
+e. Allow users to easily override *ANY* php3.ini value, except for ones
+they're not supposed to, of course.
+
+I'm happy to say that I think I pretty much reached all goals. php_ini.c
+implements a mechanism that lets you add your INI entry in a single place,
+with a default value in case there's no php3.ini value. What you get by
+using this mechanism:
+
+1. Automatic initialization from php3.ini if available, or from the
+default value if not.
+2. Automatic support in ini_alter(). That means a user can change the
+value for this INI entry at runtime, without you having to add in a single
+line of code, and definitely no additional function (for example, in PHP3,
+we had to add in special dedicated functions, like
+set_magic_quotes_runtime() or the likes - no need for that anymore).
+3. Automatic support in Apache .conf files.
+4. No need for a global php3_ini-like variable that'll store all that
+info. You can directly access each INI entry by name, in runtime. 'Sure,
+that's not revolutionary, it's just slow' is probably what some of you
+think - which is true, but, you can also register a callback function that
+is called each time your INI entry is changed, if you wish to store it in a
+cached location for intensive use.
+5. Ability to access the current active value for a given INI entry, and
+the 'master' value.
+
+Of course, (2) and (3) are only applicable in some cases. Some entries
+shouldn't be overriden by users in runtime or through Apache .conf files -
+you can, of course, mark them as such.
+
+
+So, enough hype, how does it work.
+
+Essentially:
+
+static PHP_INI_MH(OnChangeBar); /* declare a message handler for a change
+in "bar" */
+
+PHP_INI_BEGIN()
+ PHP_INI_ENTRY("foo", "1", PHP_INI_ALL, NULL, NULL)
+ PHP_INI_ENTRY("bar", "bah", PHP_INI_SYSTEM, OnChangeBar, NULL)
+PHP_INI_END()
+
+static PHP_INI_MH(OnChangeBar)
+{
+ a_global_var_for_bar = new_value;
+ return SUCCESS;
+}
+
+int whatever_minit(INIT_FUNC_ARGS)
+{
+ ...
+ REGISTER_INI_ENTRIES();
+ ...
+}
+
+
+int whatever_mshutdown(SHUTDOWN_FUNC_ARGS)
+{
+ ...
+ UNREGISTER_INI_ENTRIES();
+ ...
+}
+
+
+and that's it. Here's what it does. As you can probably guess, this code
+registers two INI entries - "foo" and "bar". They're given defaults "1"
+and "bah" respectively - note that all defaults are always given as
+strings. That doesn't reduce your ability to use integer values, simply
+specify them as strings. "foo" is marked so that it can be changed by
+anyone at any time (PHP_INI_ALL), whereas "foo" is marked so it can be
+changed only at startup in the php3.ini only, presumably, by the system
+administrator (PHP_INI_SYSTEM).
+When "foo" changes, no function is called. Access to it is done using the
+macros INI_INT("foo"), INI_FLT("foo") or INI_STR("foo"), which return a
+long, double or char * respectively (strings that are returned aren't
+duplicated - if they're manipulated, you must duplicate them first). You
+can also access the original value (the 'master' value, in case one of them
+was overriden by a user) using another pair of macros:
+INI_ORIG_INT("foo"), INI_ORIG_FLT("foo") and INI_ORIG_STR("foo").
+
+When "bar" changes, a special message handler is called, OnBarChange().
+Always declare those message handlers using PHP_INI_MH(), as they might
+change in the future. Message handlers are called as soon as an ini entry
+initializes or changes, and allow you to cache a certain INI value in a
+quick C structure. In this example, whenever "bar" changes, the new value
+is stored in a_global_var_for_bar, which is a global char * pointer,
+quickly accessible from other functions. Things get a bit more complicated
+when you want to implement a thread-safe module, but it's doable as well.
+Message handlers may return SUCCESS to acknowledge the new value, or
+FAILURE to reject it. That enables you to reject invalid values for some
+INI entries if you want. Finally, you can have a pointer passed to your
+message handler - that's the fifth argument to PHP_INI_ENTRY(). It is
+passed as mh_arg to the message handler.
+
+Remember that for certain values, there's really no reason to mess with a
+callback function. A perfect example for this are the syntax highlight
+colors, which no longer have a dedicated global C slot that stores them,
+but instead, are fetched from the php_ini hash on demand.
+
+"As always", for a perfect working example of this mechanism, consult
+functions/mysql.c. This module uses the new INI entry mechanism, and was
+also converted to be thread safe in general, and in its php_ini support in
+particular. Converting your modules to look like this for thread safety
+isn't a bad idea (not necessarily now, but in the long run).
+