#author("2017-05-18T22:50:59+09:00","default:haikikyou","haikikyou")
[[PostgreSQL/開発]]

#contents

* 概要 [#v016fcb6]

- メモリ操作のためのAPI
- メモリはchunkと呼ばれる塊単位で扱われ,context(chunkを管理)に紐づくようになっている
- contextは木構造で管理されており,上位のcontextを破棄することで,下位のcontextの領域もまとめて解放することができる

* 定義 [#de809d9f]

** マクロ [#j74669cf]

*** MemoryContextAllocExtendedのフラグ [#n24f4e6e]

|~マクロ名|~説明|h
|MCXT_ALLOC_HUGE||
|MCXT_ALLOC_NO_OOM||
|MCXT_ALLOC_ZERO||
** 列挙型 [#y26f0bb4]

** 構造体 [#r96eb7d4]

*** MemoryContextCallback [#gc5e6723]

|~番号|~データ型|~フィールド|~説明|h
|1|MemoryContextCallbackFunction|func|コールバック関数|
|2|void*|arg|コールバック関数に渡される引数|
|3|struct MemoryContextCallback|next|コールバック関数リストの次ノード。&br;コールバック関数はリスト構造で管理されており複数のコールバック関数を登録できる。|

*** MemoryContext [#o4c8d69a]

MemoryContextDataポインタの別名

#geshi(c){{
typedef struct MemoryContextData *MemoryContext;
}}

&size(12){&color(white,orange){ 参考 };};  [[struct MemoryContextData >https://doxygen.postgresql.org/structMemoryContextData.html]] - on doxygen.postgresql.org
** 関数 [#f482c76f]

*** MemoryContextAlloc [#g8ba4852]

#geshi(c){{
// 引数1:アロケーション対象のコンテキスト
// 引数2:割当てサイズ(byte)
// 戻り値:メモリチャンク
extern void *MemoryContextAlloc(MemoryContext context, Size size);
}}

- アロケーション処理は,AllocSetAlloc関数で行われる。
- 引数で指定されたメモリコンテキストに指定されたサイズのメモリ領域を確保する。
- チャンクリミットを超える場合は,新規にブロックが作成される。そうでない場合は,フリーリストから検索される。
- アクティブなアロケーションブロックにチャンクスペースがあれば,チャンクをブロックに確保しチャンクのポインタを返す。チャンクスペースがなければ,ブロックの残りの領域を整備しチャンクをフリーリストに置く。
- ブロックがなければ,新規にブロックを作成してチャンクのポインタを返す。

&size(12){&color(white,orange){ 参考 };}; - [[AllocSetAlloc()>https://doxygen.postgresql.org/aset_8c.html#a8b691370b6119226738db0605b5156bb]] - on doxygen.postgresql.org

&size(12){&color(white,#00afcc){ サンプル };};
#geshi(c){{
void memory_sample()
{
    // 専用のコンテキストを作成
    MemoryContext *context = AllocSetContextCreate(CurrentMemoryContext,
                                                   "mycontext",
                                                   0,
                                                   8 * 1024,
                                                   8 * 1024);
    MemoryContext *oldcontext = NULL;

    // カレントコンテキストのスイッチ
    oldcontext = MemoryContextSwitchTo(context);

    // メモリチャンクが返される
    MyExtensionOptions *opt = (MyExtensionOptions*) MemoryContextAlloc(context,
                                                                       sizeof(MyExtensionOptions));
    // pallocは,内部でCurrentMemoryContextを使う
    // MyExtensionOptions *opt  = (MyExtensionOptions*)palloc(sizeof(MyExtensionOptions));
    opt->optcontext = ForeignTableRelationId;
    opt->optname = pstrdup("option1");

    MemoryContextSwitchTo(oldcontext);
    MemoryContextDelete(context);
}
}}
*** MemoryContextAllocZero [#g8ba4852]

#geshi(c){{
// 引数1:アロケーション対象のコンテキスト
// 引数2:アロケーションサイズ(byte)
// 戻り値:メモリチャンク
extern void *MemoryContextAllocZero(MemoryContext context, Size size);
}}

- MemoryContextAlloc()と同様にメモリ領域をコンキストに確保する。
- 確保されたチャンクを返す前に0初期化される。
- アライメントされているかがチェックされ,memsetをするかどうかが判定される。

*** MemoryContextAllocZeroAligned [#g8ba4852]

#geshi(c){{
// 引数1:アロケーション対象のコンテキスト
// 引数2:アロケーションサイズ(byte)
// 戻り値:メモリチャンク
extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size);
}}

- MemoryContextAlloc()と同様にメモリ領域をコンキストに確保する。
- MemoryContextAllocZero()との違いは,アライメントのチェックがない点。

*** MemoryContextAllocExtended [#g8ba4852]

#geshi(c){{
// 引数1:アロケーション対象のコンテキスト
// 引数2:アロケーションサイズ(byte)
// 引数3:メモリアロケーション動作を決めるフラグ
// 戻り値:メモリチャンク
extern void *MemoryContextAllocExtended(MemoryContext context, Size size, int flags);
}}

- 基本的には,MemoryContextAlloc()と同様にメモリ領域をコンキストに確保する。
- 違いは,フラグによって細かな動作を指定できる点である。

&size(12){&color(white,orange){ 参考 };}; - [[MemoryContextAllocExtended ()>https://doxygen.postgresql.org/palloc_8h.html#a7093367d96f76697f3a7e8e534b1115e]] - on doxygen.postgresql.org

&size(12){&color(white,#00afcc){ サンプル };};
#geshi(c){{
typedef struct MyExtensionOptions {
    const char *optname;
    Oid optcontext;
} MyExtensionOptions;

void memory_sample()
{
    MemoryContext *context = AllocSetContextCreate(CurrentMemoryContext,
                                                   "mycontext",
                                                   0,
                                                   8 * 1024,
                                                   8 * 1024);
    MemoryContext *oldcontext = NULL;

    oldcontext = MemoryContextSwitchTo(context);

    // 0クリア and メモリ確保失敗時にエラー報告
    MyExtensionOptions *opt = (MyExtensionOptions*) MemoryContextAllocExtended(context,
                                                                               sizeof(MyExtensionOptions),
                                                                               MCXT_ALLOC_ZERO | MCXT_ALLOC_NO_OOM);

    opt->optcontext = ForeignTableRelationId;
    opt->optname = pstrdup("option1");

    MemoryContextSwitchTo(oldcontext);
    MemoryContextDelete(context);
}
}}


*** palloc [#g8ba4852]

#geshi(c){{
// 引数1:
extern void *palloc(Size size);
}}

*** palloc0 [#g8ba4852]

#geshi(c){{
// 引数1:
extern void *palloc0(Size size);
}}

*** palloc_extended [#g8ba4852]

#geshi(c){{
// 引数1:
extern void *palloc_extended(Size size, int flags);
}}

*** repalloc [#g8ba4852]

#geshi(c){{
// 引数1:
// 引数2:
extern void *repalloc(void *pointer, Size size);
}}

*** pfree [#g8ba4852]

#geshi(c){{
// 引数1:
extern void pfree(void *pointer);
}}

*** MemoryContextAllocHuge [#g8ba4852]

#geshi(c){{
// 引数1:
// 引数2:
extern void *MemoryContextAllocHuge(MemoryContext context, Size size);
}}


*** repalloc_huge [#g8ba4852]

#geshi(c){{
// 引数1:
// 引数2:
extern void *repalloc_huge(void *pointer, Size size);
}}

*** MemoryContextSwitchTo [#g8ba4852]

#geshi(c){{
// 引数1:
// 戻り値:
MemoryContext MemoryContextSwitchTo(MemoryContext context)
}}

*** MemoryContextRegisterResetCallback [#g8ba4852]

#geshi(c){{
// 引数1:
// 引数2:
// 戻り値:
extern void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb);
}}

*** MemoryContextStrdup [#g8ba4852]

#geshi(c){{
// 引数1:
// 引数2:
// 戻り値:
extern char *MemoryContextStrdup(MemoryContext context, const char *string);
}}

*** pstrdup [#g8ba4852]

#geshi(c){{
// 引数1:
// 戻り値:
extern char *pstrdup(const char *string);
}}


*** pnstrdup [#g8ba4852]

#geshi(c){{
// 引数1:
// 引数2:
// 戻り値:
extern char *pnstrdup(const char *in, Size len);
}}

*** psprintf [#g8ba4852]

#geshi(c){{
// 引数1:
// 戻り値:
extern char *psprintf(const char *fmt,...) pg_attribute_printf(1, 2);
}}


*** pvsnprintf [#g8ba4852]

#geshi(c){{
// 引数1:
// 引数2:
// 引数3:
// 戻り値:
extern size_t pvsnprintf(char *buf, size_t len, const char *fmt, va_list args) pg_attribute_printf(3, 0);
}}
* サンプルプログラム [#u70bfc73]

#geshi(c){{
// sample
}}

* 参考・関連 [#h201be4f]

- [[palloc.h>https://doxygen.postgresql.org/palloc_8h.html]] - on doxygen.postgresql.org
- [[memnodes.h>https://doxygen.postgresql.org/memnodes_8h.html]] - on doxygen.postgresql.org
- [[mcxt.c>https://doxygen.postgresql.org/mcxt_8c.html]] - on doxygen.postgresql.org
- [[aset.c>https://doxygen.postgresql.org/aset_8c.html]] - on doxygen.postgresql.org
- [[NTTデータ 井久保さんによる解析資料 ~ メモリ管理 ~>http://ikubo.x0.com/PostgreSQL/pdf/IK05_Memory_040702.pdf]] - http://ikubo.x0.com/PostgreSQL/pg_source.htm

&size(12){&color(white,orange){ 関連 };};

#related
* コメント [#baa736e7]

#comment

トップ   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
目次
ダブルクリックで閉じるTOP | 閉じる
GO TO TOP