1

私は、多くのグローバル変数が散らばっている古いレガシー ANSI C システムに取り組んでいます。私は、コードを再入可能かつスレッドセーフにするために、既存のコードベースをリファクタリングするチームの一員です。スレッド セーフでリエントラントな ANSI C コードの記述に関する有用な資料を見つけまし

私の(確かに不完全な)理解に基づいて、どのように進めるかについての提案を思いつきました - しかし、対処が必要ないくつかの問題をすでに思いつきました。実際にコードを書き始める前に物事を設計する。

/******************************************************************/
/*                                                                */
/* CURRENT situaton:                                              */
/* Global variables scattered accross a multitude of source files */
/*                                                                */
/******************************************************************/
static struct myStruct some_struct;
static long instance_counter;
static char[MAX_STR_LEN] instance_name;
static dbConnection * db_conn;
static SharedMemoryPtr * shrmem_ptr;




/*******************************************************************/
/*                                                                 */
/* PROPOSED solution:                                              */
/* Wrap all global variables into one thread local struct and      */
/* provide getter/setter* funcs for the variables (of course, this */
/* means that I will have to modify existing code to use the       */
/* context variable and the getter/setter methods instead of       */
/* directly accessing the global variables)                        */
/*                                                                 */ 
/*******************************************************************/

/* Thread local variables stored in ONE source file */

struct myStruct some_struct;
long instance_counter;
char[MAX_STR_LEN] instance_name;
dbConnection * db_conn;
SharedMemoryPtr * shrmem_ptr;


/* Thread local variable that provides getter/setter funcs to 'globals' */

typedef struct _ctx
{
    /* Getter functions */
    variable1_type (getter_func1*)(void);
    variable2_type (getter_func2*)(void);

    /* Setter functions */
    void (setter_func1*)(variable1_type v1);
    void (setter_func2*)(variable2_type v2);
} Context;

主な質問が 3 つあります。

  1. 私が取ったアプローチは良いものですか(つまり、最高のものですか、それともより良いものですか)。そうでない場合、私がやりたいことを行うためのより推奨される (つまり、「ベスト プラクティス」) 方法はありますか?

  2. あるスレッドでスレッドローカル変数が変更された場合、その変更は他のスレッドに反映されますか? 答えが「いいえ」の場合 (私はそのように思われます)、変数に異なる値を使用して 2 つのスレッドが実行されている可能性があることを意味します。私が考えることができるほとんどすべてのアプリケーションでは、これは受け入れられません。では、既存のマルチスレッド アプリケーションでは、このシナリオをどのように回避するのでしょうか? 私の基本的な理解では、書き込みの前にロックを取得する必要があり、読み取り中のスレッドがある場合、書き込みスレッドはブロックする必要があります。そうでない場合は、イベントの正しい順序を明確にしていただければ幸いです。また、私のサンプル データ構造を使用して、この読み取り/書き込み操作を実装する方法を示す擬似コードをいくつかいただければ幸いです。

  3. コンテキスト構造体に記述したゲッター関数の疑似コードは、理想的には、明らかな理由からポインターを返す必要があります (取得されるたびに潜在的に巨大なデータ構造をコピーすることを避けるため)。ただし、質問の前半で参照した IBM のページ (提供されたリンク) によると:

再入可能関数は、連続する呼び出しで静的データを保持せず、静的データへのポインターを返しません。すべてのデータは、関数の呼び出し元によって提供されます。

したがって(私が理解しているように)、ゲッター関数は静的データへのポインターを返すことはできません(私が間違っていない限り)。誰かが明確にすることができます。また、ゲッター関数からポインターを返す必要がない場合、データのコピーを返さないようにする/回避するために使用できる方法/テクニックはありますか (私が言ったように、構造のいくつかは非常に巨大/重いです)。

[[脇]]

私は Ubuntu 12.04 LTS で開発しているので、POSIX 準拠のソリューションに興味があります。

4

1 に答える 1