在PHP中使用资源作为数组索引 [英] Using resources as array indexes in PHP

查看:168
本文介绍了在PHP中使用资源作为数组索引的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前使用以下方法散列 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){
// $ socketResource对应哪个套接字对象?
//目前,我使用这样的解决方案:
$ socketObject = $ this-> map [(int)$ socketResource];
//不幸的是,这种行为不能保证,所以它不可靠......
}


解决方案

将资源转换为整数未定义(请参阅页面底部的注意事项)。因此,即使这个现在可以长时间工作并且可靠地工作,您也必须意识到这是您无法倚重的东西如有更改,恕不另行通知。



澄清后编辑: 把资源作为关键字,使用两个数组。一个将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];
}


I am currently using the following method of hashing resources for lookups:

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

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

echo $map[(int)$foo]; // "foo"

Is integer casting the best option for this? If not, what other hashing method would be better or more efficient? These lookups will be performed in a collection into the hundreds, many times per second in a tight loop (socket polling), so I've already ruled out iteration-based solutions.

Edit:

To explain my situation a little better, the socket_select() function takes arrays of socket resources by reference and modifies them such that after the function call, they will contain only the resources which have changed (e.g. ready to be read from). I use a Socket class as a wrapper for socket resources, to make my code more abstract and testable:

$socketObject = new Socket($socketResource);

Another of my classes keeps a list of all socket resources that need to be polled every time we call socket_select():

$reads = [$socketResource1, $socketResource2, ...];
socket_select($reads, null, null, 0);

After the call to socket_select(), I know which socket resources have changed, but to do anything meaningful in my code, I need to know which socket objects those resources correspond to. Thus, I need some way to map socket resources to their objects:

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...
}

解决方案

The observed behavior when casting resources to integer is undefined (see Caution note on the bottom of the page). So even if this works now and reliably did for a long time, you have to be aware that it's nothing you can rely on not to change without notice.

Edit after clarifications:

Instead of putting the resource as key, use two arrays. One mapping the hashes of your Socket objects to the actual objects. And another mapping the same hashes to the resource. Then pass the latter array to socket_select. Under the premise that the function will not change the array keys, you can then iterate the array and use the key to look up the Socket in 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];
}

这篇关于在PHP中使用资源作为数组索引的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆