概要 †
定義 †変数,エイリアス †マクロ †列挙型 †構造体/共用体 †Latch †
関数 †InitializeLatchSupport †extern void InitializeLatchSupport(void);
参考InitPostmasterChild() - https://git.postgresql.org/gitweb/ InitLatch †// 引数1:Latchの参照 extern void InitLatch(volatile Latch *latch);
サンプル 独自のLatchを使う(通常はMyLatchがあるのでそれを使う) volatile Latch OriginalLatch; void myworker() { InitLatch(&OriginalLatch); int rc; rc = WaitLatch(&OriginalLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, 10 * 1000L, PG_WAIT_EXTENSION); ResetLatch(&OriginalLatch); if (rc & WL_POSTMASTER_DEATH) proc_exit(1); /* Do something */ } InitSharedLatch †// 引数1:Latchの参照 extern void InitSharedLatch(volatile Latch *latch);
参考InitSharedLatch() - https://git.postgresql.org/gitweb/ OwnLatch †// 引数1:Latchの参照 extern void OwnLatch(volatile Latch *latch);
DisownLatch †// 引数1:Latchの参照 extern void DisownLatch(volatile Latch *latch);
SetLatch †// 引数1:Latchの参照 extern void SetLatch(volatile Latch *latch);
参考SetLatch() - https://git.postgresql.org/gitweb/ サンプル シグナルハンドラー内でSetLatchして待ち状態のプロセスをwake upさせる。 static volatile sig_atomic_t got_sighup = false; static void myworker_sighup(SIGNAL_ARGS) { int save_errno = errno; got_sighup = true; SetLatch(MyLatch); // waked up the waiting process errno = save_errno; } void myworker() { int rc; /* Waiting for the latch to be expired */ rc = WaitLatch(MyLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, 10 * 1000L, PG_WAIT_EXTENSION); ResetLatch(MyLatch); if (rc & WL_POSTMASTER_DEATH) proc_exit(1); /* Do something */ } ResetLatch †// 引数1:Latchの参照 extern void ResetLatch(volatile Latch *latch);
CreateWaitEventSet †// 引数1:メモリコンテキスト // 引数2:イベント数 // 戻り値:待ち受けイベントに関する情報を格納するWaitEventSet構造体のポインタ extern WaitEventSet *CreateWaitEventSet(MemoryContext context, int nevents);
サンプル void event_set_sample() { int ret = 0; int rc; WaitEvent event; /* Allocate memory for WaitEventSet which can keep a maximum of 3 events */ WaitEventSet *set = CreateWaitEventSet(CurrentMemoryContext, 3); /* Add an event for WL_LATCH_SET */ AddWaitEventToSet(set, WL_LATCH_SET, PGINVALID_SOCKET, MyLatch, NULL); /* Wait for a event to occur. */ rc = WaitEventSetWait(set, 10 * 1000L, &event, 1, PG_WAIT_EXTENSION); /* Check event flag */ if (rc == 0) ret |= WL_TIMEOUT; else { ret |= event.events & (WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_SOCKET_MASK); } /* Free memory */ FreeWaitEventSet(set); } FreeWaitEventSet †// 引数1:イベントセット構造体(WaitEventSet)の参照 extern void FreeWaitEventSet(WaitEventSet *set);
AddWaitEventToSet †// 引数1:イベントセット構造体(WaitEventSet)の参照 // 引数2:追加するイベント // 引数3:監視するファイルディスクリプタ。 // WL_LATCH_SETまたはWL_POSTMASTER_DEATHの時は、通常PGINVALID_SOCKETをセットする。 // 引数4:イベントに紐付けられるLatchの参照 // 引数5:イベントに紐付けられる、ユーザー指定可能な任意データ // 戻り値: extern int AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch, void *user_data);
ModifyWaitEvent †// 引数1:イベントセット構造体(WaitEventSet)の参照 // 引数2:イベントセット内でのイベントのposition(配列のインデックス) // 引数3:書き換え後のイベント // 引数4:イベントに紐付けられるLatchの参照 extern void ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch);
WaitEventSetWait †// 引数1:イベントセット構造体(WaitEventSet)の参照 // 引数2:タイムアウト(msec) // 引数3:発生したイベント情報を格納するWaitEvent構造体の参照 // 引数4:返される最大イベント数 // 引数5:pgstatにreportする情報 // 戻り値:発生したイベントフラグ extern int WaitEventSetWait(WaitEventSet *set, long timeout, WaitEvent *occurred_events, int nevents, uint32 wait_event_info);
参考WaitEventSetWait() - https://git.postgresql.org/gitweb/ WaitLatch †// 引数1:監視したいLatchの参照 // 引数2:タイムアウト(msec) // 引数3:pgstatにreportする情報 // 戻り値:発生したイベントフラグ extern int WaitLatch(volatile Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info);
WaitLatchOrSocket †// 引数1:監視したいLatchの参照 // 引数2:タイムアウト(msec) // 引数3:イベント監視するファイルディスクリプタ // 引数4:pgstatにreportする情報 // 戻り値:発生したイベントフラグ extern int WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock, long timeout, uint32 wait_event_info);
サンプルプログラム †static volatile sig_atomic_t got_sighup = false; static void myworker_sighup(SIGNAL_ARGS) { int save_errno = errno; got_sighup = true; /* MyLatchでwaitするプロセスをwake upする */ SetLatch(MyLatch); errno = save_errno; } void myworker(Datum main_arg) { int arg = DatumGetInt32(main_arg); /* We're now ready to receive signals */ BackgroundWorkerUnblockSignals(); for (;;) { int ret; int rc; /* MyLatchがSetLatchされる、タイムアウトする、またはpostmasterが死ぬイベントを待つ。10秒でタイムアウト。 */ rc = WaitLatch(MyLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, 10 * 1000L, PG_WAIT_EXTENSION); /* MyLatchのsetフラグをクリアする */ ResetLatch(MyLatch); /* Emergency bailout if postmaster has died */ if (rc & WL_POSTMASTER_DEATH) proc_exit(1); CHECK_FOR_INTERRUPTS(); /* * In case of a SIGHUP, just reload the configuration. */ if (got_sighup) { got_sighup = false; ProcessConfigFile(PGC_SIGHUP); } /* Do something */ } proc_exit(1); } メモ MyLatch以外のLatchを使うことも可能である。例えば、WaitLatchでMyLatchではないLatchを渡しており、シグナルハンドラでMyLatchにSetLatchするような場合。この場合、myworker_sighup関数でMyLatchがsetされるが、WaitLatchからはWL_LATCH_SETイベントでは戻らない。SetLatchでpipeへの書き込みイベントは起きるが、WaitLatchで渡しているOriginalLatchはsetされていないためである。 static void myworker_sighup(SIGNAL_ARGS) { int save_errno = errno; got_sighup = true; /* MyLatchでwaitするプロセスをwake upする */ SetLatch(MyLatch); errno = save_errno; } /* MyLatchとは別のLatch */ volatile Latch OriginalLatch; void myworker(Datum main_arg) { int arg = DatumGetInt32(main_arg); /* We're now ready to receive signals */ BackgroundWorkerUnblockSignals(); for (;;) { int rc; /* MyLatchではないLatchでイベントを待つ */ rc = WaitLatch(&OriginalLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, 10 * 1000L, PG_WAIT_EXTENSION); /* ResetLatch(&OriginalLatch); */ /* Do something */ } } 参考・関連 †
関連 コメント † |