Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using resources as array indexes in PHP

Tags:

arrays

php

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...
}
like image 869
FtDRbwLXw6 Avatar asked Jul 21 '13 19:07

FtDRbwLXw6


People also ask

What are the 3 types of PHP arrays?

In PHP, there are three types of arrays: Indexed arrays - Arrays with a numeric index. Associative arrays - Arrays with named keys. Multidimensional arrays - Arrays containing one or more arrays.

What is PHP array index?

PHP indexed array is an array which is represented by an index number by default. All elements of array are represented by an index number which starts from 0. PHP indexed array can store numbers, strings or any object. PHP indexed array is also known as numeric array.

How do you get the index of an element in an array in PHP?

We can get the array index by using the array_search() function. This function is used to search for the given element.

Which is the right way to create index array in PHP?

It's easy to create an array within a PHP script. To create an array, you use the array() construct: $myArray = array( values ); To create an indexed array, just list the array values inside the parentheses, separated by commas.


2 Answers

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];
}

Update: Casting resource to integer is no longer undefined, as seen in the linked manual page. If a resource is converted to an integer, then the result will be the unique resource number assigned to the resource by PHP at runtime.

like image 158
Gordon Avatar answered Sep 18 '22 20:09

Gordon


I use this function with multi_curl, very effective for sorting to make sure text doesn't line up randomly:

function get_resource_id($resource) {
    if (!is_resource($resource))
        return false;

    return array_pop(explode('#', (string)$resource));
}
like image 34
silkfire Avatar answered Sep 19 '22 20:09

silkfire