Jump to content

Learning about Multithreading in PHP (pthreads) ?


nik_jain

Recommended Posts

Have you tried adding PHP to your Google search string? ;)

 

I've searched my history and bookmarks, but apparently it's been too long since I found whatever it was I learned from. And I didn't bookmark it. I do have a project running using pcntl_* functions.

 

Prepare to write more code ;)

 

Here's the heart of a multi-threaded "fetcher" that uses posix_getpid, pcntl_fork and pcntl_waitpid in conjunction with an external function I didn't show (systemFetchSequential(), uses fetch/wget to get urls and write them to $outpath).

 

The function is_pid() simply returns false if the PID isn't set (probably could just use a truth check and is_int(), but I didn't and can't remember why). threaded_fetch() is limited to 10 threads by the huge if/elseif construct there; if you write more code you can have more threads. I can't recall the reason, but a switch wouldn't work according to the guy I was reading.

 

function is_pid($n) { return ($n > 0); } //EOF

function threaded_fetch( $url_array, $outpath ) {

global $threads; //we get this from the calling environment

if ( $threads > 10 ) die("Threaded_fetch() function cannot support more than 10 threads.");

$url_chunks = array_chunk( $url_array, (ceil((count($url_array)) / $threads ))+5, true );

/* PNCTL_FORK() implementation */

$ppid=posix_getpid(); // Keep reference to the PID of the parent process
$pids=array( range( 0,( $threads ) ) ); // An array to hold refrence to PIDs of child processes

for ( $i = 0; $i<=$threads; $i++ ) {

$pid=pcntl_fork(); // Forks a new child process and keeps refrence to its PID;
if ( $pid == -1 ) {
die( 'could not fork' );
}
if ( !$pid ) { /* This only runs in a child process */
$pids[$i] = posix_getpid();// Get the PID of the child process
break;
} else {
$pids[$i] = $pid;
}
} //for $i

$active_pids = count(array_filter($pids,"is_pid"));
print("Started $active_pids children to process ".count($url_chunks)." chunks of data.");

/* By this time all processes, child and parent have their own copy of $pid and $pids[]*/

$current_pid=posix_getpid(); // Get the PID of the curently running process

if ( $current_pid == $pids[0] ) { /* Task for child 1 */
systemFetchSequential( $url_chunks[0],"$outpath" );
exit();
} elseif ( $current_pid == $pids[1] ) { /* Task for child 2 */
systemFetchSequential( $url_chunks[1],"$outpath" );
exit();
} elseif ( $current_pid == $pids[2] ) { /* Task for child 3 */
systemFetchSequential($subpage_chunks[2],"$outpath");
exit();
} elseif ( $current_pid == $pids[3] ) { /* Task for child 4 */
systemFetchSequential( $url_chunks[3],"$outpath" );
exit();
} elseif ( $current_pid == $pids[4] ) { /* Task for child 5 */
systemFetchSequential( $url_chunks[4],"$outpath" );
exit();
} elseif ( $current_pid == $pids[5] ) { /* Task for child 6 */
systemFetchSequential( $url_chunks[5],"$outpath" );
exit();
} elseif ( $current_pid == $pids[6] ) { /* Task for child 7 */
systemFetchSequential( $url_chunks[6],"$outpath" );
exit();
} elseif ( $current_pid == $pids[7] ) { /* Task for child 8 */
systemFetchSequential( $url_chunks[7],"$outpath" );
exit();
} elseif ( $current_pid == $pids[8] ) { /* Task for child 9 */
systemFetchSequential( $url_chunks[8],"$outpath" );
exit();
} elseif ( $current_pid == $pids[9] ) { /* Task for child 10 */
systemFetchSequential( $url_chunks[9],"$outpath" );
exit();
}

foreach ( $pids as $key => $val ) { //wait/exit routine
pcntl_waitpid( $val, $status );
unset( $pids[$key] );
}
} //EOF

 

In this case, running this function with a $url_array will start 10 children on the server, running fetch/wget against a chunk of the $url_array until they're done.

Thanks for attempting to help, but ....

 

let me try and explain my question a bit more clearly.

I am looking to learn pThreads as described here: https://gist.github.com/krakjoe/6437782

The above article talks a lot about synchronization / mutex / waiting / sharing / context and other unknown concepts.. These are the concepts and generally learning pthreads is the help I am looking for.

Taking a real world example:

class WebRequest extends Thread {
    public function run() {
       for_doc() ;
       echo 'Running Thread : ' . $this->getCurrentThreadId() ."\n";
    }
}

Here the for_doc() is a factory function that creates a Object of type A class, but all calls to $this return null ( I know I didn't explain the issue well, ut I am just trying to give an idea about what confuses me about multithreading)

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.