summaryrefslogtreecommitdiff
path: root/documentation
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-25 11:16:36 +0100
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-25 11:16:36 +0100
commit30c5021cf56bb6fc8f42f38c688ff3f7b223f7b0 (patch)
treee699ff67725209fba818a9c159f184c411162b66 /documentation
parentaf85f97c832ba318373db3ad6df72ebedbad1a1d (diff)
update documentation about threads
Diffstat (limited to 'documentation')
-rw-r--r--documentation/extension-callbacks.html81
-rw-r--r--documentation/install.html33
2 files changed, 80 insertions, 34 deletions
diff --git a/documentation/extension-callbacks.html b/documentation/extension-callbacks.html
index 5c93736..defa550 100644
--- a/documentation/extension-callbacks.html
+++ b/documentation/extension-callbacks.html
@@ -130,4 +130,83 @@ extern "C" {
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
+<h2 id="multi-threading">Watch out for multi-threading</h2>
+<p>
+ If your extension runs on a multi-threaded PHP installation, you need to take
+ extra care. Most PHP installations (Apache, CLI scripts, etc) serve one
+ request at a time, sequentially. There are however PHP installations that use
+ multi-threading and that can serve multiple requests in parallel. If your
+ extension runs on such an environment, you should be aware that your global
+ (and static!) variables can also be accessed by multiple threads at the same
+ time. It is your own responsibility to use technologies like std::mutex or
+ std::atomic to prevent race conditions and conflicts.
+</p>
+<p>
+ If your extension is compiled for a multi-threaded environment, the PHP-CPP
+ header files defines the macro ZTS. You can use this macro to check if you
+ do have to create special code to deal with threads.
+</p>
+<p>
+<pre class="language-c++"><code>#include &lt;phpcpp.h&gt;
+
+/**
+ * Global variable that store the number of times
+ * the function updateCounters() has been called in total
+ * @var int
+ */
+int invokeTotalCount = 0;
+
+#ifdef ZTS
+
+/**
+ * Mutex so that the 'invokeTotalCount' variable is only accessed
+ * by one process at a time
+ * @var std::mutex
+ */
+std::mutex invokeTotalMutex;
+
+#endif
+
+/**
+ * Native function that is callable from PHP
+ *
+ * This function updates a number of global variables that count
+ * the number of times a function was called
+ */
+void updateCounters()
+{
+#ifdef ZTS
+
+ // lock the mutex
+ std::unique_lock&lt;std::mutex&gt; lock(invokeTotalMutex);
+
+#endif
+
+ // increment counters
+ invokeTotalCount++;
+}
+</code></pre>
+</p>
+<p>
+ Another important thing to realize is that PHP also does this locking
+ internally. If you call a PHP function from you C++ code (like Php::Value("myFunction")()),
+ or when you access a PHP variable in the Php::GLOBALS array (or one of the
+ other super-globals), PHP has to lock something to ensure that no
+ other thread is accessing the same information at the same time. These operations
+ can be expensive.
+</p>
+<p>
+ Good rules of thumb for writing native extensions with PHP-CPP therefore
+ are:
+ <ol type="1">
+ <li>Do not use global variables</li>
+ <li>Only call other <i>native</i> functions, and don't call back to PHP</li>
+ </ol>
+</p>
+<p>
+ In our opinion, these rules should not not be limiting for you. The use of global
+ variables is not considered a very good software design, so you were probably
+ not even using them, and the reason why you are writing a native extension is
+ because you want to get away from PHP. Calling back to (slow) PHP is the last
+ thing you want to do when your application has finally reached native code.
+</p>
diff --git a/documentation/install.html b/documentation/install.html
index d1d1cb0..a498acb 100644
--- a/documentation/install.html
+++ b/documentation/install.html
@@ -15,39 +15,6 @@
installation instructions and include other platforms as well.
</p>
-<h2 id="limitations">Limitations</h2>
-<p>
- At this moment, PHP-CPP only supports single-threaded PHP installations.
- Web servers come in a number forms: there are the ones that handle each
- page request in different process, and the ones that handle each page request
- in the same process, but in a different thread. If you're using such a
- multi-threaded PHP installation, you can not use the PHP-CPP library. Most
- installations are single-threaded however, so this should not be a show stopper.
-</p>
-<p>
- Are you not sure whether you have a single-threaded or multi-threaded PHP
- environment? Just try to compile the PHP-CPP library, if you see a zillion
- errors, you can be pretty sure that this is because of your installation
- is multi-threaded.
-</p>
-<p>
- The reason why we've chosen not to support multi-threaded PHP installations
- lies in the fact that internally the Zend engine uses a very odd system
- to ensure thread safety. Essentially, they pass an additional parameter to
- each and every function call that holds a pointer-to-a-pointer with thread
- information that you can access with specific C macro's, and that you have
- to pass on to every other function call that you make. This makes life for
- extension writers much harder than is necessary - and is in total conflict
- with the core principle of the PHP-CPP library: to make life easy.
-</p>
-<p>
- However, if there is demand for, we will add support for multi-threaded PHP
- installations, and hopefully we can even keep the same simple C++ API as we
- have now.
-</p>
-
-
-
<h2 id="download">Download</h2>
<p>
Installation begins with downloading the source code. You can either