在PHP中使用资源作为数组索引

FtD*_*Xw6 5 php arrays hash

我目前正在使用以下散列方法resource进行查找:

$foo = socket_create(...);
$bar = socket_create(...);

$map[(int)$foo] = 'foo';
$map[(int)$bar] = 'bar';

echo $map[(int)$foo]; // "foo"
Run Code Online (Sandbox Code Playgroud)

integer铸造我们的最佳选择吗?如果没有,那么其他什么样的散列方法会更好或更有效?这些查找将在紧密循环(套接字轮询)中以每秒数百次的速度执行,因此我已经排除了基于迭代的解决方案.

编辑:

为了更好地解释我的情况,该socket_select()函数通过引用获取套接字资源数组并修改它们,以便在函数调用之后,它们将仅包含已更改的资源(例如,准备从中读取).我使用一个Socket类作为套接字资源的包装器,使我的代码更抽象和可测试:

$socketObject = new Socket($socketResource);
Run Code Online (Sandbox Code Playgroud)

我的另一个类保留了每次调用时需要轮询的所有套接字资源的列表socket_select():

$reads = [$socketResource1, $socketResource2, ...];
socket_select($reads, null, null, 0);
Run Code Online (Sandbox Code Playgroud)

在调用之后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...
}
Run Code Online (Sandbox Code Playgroud)

Gor*_*don 6

资源转换为整数时观察到的行为未定义(请参阅页面底部的警告说明).因此,即使现在可靠地工作并且可靠地做了很长时间,您也必须意识到,如果没有通知,您无需依赖它.

澄清后编辑:

不要将资源作为密钥,而是使用两个数组.将Socket对象的哈希映射到实际对象.另一个将相同的哈希映射到资源.然后将后一个数组传递给socket_select.在函数不会更改数组键的前提下,您可以迭代数组并使用键在O(1)中查找Socket:

$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];
}
Run Code Online (Sandbox Code Playgroud)

  • 我刚测试了这个,并且通过`socket_select()`调用保存了键,一切都很好.我已经接受了你的答案并开始获得奖金(我可以奖励之前24小时),因为我非常感谢你的努力和帮助.谢谢! (2认同)