mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-16 08:58:56 +00:00
Whitespace, and a few typos
git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@327809 c90b9560-bf6c-de11-be94-00142212c4b1
This commit is contained in:
parent
d4cbcc71e6
commit
fb4f9b53fc
4 changed files with 255 additions and 139 deletions
|
@ -7,7 +7,10 @@
|
|||
|
||||
<preface xml:id="intro.pthreads">
|
||||
&reftitle.intro;
|
||||
<para>pthreads uses the well tested abilities of TSRM and PHP to provide compatible mult-threading capabilities.</para>
|
||||
<para>
|
||||
pthreads uses the well tested abilities of TSRM and PHP to
|
||||
provide compatible multi-threading capabilities.
|
||||
</para>
|
||||
</preface>
|
||||
|
||||
&reference.pthreads.setup;
|
||||
|
|
|
@ -11,14 +11,29 @@
|
|||
<!-- {{{ Cond intro -->
|
||||
<section xml:id="cond.intro">
|
||||
&reftitle.intro;
|
||||
<para>The following paragraph is taken from the Posix Thread documentation to explain the purpose of Condition Variables:</para>
|
||||
<para>
|
||||
Condition variables provide yet another way for threads to synchronize. While mutexes implement synchronization by controlling thread access to data, condition variables allow threads to synchronize based upon the actual value of data.
|
||||
Without condition variables, the programmer would need to have threads continually polling (possibly in a critical section), to check if the condition is met. This can be very resource consuming since the thread would be continuously busy in this activity. A condition variable is a way to achieve the same goal without polling.
|
||||
A condition variable is always used in conjunction with a mutex lock.
|
||||
The following paragraph is taken from the Posix Thread documentation to
|
||||
explain the purpose of Condition Variables:
|
||||
</para>
|
||||
<para>
|
||||
Condition variables provide yet another way for threads to synchronize.
|
||||
While mutexes implement synchronization by controlling thread access
|
||||
to data, condition variables allow threads to synchronize based upon
|
||||
the actual value of data. Without condition variables, the programmer
|
||||
would need to have threads continually polling (possibly in a critical
|
||||
section), to check if the condition is met. This can be very resource
|
||||
consuming since the thread would be continuously busy in this activity.
|
||||
A condition variable is a way to achieve the same goal without polling.
|
||||
A condition variable is always used in conjunction with a mutex lock.
|
||||
</para>
|
||||
<para>
|
||||
pthreads provides PHP with direct access to a carefully selected subset
|
||||
of Condition Variable functions.
|
||||
</para>
|
||||
<para>
|
||||
Because of their nature, the programmer must take care to destroy
|
||||
Condition Variable handles they are finished with.
|
||||
</para>
|
||||
<para>pthreads provides PHP with direct acces to a carefully selected subset of Condition Variable functions.</para>
|
||||
<para>Because of their nature, the programmer must take care to destroy Condition Variable handles they are finished with.</para>
|
||||
</section>
|
||||
<!-- }}} -->
|
||||
|
||||
|
|
|
@ -9,10 +9,8 @@
|
|||
<link xlink:href="&url.pecl.package;pthreads">&url.pecl.package;pthreads</link>
|
||||
</para>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<!-- Keep this comment at the end of the file
|
||||
Local variables:
|
||||
mode: sgml
|
||||
|
|
|
@ -8,164 +8,264 @@
|
|||
<example>
|
||||
<title>Hello World Example</title>
|
||||
<para>This HelloWorld example demonstrates how simple it is to define and execute Threads in PHP applications.</para>
|
||||
<programlisting role="php"><![CDATA[
|
||||
<?php
|
||||
class HelloWorld extends Thread {
|
||||
public function __construct($world){
|
||||
$this->world = $world;
|
||||
}
|
||||
<screen>
|
||||
<![CDATA[
|
||||
<?php
|
||||
class HelloWorld extends Thread {
|
||||
public function __construct($world) {
|
||||
$this->world = $world;
|
||||
}
|
||||
|
||||
public function run(){
|
||||
return sprintf("Hello %s", $this->world);
|
||||
}
|
||||
}
|
||||
$thread = new HelloWorld("World");
|
||||
if ($thread->start()) {
|
||||
printf("Thread #%lu says: %s\n", $thread->getThreadId(), $thread->join());
|
||||
}
|
||||
?>
|
||||
]]></programlisting>
|
||||
public function run() {
|
||||
return sprintf("Hello %s", $this->world);
|
||||
}
|
||||
}
|
||||
|
||||
$thread = new HelloWorld("World");
|
||||
|
||||
if ($thread->start()) {
|
||||
printf("Thread #%lu says: %s\n", $thread->getThreadId(), $thread->join());
|
||||
}
|
||||
?>
|
||||
]]>
|
||||
</screen>
|
||||
</example>
|
||||
</section>
|
||||
|
||||
<section role="examples">
|
||||
<example>
|
||||
<title>Synchronization</title>
|
||||
<para>The purpose of PHP is to generate content, having Threading in the toolbox makes more content available. But content is a relative subject, for this reason good control is needed over when a Thread is allowed to execute, or indeed, forced to wait.</para>
|
||||
<para>For example, a meta search engine may have to carry out the following:</para>
|
||||
<orderedlist>
|
||||
<listitem><para>Initiate a search with primary source of data</para></listitem>
|
||||
<listitem><para>Log results of API usage for statistical analysis</para></listitem>
|
||||
<listitem><para>Cache results to limit external API usage</para></listitem>
|
||||
<listitem><para>Query local databases to generate page content - recent searches etc</para></listitem>
|
||||
<listitem><para>Log results of local databse usage, HTTP usage, cache usage and possibly fall back to secondary source and goto 2;</para></listitem>
|
||||
<listitem><para>Generate content ( HTML ) from API output, xml/json etc</para></listitem>
|
||||
<listitem><para>Send content to client</para></listitem>
|
||||
</orderedlist>
|
||||
<para>In a multi-threaded design, the Thread delegated Task 2 cannot possibly run until Thread 1 has returned a result.</para>
|
||||
<para>In an extreme design, where each Task is allocated a Thread, Threads 2,3,4,5 and even 6 can all be run concurrently, but they all depend on Thread 1 returning content.</para>
|
||||
<para>pthreads includes an easy to use way to synchronize when Threads are allowed to execute, or forced to wait, to allow flexible, powerful multi-threading wether being used for a Search Engine or Administration ( ie. cron jobs ).</para>
|
||||
<programlisting role="php"><![CDATA[
|
||||
<?php
|
||||
class Task1 extends Thread {
|
||||
public function __construct($params){
|
||||
$this->params = $params;
|
||||
}
|
||||
<title>Synchronization</title>
|
||||
<para>
|
||||
The purpose of PHP is to generate content, having Threading in the toolbox
|
||||
makes more content available. But content is a relative subject, for this
|
||||
reason good control is needed over when a Thread is allowed to execute,
|
||||
or indeed, forced to wait.
|
||||
</para>
|
||||
<para>
|
||||
For example, a meta search engine may have to carry out the following:
|
||||
</para>
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Initiate a search with primary source of data
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Log results of API usage for statistical analysis
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Cache results to limit external API usage
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Query local databases to generate page content - recent searches etc
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Log results of local database usage, HTTP usage, cache usage and
|
||||
possibly fall back to secondary source and goto 2;
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Generate content ( HTML ) from API output, xml/json etc
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Send content to client
|
||||
</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
<para>
|
||||
In a multi-threaded design, the Thread delegated Task 2 cannot possibly run
|
||||
until Thread 1 has returned a result.
|
||||
</para>
|
||||
<para>
|
||||
In an extreme design, where each Task is allocated a Thread, Threads 2,3,4,5
|
||||
and even 6 can all be run concurrently, but they all depend on Thread 1
|
||||
returning content.
|
||||
</para>
|
||||
<para>
|
||||
pthreads includes an easy to use way to synchronize when Threads are allowed
|
||||
to execute, or forced to wait, to allow flexible, powerful multi-threading
|
||||
whether being used for a Search Engine or Administration ( ie. cron jobs ).
|
||||
</para>
|
||||
<screen>
|
||||
<![CDATA[
|
||||
<?php
|
||||
class Task1 extends Thread {
|
||||
public function __construct($params) {
|
||||
$this->params = $params;
|
||||
}
|
||||
|
||||
/* ... */
|
||||
/* ... */
|
||||
|
||||
public function run(){
|
||||
/* do some admin possibly here, maybe lookup local caches, check if the client is googlebot etc */
|
||||
if ($this->ensureAvailabiilty()) {
|
||||
$this->notify();
|
||||
|
||||
return $this->resultSet();
|
||||
}
|
||||
}
|
||||
}
|
||||
public function run() {
|
||||
|
||||
/* do some admin possibly here, maybe lookup local caches, check if the client is googlebot etc */
|
||||
if ($this->ensureAvailabiilty()) {
|
||||
$this->notify();
|
||||
return $this->resultSet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Task2 extends Thread {
|
||||
public function __construct($task1, $params){
|
||||
$this->task1 = $task1;
|
||||
$this->params = $params;
|
||||
}
|
||||
class Task2 extends Thread {
|
||||
public function __construct($task1, $params) {
|
||||
$this->task1 = $task1;
|
||||
$this->params = $params;
|
||||
}
|
||||
|
||||
/* ... */
|
||||
/* ... */
|
||||
|
||||
public function run(){
|
||||
$task1 = Thread::getThread($this->task1);
|
||||
if ($task1->wait()) {
|
||||
$this->createLogs();
|
||||
}
|
||||
}
|
||||
}
|
||||
public function run(){
|
||||
$task1 = Thread::getThread($this->task1);
|
||||
if ($task1->wait()) {
|
||||
$this->createLogs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$tasks = array();
|
||||
$tasks = array();
|
||||
$tasks[0] = new Task1($_POST);
|
||||
$tasks[1] = new Task2($tasks[0]->getThreadId(), $_POST);
|
||||
/* ... */
|
||||
|
||||
$tasks[0]=new Task1($_POST);
|
||||
$tasks[1]=new Task2($tasks[0]->getThreadId(), $_POST);
|
||||
/* ... */
|
||||
foreach ($tasks as $id => $task) {
|
||||
$task->start();
|
||||
}
|
||||
|
||||
foreach ($tasks as $id => $task) {
|
||||
$task->start();
|
||||
}
|
||||
|
||||
/* ... */
|
||||
?>
|
||||
]]></programlisting>
|
||||
<para>Using the wait/notify mechanism included in pthreads hides the complexity of using Mutex and Condition Variables to synchronize Threads, greatly simplifies readability and more importantly maintainability of an idea or implementation.</para>
|
||||
/* ... */
|
||||
?>
|
||||
]]>
|
||||
</screen>
|
||||
<para>
|
||||
Using the wait/notify mechanism included in pthreads hides the complexity of
|
||||
using Mutex and Condition Variables to synchronize Threads, greatly simplifies
|
||||
readability and more importantly maintainability of an idea or implementation.
|
||||
</para>
|
||||
</example>
|
||||
</section>
|
||||
|
||||
<section role="examples">
|
||||
<example>
|
||||
<title>Mutex and Condition Variables</title>
|
||||
<para>pthreads allows direct access to ( a subset of ) both of these features. The programmer should take care to destroy Mutex and Condition Variable handles that are no longer required for their logic.</para>
|
||||
<para>Mutex and Condition Variables are not destroyed on behalf of the programmer like other resources in PHP, as this would limit their usefulness in the context of multi-threading in SAPI environments.</para>
|
||||
<para>They are easily stored and passed around as they are represented as long numbers. Mutex and Condition Variables persist once allocated until they are explicitly destroyed.</para>
|
||||
<programlisting role="php"><![CDATA[
|
||||
<?php
|
||||
/* ... */
|
||||
if (Cond::broadcast($finished)) {
|
||||
Cond::destroy($finished);
|
||||
Mutex::destroy($signals);
|
||||
}
|
||||
?>
|
||||
]]></programlisting>
|
||||
<para>
|
||||
The snippet above shows a PHP script sending it's final broadcast to the Threads it has created and cleaning up the Condition Variable it created and used for the broadcast.
|
||||
Other Threads that were waiting for a signal on $finished were using $signals - waiting for a signal always requires a Mutex - and as the Condition Variable is no longer valid, the accompanying Mutex is also destroyed.
|
||||
</para>
|
||||
<warning>
|
||||
<para>Before the programmer attempts to use Condition Variables they should have knowledge of "Spurious Wakeups" as allowed for in the Posix Threads specification upon which pthreads is built.</para>
|
||||
<para>
|
||||
A brief exaplanation of the problem is as follows:
|
||||
</para>
|
||||
<para>
|
||||
A call to Cond::wait may return before the Condition Variable recieves a legitimate signal as a result of another context calling Cond::signal or Cond::broadcast.
|
||||
Because of this behaviour, a call to wait for a signal on a Condition Variable must check a predicate ( usually a boolean value ) upon returning from the call to Cond::wait. This eliminates the risk of Spurious Wakeups.
|
||||
</para>
|
||||
</warning>
|
||||
<para>
|
||||
pthreads allows direct access to ( a subset of ) both of these features.
|
||||
The programmer should take care to destroy Mutex and Condition Variable
|
||||
handles that are no longer required for their logic.
|
||||
</para>
|
||||
<para>
|
||||
Mutex and Condition Variables are not destroyed on behalf of the programmer
|
||||
like other resources in PHP, as this would limit their usefulness in the
|
||||
context of multi-threading in SAPI environments.
|
||||
</para>
|
||||
<para>
|
||||
They are easily stored and passed around as they are represented as long numbers.
|
||||
Mutex and Condition Variables persist once allocated until they are explicitly
|
||||
destroyed.
|
||||
</para>
|
||||
<screen>
|
||||
<![CDATA[
|
||||
<?php
|
||||
/* ... */
|
||||
if (Cond::broadcast($finished)) {
|
||||
Cond::destroy($finished);
|
||||
Mutex::destroy($signals);
|
||||
}
|
||||
?>
|
||||
]]>
|
||||
</screen>
|
||||
<para>
|
||||
The snippet above shows a PHP script sending it's final broadcast to the Threads
|
||||
it has created and cleaning up the Condition Variable it created and used for
|
||||
the broadcast. Other Threads that were waiting for a signal on $finished were
|
||||
using $signals - waiting for a signal always requires a Mutex - and as the
|
||||
Condition Variable is no longer valid, the accompanying Mutex is also destroyed.
|
||||
</para>
|
||||
<warning>
|
||||
<para>
|
||||
Before the programmer attempts to use Condition Variables they should have
|
||||
knowledge of "Spurious Wakeups" as allowed for in the Posix Threads
|
||||
specification upon which pthreads is built.
|
||||
</para>
|
||||
<para>
|
||||
A brief explanation of the problem is as follows:
|
||||
</para>
|
||||
<para>
|
||||
A call to Cond::wait may return before the Condition Variable receives a
|
||||
legitimate signal as a result of another context calling Cond::signal
|
||||
or Cond::broadcast. Because of this behavior, a call to wait for a
|
||||
signal on a Condition Variable must check a predicate (usually a boolean
|
||||
value) upon returning from the call to Cond::wait. This eliminates the
|
||||
risk of Spurious Wakeups.
|
||||
</para>
|
||||
</warning>
|
||||
</example>
|
||||
</section>
|
||||
|
||||
<section role="examples">
|
||||
<example>
|
||||
<title>Thread Members</title>
|
||||
<para>The members of a Thread can be of any type that PHP supports the serialization of, including programmer declared classes.</para>
|
||||
<para>In the case where a Thread contains members that are of a programmer declared type ( class ), the programmer must include the declaration using Thread::__prepare magic method.</para>
|
||||
<para>Thread::__prepare method is executed by pthreads in the newly created context, before the newly created context executes Thread::run. This results in correct deserialization of the programmer declared type in the new context.</para>
|
||||
<programlisting role="php"><![CDATA[
|
||||
<?php
|
||||
class ExampleThread extends Thread {
|
||||
public function __prepare(){
|
||||
require_once("/path/to/inc.php");
|
||||
}
|
||||
|
||||
public function __construct($myType){
|
||||
$this->myType = $myType;
|
||||
}
|
||||
|
||||
public function run(){
|
||||
if (method_exists($this->myType, "myMethod")) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
require_once("/path/to/inc.php");
|
||||
/* ... */
|
||||
$my = new Inc();
|
||||
/* ... */
|
||||
$example = new ExampleThread($my);
|
||||
if ($example->start()) {
|
||||
/* ... */
|
||||
}
|
||||
?>
|
||||
]]></programlisting>
|
||||
<para>
|
||||
In the example above, /path/to/inc.php declares a class, as defined by the programmer. The programmer includes the declaration in the global scope before passing an instance of the object to an instance of ExampleThread.
|
||||
The instance of ExampleThread is able to manipulate the object and execute member functions having included the declaration using __prepare magic.
|
||||
The members of a Thread can be of any type that PHP supports the serialization
|
||||
of, including programmer declared classes.
|
||||
</para>
|
||||
<para>
|
||||
In the case where a Thread contains members that are of a programmer declared
|
||||
type (class), the programmer must include the declaration using Thread::__prepare
|
||||
magic method.
|
||||
</para>
|
||||
<para>
|
||||
Thread::__prepare method is executed by pthreads in the newly created context,
|
||||
before the newly created context executes Thread::run. This results in correct
|
||||
deserialization of the programmer declared type in the new context.
|
||||
</para>
|
||||
<screen>
|
||||
<![CDATA[
|
||||
<?php
|
||||
class ExampleThread extends Thread {
|
||||
public function __prepare(){
|
||||
require_once("/path/to/inc.php");
|
||||
}
|
||||
|
||||
public function __construct($myType){
|
||||
$this->myType = $myType;
|
||||
}
|
||||
|
||||
public function run(){
|
||||
if (method_exists($this->myType, "myMethod")) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
require_once("/path/to/inc.php");
|
||||
/* ... */
|
||||
|
||||
$my = new Inc();
|
||||
/* ... */
|
||||
|
||||
$example = new ExampleThread($my);
|
||||
if ($example->start()) {
|
||||
/* ... */
|
||||
}
|
||||
?>
|
||||
]]>
|
||||
</screen>
|
||||
<para>
|
||||
In the example above, /path/to/inc.php declares a class, as defined by the
|
||||
programmer. The programmer includes the declaration in the global scope
|
||||
before passing an instance of the object to an instance of ExampleThread.
|
||||
The instance of ExampleThread is able to manipulate the object and execute
|
||||
member functions having included the declaration using __prepare magic.
|
||||
</para>
|
||||
</example>
|
||||
</section>
|
||||
</chapter>
|
||||
|
|
Loading…
Reference in a new issue