2012-04-13 86 views
11

ほとんどの私たちのオブジェクトがネットワーク通信に基づいているため、boost::asioを入力データのソースとして使用するように書かれたアプリケーションがあります。いくつかの特定の要件のために、入力メソッドとして共有メモリを使用できるようにする必要があります。私は既に共有メモリコンポーネントを作成しており、比較的うまく動作しています。Boost :: asio、共有メモリとプロセス間通信

問題は、共有メモリプロセスから消費するアプリケーションへの通知を処理する方法です。既存の入力スレッド(boost::asioを使用)のデータを処理する必要があります。その入力スレッドがデータを待っているのをブロックしないでください。

これは、共有メモリプロバイダプロセスから通知されるイベントを待つ中間スレッドを導入し、完了スレッドを入力スレッドにポストしてデータの読み込みを処理することで実装しました。

これは現在も動作していますが、中間スレッドを導入すると、遅延にマイナスの影響を与えるデータを読み取る前に、大量のケースで余分なコンテキスト切り替えが発生し、追加の糸もまた比較的高価である。ここで

は、アプリケーションが何をしているかの単純な例です:?( interrupt_thread経由 postにそれをせずに
#include <iostream> 
using namespace std; 

#include <boost/asio.hpp> 
#include <boost/thread.hpp> 
#include <boost/scoped_ptr.hpp> 
#include <boost/bind.hpp> 

class simple_thread 
{ 
public: 
    simple_thread(const std::string& name) 
     : name_(name) 
    {} 

    void start() 
    { 
     thread_.reset(new boost::thread(
     boost::bind(&simple_thread::run, this))); 
    } 

private: 
    virtual void do_run() = 0; 

    void run() 
    { 
     cout << "Started " << name_ << " thread as: " << thread_->get_id() << "\n"; 
     do_run(); 
    } 


protected: 
    boost::scoped_ptr<boost::thread> thread_; 
    std::string name_; 
}; 

class input_thread 
    : public simple_thread 
{ 
public: 
    input_thread() : simple_thread("Input") 
    {} 

    boost::asio::io_service& svc() 
    { 
     return svc_; 
    } 

    void do_run() 
    { 
     boost::system::error_code e; 
     boost::asio::io_service::work w(svc_); 
     svc_.run(e); 
    } 

private: 
    boost::asio::io_service svc_; 
}; 

struct dot 
{ 
    void operator()() 
    { 
     cout << '.'; 
    } 
}; 

class interrupt_thread 
    : public simple_thread 
{ 
public: 
    interrupt_thread(input_thread& input) 
     : simple_thread("Interrupt") 
     , input_(input) 
    {} 

    void do_run() 
    { 
     do 
     { 
     boost::this_thread::sleep(boost::posix_time::milliseconds(500)); 
     input_.svc().post(dot()); 
     } 
     while(true); 
    } 

private: 
    input_thread& input_; 
}; 

int main() 
{ 
    input_thread inp; 
    interrupt_thread intr(inp); 

    inp.start(); 
    intr.start(); 

    while(true) 
    { 
     Sleep(1000); 
    } 
} 

が直接 input_threadで扱うデータを取得する方法はあるの仮定があることです割り込みスレッドは、外部アプリケーションからのタイミング(セマフォを介してデータが利用可能であるという通知)によって完全に駆動されます。また、消費アプリケーションと提供アプリケーションの両方を完全に制御し、 input_threadオブジェクト(セマフォオブジェクトをブロックしてそこで待つことはできません)。共有メモリを提供するアプリケーションを経由して来るデータのオーバーヘッド、CPU使用率、およびレイテンシを削減することです。私はこの質問を投稿するので、あなたの答えを見つけたと思い

+2

* NIXの場合は、UNIXパイプを使用して通知するのが最も簡単な方法です。パイプの一端は通常のソケットとして 'input_thread'に追加されます。それでも、同期などのオーバーヘッドが発生しますが、(ソケットバッファからの/への)冗長コピーを保存します。ソケット上でオフセットと長さを送信し、shmemに直接インデックスを付けることができます。 – Useless

+0

Windowsでは、ウィンドウ:: object_handleを使用して、同期オブジェクトで直接非同期待機することができます。 –

答えて

1

が、これは他の人が利益のためである...

試してみるとブーストstrandsをチェックしてください。

これは、作業を行うスレッドを選択する機能を提供します。

これは自動的に特定のストランドにキューイングされます。これはあなたが考える必要のないものです。

作業が完了したことを知る必要がある場合は、完了ハンドラも提供します。

関連する問題