summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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