/** * Constructs a new socket. * * @param string $address Address to make the connection on. * @param string $options Connection options * * @return void */ public function __construct($address, $options = []) { parent::__construct(); $defaults = ['port' => null, 'domain' => AF_INET, 'type' => SOCK_STREAM, 'protocol' => SOL_TCP]; $options += $defaults; $this->_address = $address; $this->_options = $options; /** * TODO * * Shorten this entire loop. */ $this->_idle = new Process(function ($processor) { if (XPSPL_DEBUG) { logger(XPSPL_LOG)->debug('Entering socket wait loop'); } $idle = $processor->get_routine()->get_idles_available(); // 30 second default wait $time = 30; $utime = 0; // Determine if another function has requested to execute in x // amount of time if (count($processor->get_routine()->get_signals()) !== 0) { // If we have signals to process only poll and continue $time = 0; } elseif (count($idle) >= 2) { $default_wait_time = time() + $this->default_wait_time; foreach ($idle as $_idle) { // if ($_idle->get_idle() instanceof Time) { // // echo $default_wait_time.PHP_EOL; // // echo $_idle->get_idle()->get_time_until().PHP_EOL; // // echo $_idle->get_idle()->get_time_until() < $default_wait_time.PHP_EOL; // // echo $_idle->get_idle()->get_time_until() > $default_wait_time.PHP_EOL; // // echo $_idle.PHP_EOL; // } // if ($_idle->get_idle() instanceof Time && ( // // $default_wait_time > $_idle->get_idle()->get_time_until())) { // // $time = round($_idle->get_idle()->convert_length( // // $_idle->get_idle()->get_time_left(), // // TIME_SECONDS // // ), 3); // // if ($time > 0 && $time < 1) { // // $utime = $time * 1000; // // $time = 0; // // } // // echo $time.PHP_EOL; // // break; // } } } // establish sockets $re = [$this->_connection->get_resource()]; $wr = $ex = []; foreach ($this->_clients as $_k => $_c) { $_resource = $_c->get_resource(); // test if socket is still connected // send disconnect if disconnect detected if ($_c->is_connected() === false) { xp_emit(new SIG_Disconnect($_c)); unset($this->_clients[$_k]); continue; } else { $re[] = $_resource; $ex[] = $_resource; } } $count = socket_select($re, $wr, $ex, $time, $utime); if ($count === false) { logger(XPSPL_LOG)->debug('Socket wait loop ended PROBLEM'); return false; } elseif ($count == 0) { if (XPSPL_DEBUG) { logger(XPSPL_LOG)->debug('Socket wait loop ended no connection changes'); } return true; } if (XPSPL_DEBUG) { logger(XPSPL_LOG)->debug('Socket wait loop ended connection changes detected'); } // Check Read if (count($re) !== 0) { foreach ($re as $_r) { if (XPSPL_DEBUG) { logger(XPSPL_LOG)->debug(sprintf('Connection Read %s', strval(intval($_r)))); } $id = intval($_r); if (!isset($this->_clients[$id])) { $client = new Client($_r); $id = intval($client->get_resource()); xp_emit(new SIG_Connect($this, $client)); $this->_clients[$id] = $client; if (XPSPL_DEBUG) { logger(XPSPL_LOG)->debug(sprintf('Added Connection %s', strval(intval($id)))); } } else { $this->_clients[$id]->_read_buffer(); xp_emit(new SIG_Read($this, $this->_clients[$id])); } } } // Check Write if (count($wr) !== 0) { foreach ($wr as $_write) { if (XPSPL_DEBUG) { logger(XPSPL_LOG)->debug(sprintf('Connection Write %s', strval($_write))); } $processor->get_routine()->add_signal(new SIG_Write($this, $this->_clients[intval($_write)])); } } // Errors if (count($ex) !== 0) { foreach ($ex as $_excep) { if (XPSPL_DEBUG) { logger(XPSPL_LOG)->debug(sprintf('Connection Exception %s', strval($_excep))); } $this->_clients[intval($_excep)]->error = socket_last_error($_excep); $this->_clients[intval($_excep)]->error_str = socket_strerror($_excep); $processor->get_routine()->add_signal(new SIG_Error($this, $this->_clients[intval($_excep)])); } } }); $this->on_disconnect(xp_priority(PHP_INT_MAX, '\\network\\system_disconnect')); // After processing read clean the buffer xp_after(new SIG_Read($this), xp_low_priority('\\network\\clean_buffer')); // Emit this has started xp_emit($this); }
<?php /** * Copyright 2010-12 Nickolas Whiting. All rights reserved. * Use of this source code is governed by the Apache 2 license * that can be found in the LICENSE file. */ require_once dirname(realpath(__FILE__)) . '/../__init__.php'; xp_import('unittest'); unittest\test(function ($test) { $foo = XP_SIG('foo'); xp_signal($foo, function () { }); xp_before($foo, function ($foo) { $foo->foo = 'foo'; }); xp_emit($foo); $test->equal($foo->foo, 'foo'); }, 'API Before function');
/** * Send the signal to disconnect this socket. * * @param integer $how * * @return event\Disconnect */ public function disconnect() { return xp_emit(new SIG_Disconnect(null, $this)); }
<?php ini_set('memory_limit', '10G'); xp_set_signal_history(true); $sig = XP_SIG('foo'); $time = time(); // Emit a few foo objects for ($i = 0; $i < 10000000; $i++) { xp_emit($sig); } $end = time(); $emitted = 0; foreach (xp_signal_history() as $_node) { if ($_node[0]->compare($sig)) { $emitted++; } } echo 'Emitted ' . $emitted . ' signals in ' . ($end - $time) . ' seconds' . PHP_EOL; echo 'Rate of ' . $emitted / ($end - $time);
<?php /** * This example demonstrates emitting signals based on network input and analysing * the emitted signals from the network to detect a wedding. * * This allows for recieving input from any input source. */ xp_import('network'); $server = network\connect('0.0.0.0', ['port' => 8000]); $server->on_read(function ($signal) { $read = trim($signal->socket->read()); if ($read == null) { return false; } xp_emit(XP_SIG($read)); }); // Once a bride, groom and bell signals are emitted we emit the wedding. $wedding = xp_complex_sig(function ($signal) { if (!isset($this->reset) || $this->reset) { $this->reset = false; $this->bride = false; $this->groom = false; $this->bells = false; } switch (true) { case $signal->compare(XP_SIG('groom')): $this->groom = true; break; case $signal->compare(XP_SIG('bride')): $this->bride = true;
xp_import('network'); $ops = 0; $thread = xp_threaded_process(function () { $start_time = 0; $this->operations = 0; $sig = XP_SIG('a'); do { echo $ops; xp_emit($sig); $this->operations++; $ops = $this->operations / (microtime(true) - $start_time); } while (true); }); $ops_sig = xp_signal(XP_SIG('op'), xp_exhaust(null, $thread)); xp_emit(XP_SIG('op')); // $server = network\connect('0.0.0.0', ['port'=>8000]); // $server->on_connect(xp_null_exhaust(function($server) use ($ops){ // $server->socket->write($ops); // $server->socket->disconnect(); // })); // $server = // $iterations = 1000000; // $start = microtime(true); // for ($i=0;$i<$iterations;$i++) {} // $end = microtime(true); // $loop_time = $end - $start; // $sig = XP_SIG(null); // $start = microtime(true); // for ($i=0;$i<$iterations;$i++) { // xp_emit($sig);
<?php // Handle Foo xp_signal(XP_SIG('foo'), function ($signal) { echo $signal->bar; }); // When foo is emitted insert bar into the event xp_before(XP_SIG('foo'), function ($signal) { echo "I RAN" . PHP_EOL; $signal->bar = 'foo'; }); xp_before(XP_SIG('foo'), xp_high_priority(function ($signal) { echo "I RAN BEFORE" . PHP_EOL; })); // After foo is emitted unset bar in the event xp_after(XP_SIG('foo'), function ($signal) { unset($signal->bar); }); $signal = xp_emit(XP_SIG('foo')); var_dump(isset($signal->bar));
<?php $max_threads = 16 - 1; class My_Thread extends \XPSPL\Process { public function execute($signal, $thread) { while (true) { var_dump($thread); } } } for ($i = 0; $i < $max_threads; $i++) { xp_signal(XP_SIG('test' . $i), xp_threaded_process(new My_Thread())); } for ($i = 0; $i < $max_threads; $i++) { xp_emit(XP_SIG('test' . $i)); }
/** * Processes any files awaiting to upload and attempts to begin the upload * transfer. * * @todo Add an emit for failure to connect, incorrect file. * * @return void */ protected function _init_transfers() { foreach ($this->_files as $_k => $_file) { if (!$_file instanceof File) { continue; } if ($this->_options['secure']) { $connection = ftp_ssl_connect($this->_options['hostname'], $this->_options['port'], $this->_options['timeout']); } else { $connection = ftp_connect($this->_options['hostname'], $this->_options['port'], $this->_options['timeout']); } if (false === $connection) { break; } $login = ftp_login($connection, $this->_options['username'], $this->_options['password']); if ($login === false) { $this->_sig_failure->set_upload($_file); xp_emit($this->_sig_failure, new SIG_Failure($_file)); ftp_close($connection); break; } if (!file_exists($_file->get_full_path())) { xp_emit($this->_sig_failure, new SIG_Failure($_file)); } else { $transfer = ftp_nb_put($connection, $_file->get_name(), $_file->get_full_path(), $_file->get_transfer_mode()); if ($transfer === FTP_MOREDATA) { $this->_uploading[] = [$connection, $_file]; } else { if ($transfer == FTP_FINISHED) { $this->_sig_complete->set_upload($_file); xp_emit($this->_sig_complete); // Close the FTP connection to that file ftp_close($connection); $this->_uploaded[] = $_file; } else { $this->_sig_failure->set_upload($_file); xp_emit($this->_sig_failure); // Close the FTP connection to that file ftp_close($connection); } } } unset($this->_files[$_k]); } }