diff options
author | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-03-08 21:27:18 +0100 |
---|---|---|
committer | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-03-08 21:27:18 +0100 |
commit | 5b25b7b7d2ba6d7daee0a8920278dcb000896a76 (patch) | |
tree | 0d0c4f0d13d8486cf01838d9084396676c8deeb8 | |
parent | 25e162cbf64763245def4d11b4be40ced11ee330 (diff) |
the extension callback functions are no lambdas, and can no longer be passed to the constructor, but have to be set with special callback functions, documentation updated too
-rw-r--r-- | documentation/extension-lifetime.html | 109 | ||||
-rw-r--r-- | include/extension.h | 55 | ||||
-rw-r--r-- | src/extension.cpp | 64 |
3 files changed, 148 insertions, 80 deletions
diff --git a/documentation/extension-lifetime.html b/documentation/extension-lifetime.html index 10ce12a..4647bec 100644 --- a/documentation/extension-lifetime.html +++ b/documentation/extension-lifetime.html @@ -7,40 +7,41 @@ </p> <p> After this get_module() call, your extension is loaded and will be used to handle - <i>multiple pageviews</i>. This is an important difference between standard + <i>multiple</i> pageviews. This is an important difference between standard PHP scripts and native extensions, because standard PHP scripts handle only a single - pageview. Extension can be used to serve multiple pageviews after - each other. + pageview. But extensions serve multiple pageviews after each other. </p> <p> - This difference is especially important when you use global variables. Global - variables are initialized when the extension is loaded - and not at the beginning - of each pageview. Changes that you make to global variables keep their value, - and subsequent requests will see the updated value. If you do not want this, - you can register callback functions that get called in front of each - request and right after each request. In these callback you can then - re-initialize the global variables. + This difference is especially important if you use global <i>C++</i> variables. + Such global variables are initialized when the extension is loaded - and not at + the beginning of each pageview. Changes that you make to global variables keep + their value, and subsequent requests will therefore see this updated value. +</p> +<p> + This, by the way, only happens to global C++ variables. The Php::GLOBALS object, + with all the global PHP variables, is re-initialized at the beginning of + each request. You do not have to worry about changes that you make to these + global PHP variables: at the beginning of the next request, you will have a + fresh and new Php::GLOBALS object, and the changes that you made during the + previous request are no longer stored in it. +</p> +<p> + Back to the global C++ variables. If you want to reset a global variable + at the beginning of a new request, you can register a special callback function + that gets called in front of each request. </p> <p> <pre class="language-c++"><code>#include <phpcpp.h> -#include <iostream> - -/** - * Global value that keeps track of the number - * of requests that have been handled - * @var int - */ -int requestCount = 0; /** - * Global value that stores the number of times + * Global variable that stores the number of times * the function updateCounters() has been called in total * @var int */ int invokeTotalCount = 0; /** - * Global value that keeps track how many times the + * Global variable that keeps track how many times the * function updateCounters() was called during the * current request * @var int @@ -75,39 +76,59 @@ extern "C" { // the extension object static Php::Extension extension("my_extension", "1.0"); - // install a callback function that is called when the PHP engine - // is fully initialized - extension.onReady([]() { - - // set global variables to their initial values - requestCount = 0; - invokeTotalCount = 0; - }); - - // install a callback that is called at the beginning of each - // request + // install a callback that is called at the beginning + // of each request extension.onRequest([]() { // re-initialize the counter invokeDuringRequestCount = 0; }); - // install a callback that is called after each request - extension.onCleanup([]() { - - // @todo add your own implementation - - }); - - // install a callback that is called when the Zend engine - // is closing down - extension.onFinalize([]() { - - // @todo add your own implementation - }); + // add the updateCounter method to the extension + extension.add("updateCounter", updateCounter); // return the extension details return extension; } }</code></pre> </p> +<p> + The Php::Extension class has a method onRequest() that is used in the + above example to register a callback function. This callback is called right + before every pageview/request. As you can see in the example, it is + permitted to use lambda functions. In the above example the global variable + invokeDuringRequestCount is re-initialized. +</p> +<p> + The onRequest() is not the only callback that can be registered. There are + four different callbacks on*() methods that you can call to register callbacks. +</p> +<p> + <ul> + <li>onStartup(const std::function<void()> &callback);</li> + <li>onRequest(const std::function<void()> &callback);</li> + <li>onIdle(const std::function<void()> &callback);</li> + <li>onShutdown(const std::function<void()> &callback);</li> + </ul> +</p> +<p> + The startup callback is called when the Zend engine has loaded your extension + and all functions and classes in it were registered. If you want to initialize + additional variables in your extension before the functions are going to get called, + you can use the onStartup() function to register a callback to run this + initialization code. +</p> +<p> + After the extension is initialized, requests will be processed by it. In the + example above we've used the onRequest() method to register a callback that is + called in front of each request. There is also a callback that gets called + <i>after</i> each request, when the extension moves to an idle state - waiting + for the next request. This callback can be registered with the onIdle() + method on the Php::Extension object. +</p> +<p> + The fourth callback that you can register is a callback that gets called + right before PHP shuts down. If there is anything to clean up, you can install + such a callback and run the cleanup code from it. +</p> +
\ No newline at end of file diff --git a/include/extension.h b/include/extension.h index 42bbff2..ca7e807 100644 --- a/include/extension.h +++ b/include/extension.h @@ -69,10 +69,10 @@ public: * * @param callback */ - void onReady(const Callback &callback) + void onStartup(const Callback &callback) { // copy callback - _onReady = callback; + _onStartup = callback; } /** @@ -83,10 +83,10 @@ public: * * @param callback */ - void onFinalize(const Callback &callback) + void onShutdown(const Callback &callback) { // copy callback - _onFinalize = callback; + _onShutdown = callback; } /** @@ -110,13 +110,15 @@ public: * * The callback will be called after _each_ request, so that you can clean up * certain things and make your extension ready to handle the next request. + * This method is called onIdle because the extension is idle in between + * requests. * * @param callback */ - void onCleanup(const Callback &callback) + void onIdle(const Callback &callback) { // copy callback - _onCleanup = callback; + _onIdle = callback; } /** @@ -155,7 +157,7 @@ private: * pageviews are going to be handled * @var Callback */ - Callback _onReady; + Callback _onStartup; /** * Callback that is called in front of each request @@ -167,26 +169,45 @@ private: * Callback that is called right after each request * @var Callback */ - Callback _onCleanup; + Callback _onIdle; /** * Callback that is called right before the engine is closing down * @var Callback */ - Callback _onFinalize; - + Callback _onShutdown; + /** - * Callback that is called before each request - * @var request_callback + * Function that is called when the extension initializes + * @param type Module type + * @param number Module number + * @return int 0 on success */ - request_callback _start; - + static int onStartup(int type, int module_number); + /** - * Callback that is called after each request - * @var request_callback + * Function that is called when the extension is about to be stopped + * @param type Module type + * @param number Module number + * @return int */ - request_callback _stop; + static int onShutdown(int type, int module_number); + /** + * Function that is called when a request starts + * @param type Module type + * @param number Module number + * @return int 0 on success + */ + static int onRequest(int type, int module_number); + + /** + * Function that is called when a request is ended + * @param type Module type + * @param number Module number + * @return int 0 on success + */ + static int onIdle(int type, int module_number); }; /** diff --git a/src/extension.cpp b/src/extension.cpp index 89ec3b9..3f29d9c 100644 --- a/src/extension.cpp +++ b/src/extension.cpp @@ -81,7 +81,7 @@ static int match_module(_zend_module_entry *entry) * @param number * @return Extension* */ -static Extension *extension(int number) +static Extension *find(int number) { // do we already have an extension with this number? auto iter = number2extension.find(number); @@ -104,13 +104,22 @@ static Extension *extension(int number) * @param number Module number * @return int 0 on success */ -static int extension_startup(INIT_FUNC_ARGS) +int Extension::onStartup(int type, int module_number) { // initialize and allocate the "global" variables ZEND_INIT_MODULE_GLOBALS(phpcpp, init_globals, NULL); - // initialize the extension - return BOOL2SUCCESS(extension(module_number)->initialize()); + // get the extension + Extension *extension = find(module_number); + + // initialize namespace + extension->initialize(""); + + // is the callback registered? + if (extension->_onStartup) extension->_onStartup(); + + // done + return BOOL2SUCCESS(true); } /** @@ -119,10 +128,16 @@ static int extension_startup(INIT_FUNC_ARGS) * @param number Module number * @return int */ -static int extension_shutdown(SHUTDOWN_FUNC_ARGS) +int Extension::onShutdown(int type, int module_number) { - // finalize the extension - return BOOL2SUCCESS(extension(module_number)->finalize()); + // get the extension + Extension *extension = find(module_number); + + // is the callback registered? + if (extension->_onShutdown) extension->_onShutdown(); + + // done + return BOOL2SUCCESS(true); } /** @@ -131,10 +146,16 @@ static int extension_shutdown(SHUTDOWN_FUNC_ARGS) * @param number Module number * @return int 0 on success */ -static int request_startup(INIT_FUNC_ARGS) +int Extension::onRequest(int type, int module_number) { - // start the request - return extension(module_number)->startRequest(); + // get the extension + Extension *extension = find(module_number); + + // is the callback registered? + if (extension->_onRequest) extension->_onRequest(); + + // done + return BOOL2SUCCESS(true); } /** @@ -143,10 +164,16 @@ static int request_startup(INIT_FUNC_ARGS) * @param number Module number * @return int 0 on success */ -static int request_shutdown(INIT_FUNC_ARGS) +int Extension::onIdle(int type, int module_number) { - // end the request - return BOOL2SUCCESS(extension(module_number)->endRequest()); + // get the extension + Extension *extension = find(module_number); + + // is the callback registered? + if (extension->_onIdle) extension->_onIdle(); + + // done + return BOOL2SUCCESS(true); } /** @@ -156,8 +183,7 @@ static int request_shutdown(INIT_FUNC_ARGS) * @param start Request start callback * @param stop Request stop callback */ -Extension::Extension(const char *name, const char *version, request_callback start, request_callback stop) : - Namespace(""), _start(start), _stop(stop) +Extension::Extension(const char *name, const char *version) : Namespace("") { // keep extension pointer based on the name name2extension[name] = this; @@ -177,10 +203,10 @@ Extension::Extension(const char *name, const char *version, request_callback sta _entry->deps = NULL; // dependencies on other modules _entry->name = name; // extension name _entry->functions = NULL; // functions supported by this module (none for now) - _entry->module_startup_func = extension_startup; // startup function for the whole extension - _entry->module_shutdown_func = extension_shutdown; // shutdown function for the whole extension - _entry->request_startup_func = request_startup; // startup function per request - _entry->request_shutdown_func = request_shutdown; // shutdown function per request + _entry->module_startup_func = &Extension::onStartup; // startup function for the whole extension + _entry->module_shutdown_func = &Extension::onShutdown; // shutdown function for the whole extension + _entry->request_startup_func = &Extension::onRequest; // startup function per request + _entry->request_shutdown_func = &Extension::onIdle; // shutdown function per request _entry->info_func = NULL; // information for retrieving info _entry->version = version; // version string _entry->globals_size = 0; // size of the global variables |