В настоящее время я использую следующий метод хэширования resource
s для поиска:
$foo = socket_create(...); $bar = socket_create(...); $map[(int)$foo] = 'foo'; $map[(int)$bar] = 'bar'; echo $map[(int)$foo]; // "foo"
Самый лучший вариант для этого? Если нет, то какой другой метод хеширования будет лучше или эффективнее? Эти поисковые запросы будут выполняться в коллекции в сотни, много раз в секунду в плотном цикле (сокет-опрос), поэтому я уже исключил итерационные решения.
Редактировать:
Чтобы объяснить мою ситуацию немного лучше, функция socket_select()
принимает массивы ресурсов сокетов по ссылке и изменяет их так, что после вызова функции они будут содержать только те ресурсы, которые были изменены (например, готовы к чтению). Я использую класс Socket
в качестве оболочки для ресурсов сокетов, чтобы сделать мой код более абстрактным и проверяемым:
$socketObject = new Socket($socketResource);
Еще один из моих классов хранит список всех ресурсов сокетов, которые нужно опросить каждый раз, когда мы вызываем socket_select()
:
$reads = [$socketResource1, $socketResource2, ...]; socket_select($reads, null, null, 0);
После вызова socket_select()
я знаю, какие ресурсы сокетов изменились, но чтобы сделать что-то значимое в моем коде, мне нужно знать, какие объекты сокетов соответствуют этим ресурсам. Таким образом, мне нужно каким-то образом сопоставить ресурсы сокетов с их объектами:
foreach ($reads as $socketResource) { // Which socket object does $socketResource correspond to here? // Currently, I use a solution like this: $socketObject = $this->map[(int)$socketResource]; // Unfortunately, this behavior isn't guaranteed, so it isn't reliable... }
Наблюдаемое поведение при отливке ресурсов до целого числа не определено (см. Примечание в нижней части страницы). Поэтому, даже если это работает и надежно работает в течение длительного времени , вы должны знать, что ничто из того, что вы можете полагаться на то, чтобы не меняться без предупреждения.
Изменить после разъяснений:
Вместо того, чтобы использовать ресурс как ключ, используйте два массива. Одно отображение хэшей ваших объектов Socket на реальные объекты. И еще одно отображение того же хэша на ресурс. Затем передайте последний массив в socket_select
. В предположении, что функция не изменит ключи массива, вы можете затем перебрать массив и использовать ключ для поиска Socket в O (1):
$r1 = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $r2 = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $s1 = new Socket($foo); $s2 = new Socket($bar); $socketMap = array( spl_object_hash($s1) => $s1, spl_object_hash($s2) => $s2 ); $reads = array( spl_object_hash($s1) => $r1, spl_object_hash($s2) => $r2 ); socket_select($reads, null, null, 0); foreach (array_keys($reads) as $hash) { $socketObject = $socketMap[$hash]; }
Я использую эту функцию с multi_curl, очень эффективную для сортировки, чтобы текст не выстраивался случайным образом:
function get_resource_id($resource) { if (!is_resource($resource)) return false; return array_pop(explode('#', (string)$resource)); }
Я предлагаю вам создать объект коллекции вместо переменной $map
, например.
class ResourceCollection implements ArrayAccess { private $map = array(); /** * returns index of element or FALSE if not existent */ protected function getIndex($offset){ if(is_resource($offset)){ $index = array_search($offset, $this->map); } else // you can add more tests if you need if(isset($this->map[$offset])) $index = $offset; else $index = false; return $index; } /** * required by ArrayAccess interface */ public function offsetExists($offset){ return ($this->getIndex($offset) === false)? false : true; } /** * required by ArrayAccess interface */ public function offsetGet($offset){ $index = $this->getIndex($offset); if($index === false) throw new ... // or handle error of non-existent element return $this->map[$index]; } // etc., implement ArrayAccess interface, Iterator and anything you want }
Хотя я не тестировал его, это должно позволить вам получить доступ к объекту, как если бы это был массив, и я надеюсь, что таким образом (для этого нет документации) ресурсы могут использоваться как индексы массива.