「純粋な」C/C++ (それが何を意味するかは問わない) のみを検討するよう、回答者に依頼してもよろしいですか? STLは大丈夫です。ブーストはありません。
共有メモリ内の C++ オブジェクトの割り当てと割り当て解除のために、独自の C++ メモリ プール クラス (Linux システム上) を作成しています。複数のプロセスで同じオブジェクトにアクセスするには、これが必要です。POSIX セマフォを使用してメモリ プール オブジェクト操作へのアクセスを制御しますが、基本的な割り当て/割り当て解除に関する質問がありました。私のコードは、同じプールから割り当てられた同じサイズのオブジェクトに対してのみ機能します。現時点では、プールの動的な拡大と縮小に関連する問題は無視できます。
合計 MAXFOOOBJECTS 個の Foo オブジェクトに対して定義された共有メモリ セグメントがあるとします。共有メモリ セグメントを次のように定義します。
int shmid = shmget (somekey, ((sizeof(Foo) + 4) * MAXFOOOBJECTS) + 4, correctFlags);
void* sMem = shmat (shmid, (void*)0, 0);
この共有メモリを使用するすべてのプロセスによって、メモリは次のように解釈されます。
struct SharedMemStructure
{
int numberOfFooObjectsInPool;
Foo* ptrArray [MAXFOOOBJECTS]; // Pointers to all the objects in the array below
Foo objects [MAXFOOOBJECTS]; // Same as the value in the shmget call
};
次のように定義されたオブジェクト Foo があるとします。
<Foo.h>
class Foo
{
public:
Foo ();
~Foo ();
void* operator new (); // Will allocate from shared memory
void operator delete (void* ptr); // Will deallocate from shared memory
private:
static void* sharedMem; // Set this up to be a POSIX shared memory that accesses
// the shared region in memory
static int shmid;
}
<Foo.cpp>
int Foo::shmid = shmget (somekey, ((sizeof(Foo) + 4) * MAXFOOOBJECTS) + 4, correctFlags);
void* Foo::sharedMem = shmat (shmid, (void*)0, 0);
void* Foo::operator new ()
{
void* thisObject = NULL;
sem_wait (sem); // Implementation of these is not shown
// Pick up the start of a chunk from sharedMem (will make sure this
// chunk has unused memory...
thisObject = (sharedMem + 4 + 4 * MAXFOOOBJECTS +
(sizeof (Foo) * sharedMem->numberOfFooObjectsInPool);
sharedMem->ptrArray[numberOfFooObjectsInPool] = thisObject;
sharedMem->numberOfFooObjectsInPool ++;
sem_post (sem);
return thisObject;
}
void Foo::operator delete (void* ptr)
{
int index = 0;
sem_wait (sem); // Implementation of these is not shown
// Swap the deleted item and the last item in the ptrArray;
index = (ptr - (sharedMem + 4 + (4*MAXFOOOBJECTS)))/(sizeof(Foo));
ptrArray[index] == ptrArray[numberOfFooObjectsInPool - 1];
numberOfFooObjectsInPool --;
sem_post (sem);
}
さて、私の質問は次のとおりです。
- 前述のスキームは、皆さん (新規と削除のそれぞれに O (1)) には問題ないように見えますか?それとも、まったく重要な何かが欠けていますか? すぐにわかる問題の 1 つは、たとえば Foo オブジェクト配列が最小ヒープとして解釈される場合、new と delete を実行するたびにヒープ プロパティを強制終了することです。
- このプールが最小ヒープに使用されないことを保証する場合 (たとえば、タイマー管理手法で必要な場合)、前述のスキームに問題はありますか?
- 反対に、共有メモリ内の Foo 配列を最小ヒープまたは最大ヒープとして (つまり、新規および削除中に) 管理し、新規または削除ごとに O (lg n) の最悪のケースを招く可能性があります。コメントはありますか?
- 望ましい他の方法はありますか?