2

私はmbedプラットフォームにrtosライブラリを使用しています。スレッドにジャンプして、一定の速度で特定の値をインクリメントし、終了したらスレッドを閉じることができるようにしたいと思います。問題は、mbedRTOSライブラリからスレッドを実装するメソッドがconst void *引数を取ることしかできないことです。これは、float値の配列を送信する必要があることを除いて、大したことではありません。これらの値の1つは、インクリメントする必要のある値へのポインター(*joint)であり、他の値は、単純にconst範囲と速度を制御するものです。インクリメント。私はそれを制御していると思い、適切にキャストするためのコードをここに見つけましたが、それでも0の値を考え続けています://float (*vals)[4] = (float (*)[4])args;

これがコードで、スレッド作業に関与する2つの関数だけに切り詰められています。

void increment( void const *args ) { //float *joint, float inc, float target, int speed ) 
    //float (*vals)[4] = (float (*)[4])args;
    float *vals = (float* )args;

    // joint is the outside value I want to increment
    float *joint  = &vals[0];
    float inc    = vals[1];
    float target = vals[2];
    int   speed  = (int)vals[3];
    float start = 0.5;


    if( inc < 0 ) 
        for( *joint = start; *joint > target; *joint+=inc ) {
             wait( 0.1 / speed );
        }
    }


void thread_inc( float *joint, float inc, float target, int speed ){
    float args[4] = { *joint, inc, target, (float)speed };
    //Thread move( increment, args );
    Thread move( increment, &args );
    return;
}

私を正しい方向に向ける何かを前もってありがとう!

4

5 に答える 5

2

私はこれをjlunavtgrad、Pat、BurtonSamogradから絶対に盗んでいます。私は彼らの3つの答えすべてが本当にOPに答えているように感じます。

  1. これは、新しいスレッドコンテキストに渡される引数を表す構造体を使用すると、はるかに適切に管理されます。

  2. args配列はスタック上にあり、スコープによって制限されますthread_inc。構造体に置き換えることで、ここに含まれるスコープの問題を回避することはできません。したがって、引数(任意の形式)は、別のスレッドコンテキストがそれらを適切に使用できるように割り当てる必要があります。これは、グローバルまたはヒープで実行できます。

  3. float *joint引数thread_incは逆参照され、値は引数を設定するために使用されます。引数配列にコピーされた値のみが変更されるため、これは望ましい動作ではないようです。

コードで提案された変更:

struct thread_args {
  float * joint;
  float inc;
  float target;
  int speed;
};


void increment( void const *args ) {
  thread_args* threadArgs = static_cast<thread_args*>( args );

  float *joint  = threadArgs->joint;
  float inc    = threadArgs->inc;
  float target = threadArgs->target;
  int   speed  = threadArgs->speed;
  float start = 0.5;

  if( inc < 0 ){ 
    for( *joint = start; *joint > target; *joint+=inc ) {
       wait( 0.1 / speed );
    }
  }

  delete threadArgs;
}

void thread_inc( float *joint, float inc, float target, int speed ){
  thread_args* threadArgs = new thread_args;
  threadArgs->joint = joint;
  threadArgs->inc = inc;
  threadArgs->target = target;
  threadArgs->speed = speed;

  //Thread move( increment, args );
  Thread move( increment, threadArgs );
  return;
}

このソリューションに関連する最後の提案は、生の形式で使用するのではなくnewdeleteのような種類のスマートポインターを使用することshared_ptrです。

于 2012-04-30T18:23:05.633 に答える
2

引数のリストをvoid*に渡そうとする代わりに、各引数のフィールドを持つスレッド引数の構造体を定義することをお勧めします。記入してから、構造体のアドレスをvoid*として渡します。

于 2012-04-30T17:05:50.740 に答える
2

様式的には、構造体を使用してこの情報をスレッドに渡すことをお勧めします。これにより、コードが読みやすくなり、構文がいくらかクリーンアップされます。

struct thread_args {
   float * joint;
   float inc;
   float target;
   int speed;
};
于 2012-04-30T17:06:44.110 に答える
1

You are creating the args array on the stack, so when you create the thread it is out of scope when the function returns. You should allocate the args array using new/malloc, initialize it and then pass it into the move thread. When the move thread is done you can free the array. Another option is to create the array that is passed to thread_inc in a calling function.

于 2012-04-30T17:03:56.137 に答える
1

*ジョイントをincrement関数に渡すときに逆参照しているため、関数はその値を更新できません。

これを試して:

void increment( void const *args ) { //float *joint, float inc, float target, int speed ) 
    //float (*vals)[4] = (float (*)[4])args;
    float *vals = (float* )args;

    // joint is the outside value I want to increment
    float *joint  = (float *)vals[0];
    float inc    = vals[1];
    float target = vals[2];
    int   speed  = (int)vals[3];
    float start = 0.5;


    if( inc < 0 ) 
        for( *joint = start; *joint > target; *joint+=inc ) {
             wait( 0.1 / speed );
        }
    }


void thread_inc( float *joint, float inc, float target, int speed ){
    float args[4] = { (float)joint, inc, target, (float)speed };
    //Thread move( increment, args );
    Thread move( increment, &args );
    return;
}
于 2012-04-30T17:06:33.940 に答える