はPHP

2013-07-21 2 views
5

に私は現在、検索にresource Sをハッシュの次のメソッドを使用しています:はPHP

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

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

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

は、このための最良の選択肢をキャストintegerですか?そうでない場合は、他のどのようなハッシング方法がより効率的か、より効率的になるでしょうか?これらのルックアップは、タイトなループ(ソケットポーリング)で数百回、毎秒何回も実行されるコレクションなので、すでに反復ベースのソリューションを排除しています。

編集:

少し良く私の状況を説明するために、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... 
} 

答えて

6

casting resources to integerが定義されていないときに観察された動作(ページの下部にある注意の注意を参照)。したがって、たとえこのworks now and reliably did for a long timeであっても、予告なしに変更しないことに頼ることはできないことに気づく必要があります。明確化した後

編集:代わりにキーなどのリソースを置くの

、二つの配列を使用しています。 1つはあなたのSocketオブジェクトのハッシュを実際のオブジェクトにマッピングします。もう1つは同じハッシュをリソースにマッピングします。その後、後者の配列をsocket_selectに渡します。関数は配列のキーを変更しないという前提の下で、あなたはその配列を反復処理し、(1)Oでソケットをルックアップするためにキーを使用することができます。

$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

実際には、連想配列を 'socket_select()'に渡すことは考えていませんでした。それはうまくいくかもしれません。私は後でこれをテストしなければならないでしょう。フォローアップしてお知らせします。ありがとう! – FtDRbwLXw6

+2

私はちょうどこれをテストし、キーは 'socket_select()'コールによって保持され、すべてがうまくいきます。あなたの努力と助けに本当に感謝しているので、私はあなたの答えを受け入れて、賞金を授与しました(私がそれを授与する前に24時間)。ありがとうございました! – FtDRbwLXw6

+0

@drrcknlsn yay!それはうまくいきます。そして賞金を感謝します! – Gordon

1

私はテキストがランダムに並んでいないことを確認するためにソートするために非常に効果的な、multi_curlでこの機能を使用します。

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

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

私はあなたのコレクションオブジェクトを作る代わりに提案します例えば、変数$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 
} 

私はそれをテストしていませんでしたが、それが配列だったと私はこの方法(これにはドキュメントが存在しない)リソースが配列のインデックスとして使用することができることを願っているかのように、これはあなたがオブジェクトにアクセスできるようにする必要があります。

+0

答えてくれてありがとうございますが、 'array_search()'は反復を使用していますので、代わりにO(1)解を探していたO(n)解です。 – FtDRbwLXw6

+0

両方のソリューションを組み合わせることができるので、2つの変数について考える必要はありません:-) – Voitcus