2016-07-05 4 views
0

私は自分自身を少し縛りつけました。私は、メインクラス、シリアルポート処理クラス、およびFFTの実際のパフォーマンスを扱うクラスに分割された、ある種のオシロスコープ型プログラムを作っています。シリアルハンドラクラスでは、boost.Asioの非同期読み取り機能を使用して、シリアルポートからFFT Handlingクラスのメンバ関数に渡したいデータを読み込みます。セットアップは読書のためのかなり標準的です。私は、io_serviceオブジェクトが別のスレッド上で実行されて、読み込むデータがあるときにイベントハンドラを呼び出します。C++イベントハンドラからデータを取り出し、別のクラスのメソッドに渡す?

そこに問題があります。どうやら、私は、async_read_someのイベントハンドラからのデータを別のスレッドの別のクラスのメソッドに渡す方法を見つける必要があります。私はそれが完全に正直である可能性があるかどうかも分かりません。 2つのクラスはメインメソッドに一緒に存在するので、それらの間でデータを渡すことは可能かもしれません。でもそれは不可能でも、望みの効果を達成する方法は何でしょうか?最悪の場合、それらを1つのクラスにマージすることが可能かもしれないと思います。

EDIT:ここでは、すべてのリンクを正確に把握するための簡単な疑似コードを示します。免責事項:私は疑似コードを正しく書く方法を完全にはわかっていないが、私は凶悪化したプログラマーだから分かりにくい場合は教えてください。

//declared globally 
boost::mutex mutex_; 
sem_t qSem; 
queue q; 


class SerialHandler{ 
private: 
    string portName; 
public: 
    void StartConnection(){ 

     //...some initialization things 

     AsyncReadSome(); 

     //thread is initiated here 
     t1 = new boost::thread(boost::bind(&boost::asio::io_service::run, &ioService)); 
    } 

    //the only important thing here is it reads into a buffer and calls the event after the read 
    void AsyncReadSome(){ 
     serialPort->async_read_some(boost::asio::buffer(rawBuffer, SERIAL_PORT_READ_BUFF_SIZE), 
     boost::bind(&SerialHandler::HandlePortOnReceive, 
     this, placeholders::error, 
     placeholders::bytes_transferred, q)); 
    } 

    void HandlePortOnReceive(error_code &ec, size_t bytes_transferred, queue q){ 
     scoped_lock (mutex_); //from boost lib 

     for (int i=0;i<bytes_transferred;i++){ 
      double d = (double) rawBuffer[i]; //pushes data into queue 
      q.push(c); 
      sem_post(&qSem); 
     } 
     AsyncReadSome(); //loops back on itself 
    } 
} 


class FFTHandler{ 
private: 
    double *in; //holds the input array 
    fftw_complex *out;//holds out array 

    int currentIndex; 
public: 
    void AppendIn(queue &q, sem_t &_qSem){ 
     while (1){ 
      sem_wait(&_qSem); 
      double d = q.pop(); 
      in[currentIndex] = d; 
      if (...){}//some logic to not overflow the in[] 
     } 
    } 
} 


int main(){ 
    FFTHandler fftHandler; 
    SerialHandler serialHandler; 

    //...some initialization of global variables goes here 

    serialHandler.StartConnection(); 

    boost::thread *t2=new boost::thread(boost::bind(&FFTHandler.AppendIn, &fftHandler, &q, &qSem); 

    char c = getchar(); 
    if (c){call stop functionality} 

} 
+2

[boost signals](http://www.boost.org/doc/libs/1_61_0/doc/html/signals.html)を見ましたか? – mvidelgauz

+0

@mvidelgauz私はboost :: signals2を一度も使用していないので、私の無知を言い訳しなくてはいけませんが、ドキュメントとチュートリアルの読んで判断すると、どうすればこのイベントハンドラからメインスレッドのクラスにデータを渡します。あなたは精巧にお考えですか? – Scorch

+1

申し訳ありません、現時点では、古いプロジェクトのコードはありません。明日の夜まで誰も答えないなら、私はコードサンプルを見つけようとします。一方、あなたはまたそれのためにGoogleをすることができます(多分 "site:stackoverflow.com"で:-))。私はそれらがたくさんあると確信しています – mvidelgauz

答えて

1

免責事項: 私はboost :: signalsを使用したことがないので、これがより良い解決策である可能性があります。私はmvidelgauzが投稿したリンクを素早く見て回った。

スレッド間でデータを共有する方法は次のとおりです。 スレッド間で共有する必要があるデータが含まれるグローバル変数があります。あなたの状況について私が知ることから、私はある種のFIFOを使用します。シリアルハンドラクラスのイベントハンドラがシリアルポートからデータを読み込んで共有FIFOに格納するとき(共有変数にアクセスするときは必ずミューテックスを使用してください)、セマフォに投稿してください。別のスレッドの別のクラスのメソッドは、そのセマフォを待つ必要があります。シリアルハンドラスレッドがセマフォにポストすると、別のスレッドが起動し、FIFOからデータを読み取ることができます。繰り返しますが、FIFOから読み込む前にmutexを使用するようにしてください。個人的には、私はpthreadsに精通しているので、それは私が使用するものです。

私はあなたのコードがどのように動作するかを知らずにできる限り最善を尽くします。ここにいくつかの擬似コードがあります:

#include <pthread.h> 
#include <semaphore.h> 

// Global variable 
Queue q; 
pthread_mutex_t q_mutex; 
sem_t q_sem; 
// Make sure to initialize these variables somewhere 

// Serial thread event handler: 
char c = serial_port_read(); // I don't know how this works for you 
pthread_mutex_lock(&q_mutex); 
q.push(c); 
pthread_mutex_unlock(&q_mutex); 
sem_post(&q_sem); 
return; 

// Separate thread that waits for this data 
sem_wait(&q_sem); 
pthread_mutex_lock(&q_mutex); 
char c = q.pop(); 
pthread_mutex_unlock(&q_mutex); 

質問がありましたら教えてください。

+0

私は先に進んであなたの方法を試しました(私はそれを上に含めました)。セマフォは他のスレッドにポップするデータがあることを通知してからポップすることができますか? AppendIn()を呼び出すタイミングをプログラムに教えていないような気がします。私はそれをメイン()に含めるだろうか? – Scorch

+1

はい、セマフォーは本当に単なるシグナルです。セマフォの値が0の場合、セマフォを待ってスレッドをブロックします。セマフォにポストすると、セマフォが増えます。それが起こると、もう一方のスレッドは起き上がり、セマフォをデクリメントして移動します。 AppendIn()の呼び出しは、常に呼び出されるようにwhile(1)ループ内にある必要があります。これはメインにあるかもしれませんが、メインのように見えるので、他のことをする必要があります。それはおそらく独自のスレッドでなければなりません。また、あなたはミューテックスを一度ロックしていますが、決してロックを解除することはありません。 scoped_lock(mutex_)で何をしているのか説明できますか? – mgarey

+0

私はscoped_lockを主に利便性のために使用しています。なぜなら、スコープがスコープから外れてから自動的にロックが解除されるまで、ロックとして機能するからです。ちょっとした予期せぬエラーが発生し、mutexのロックを解除せずに関数が戻ることがあります。私が行った変更で質問を更新し、それが動作するかどうかを確認します – Scorch

関連する問題