2

次のようなメソッドへのコールバックを取得する 2 つの異なるソース (ネットワーク リッスン) から更新を受信して​​います。

void onUpdate(Update* update)
{
    static MutexT lock;
    static hash_set<UpdateID> set;

    ScopedGuard _(lock); //lock here
    hash_set<UpdateID>::iterator it = set.find(update->id);
    if (it == set.end())
        set.insert(update->id);
    else
        return;

    listener->onUpdate(/*some stuff*/);
}

両方のソースが同じ更新を提供しているため、重複の通知を避けたい場合は、両方のソース間で調停して、最初に提供した人からの最新情報を入手し、一方のソースが更新されていない可能性がある場合は見逃した更新についても確認する必要があります。信頼できない。onUpdate問題は、すべての更新をロックするのは費用がかかるということです。重複した呼び出しが絶対に望ましくない場合、このロックを回避する方法はありますか?

(または、少なくともコストを削減する方法ですか?)

4

3 に答える 3

2

まず第一に、ロックは静的であってはならず、メンバー変数であるべきです。

リーダー/ライターミューテックスを使用することで、より効率的にすることができます。

boost::shared_mutex          mutex_;
std::unordered_set<UpdateID> set_;

void onUpdate(const Update& update)
{
    boost::upgrade_lock<boost::shared_mutex> lock(mutex_);

    auto it = set_.find(update.id);
    if(it == set_.end())
    {
        boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(mutex_);
        set.insert(update.id);
    }

    listener->onUpdate(/*some stuff*/);
}
于 2012-09-11T19:15:57.220 に答える
0

では、ハッシュ テーブルにエントリを継続的に追加するだけですか? それらを削除したことはありませんか?ハッシュ テーブルの読み込みはどのようになりますか? 十分な衝突があると、挿入/ルックアップのパフォーマンスが低下します。

ストリームにシーケンス番号がある場合は、実際に見たメッセージではなく、ギャップ (シーケンス番号の欠落) を追跡したほうがよいと思います。高速 UDP 側では、シーケンス番号にギャップがある場合、不足しているメッセージをハッシュ テーブルに記録し、受信するすべてのメッセージで onUpdate() を呼び出します。低速 TCP 側では、ハッシュ テーブルを調べて、メッセージがギャップを埋めるかどうかを確認します。もしそうなら、onUpdate() を呼び出してそのメッセージをハッシュ テーブルから削除します。それ以外の場合は何もしません。

そうは言っても、ロックフリーのハッシュテーブルは可能です。それらがロックフリーであるかどうかはわかりませんが、Microsoft にはconcurrent_unordered_map (およびconcurrent_unordered_set ) があり、TBB にはconcurrent_hash_mapがあります。

于 2012-09-11T21:21:55.843 に答える
-1

挿入状態を 2 回チェックすることで、コストのかかるロックを回避するダブルチェック ロック設計パターンがあります。しかし、より高価なのは、ロックまたは検索です。

于 2012-09-11T19:16:26.200 に答える