2013-07-21 12 views
5

Attualmente sto usando il seguente metodo di hashing resource s per le ricerche:Utilizzando risorse come indici di array in PHP

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

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

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

è integer lanciare l'opzione migliore per questo? In caso contrario, quale altro metodo di hashing sarebbe migliore o più efficiente? Queste ricerche verranno eseguite in una raccolta in centinaia, molte volte al secondo in un ciclo stretto (polling socket), quindi ho già escluso soluzioni basate sull'iterazione.

Edit:

Per spiegare la mia situazione un po 'meglio, la funzione socket_select() prende array di risorse presa come riferimento e modifica di loro in modo tale che, dopo la chiamata di funzione, conterranno solo le risorse che hanno cambiato (ad esempio, pronto per essere letto da). Io uso una classe Socket come wrapper per le risorse di socket, per rendere il mio codice più astratto e verificabili:

$socketObject = new Socket($socketResource); 

Un'altra delle mie classi mantiene un elenco di tutte le risorse di socket che necessitano di essere interrogato ogni volta che chiamiamo socket_select():

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

Dopo la chiamata al socket_select(), so quale presa risorse sono cambiati, ma per fare qualcosa di significativo nel mio codice, ho bisogno di sapere quale presa oggetti quelle risorse corrispondono a . Così, ho bisogno di qualche modo per mappare le risorse di socket ai loro oggetti:

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

risposta

6

Il comportamento osservato quando casting resources to integer non è definito (consultare la nota di avvertenza nella parte inferiore della pagina). Quindi, anche se questo works now and reliably did for a long time, devi essere consapevole che non è nulla su cui puoi fare affidamento per non cambiare senza preavviso.

Edit dopo chiarimenti:

Invece di mettere la risorsa come chiave, utilizzare due array. Una mappatura degli hash degli oggetti Socket agli oggetti reali. E un'altra mappatura gli stessi hash alla risorsa. Quindi passare il secondo array a socket_select. Sotto la premessa che la funzione non cambierà le chiavi dell'array, è possibile scorrere l'array e utilizzare il tasto per cercare la presa 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]; 
} 
+0

In realtà non ho mai pensato di passare un array associativo a 'socket_select()'; potrebbe funzionare. Dovrò verificarlo più tardi. Seguirò e ti farò sapere. Grazie! – FtDRbwLXw6

+2

Ho appena provato questo, e le chiavi sono mantenute attraverso la chiamata 'socket_select()', e tutto funziona alla grande. Ho accettato la tua risposta e ho iniziato una taglia (24 ore prima che io possa premiarla) perché apprezzo molto il tuo impegno e il tuo aiuto. Grazie! – FtDRbwLXw6

+0

@drrcknlsn yay! Felice funziona. E apprezza la generosità! – Gordon

1

Io uso questa funzione con multi_curl, molto efficace per l'ordinamento per rendere il testo sicuro non è allineata in modo casuale:

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

    return array_pop(explode('#', (string)$resource)); 
} 
0

vi propongo si fa un oggetto di raccolta, invece di $map variabile, ad es.

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 
} 

Anche se io non l'ho provato, questo dovrebbe consentire di accedere l'oggetto come se fosse un array e spero che in questo modo (non v'è alcuna documentazione per questo) le risorse potrebbero essere usati come indici di array .

+0

Grazie per la risposta, ma 'array_search()' usa l'iterazione, quindi questa è una soluzione O (n), dove invece cercavo una soluzione O (1). – FtDRbwLXw6

+0

Puoi combinare entrambe le soluzioni in modo da non dover pensare a due variabili :-) – Voitcus

Problemi correlati