summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-08 21:27:18 +0100
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-08 21:27:18 +0100
commit5b25b7b7d2ba6d7daee0a8920278dcb000896a76 (patch)
tree0d0c4f0d13d8486cf01838d9084396676c8deeb8
parent25e162cbf64763245def4d11b4be40ced11ee330 (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.html109
-rw-r--r--include/extension.h55
-rw-r--r--src/extension.cpp64
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 &lt;phpcpp.h&gt;
-#include &lt;iostream&gt;
-
-/**
- * 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&lt;void()&gt; &callback);</li>
+ <li>onRequest(const std::function&lt;void()&gt; &callback);</li>
+ <li>onIdle(const std::function&lt;void()&gt; &callback);</li>
+ <li>onShutdown(const std::function&lt;void()&gt; &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