バージョンごとのドキュメント一覧

56.4. その他のコーディング規約 #

<title>Miscellaneous Coding Conventions</title>

標準C #

<title>C Standard</title>

Code in <productname>PostgreSQL</productname> should only rely on language features available in the C99 standard. That means a conforming C99 compiler has to be able to compile postgres, at least aside from a few platform dependent pieces. PostgreSQLのコードはC99の標準で利用可能な言語機能にのみ依存することになっています。 つまり、C99に準拠したコンパイラであれば、少数のプラットフォーム依存の部分を除けばpostgresをコンパイルできるはずです。

A few features included in the C99 standard are, at this time, not permitted to be used in core <productname>PostgreSQL</productname> code. This currently includes variable length arrays, intermingled declarations and code, <literal>//</literal> comments, universal character names. Reasons for that include portability and historical practices. 現時点では、C99の標準に含まれる機能のいくつかはPostgreSQLのコアコードでは使うことが許可されていません。 今のところ、可変長配列、型宣言とコードの混在、//コメント、汎用文字名が含まれます。 その理由には、移植性と歴史的な慣例が含まれます。

Features from later revisions of the C standard or compiler specific features can be used, if a fallback is provided. 代替策が用意されているのであれば、それより後のバージョンの標準Cの機能、あるいはコンパイラに依存した機能を使用することもできます。

For example <literal>_Static_assert()</literal> and <literal>__builtin_constant_p</literal> are currently used, even though they are from newer revisions of the C standard and a <productname>GCC</productname> extension respectively. If not available we respectively fall back to using a C99 compatible replacement that performs the same checks, but emits rather cryptic messages and do not use <literal>__builtin_constant_p</literal>. 例えば、_Static_assert()__builtin_constant_pは、それぞれ、標準Cのより新しいバージョン由来、GCC拡張ですが、現在、使用されています。 それらが利用できない場合は、それぞれ、同じチェックをする(ただし、やや暗号的なメッセージを発する)C99互換のもので代用し、__builtin_constant_pは使いません。

関数のようなマクロとインライン関数 #

<title>Function-Like Macros and Inline Functions</title>

Both macros with arguments and <literal>static inline</literal> functions may be used. The latter are preferable if there are multiple-evaluation hazards when written as a macro, as e.g., the case with 引数付きのマクロとstatic inlineの関数のどちらも使用することができます。 マクロとして記述した場合に、複数回評価されるリスクがあるならば、後者を選択します。 例えば次のような場合です。

#define Max(x, y)       ((x) > (y) ? (x) : (y))

or when the macro would be very long. In other cases it's only possible to use macros, or at least easier. For example because expressions of various types need to be passed to the macro. あるいは、マクロにすると非常に長くなる場合も、インライン関数を選択します。 その他に、マクロだけしか利用できない、あるいはマクロの方が使いやすい場合があります。 例えば、マクロに様々な型の式を渡す必要がある場合などです。 訳注:原文は構文的に不完全だが、文脈的に考えて There are other cases where it's only... という意図であると解釈して訳した。

When the definition of an inline function references symbols (i.e., variables, functions) that are only available as part of the backend, the function may not be visible when included from frontend code. インライン関数の定義がバックエンドの一部としてのみ利用可能なシンボル(つまり、変数、関数)を参照する場合、その関数はフロントエンドのコードからインクルードされたときに不可視かもしれません。

#ifndef FRONTEND
static inline MemoryContext
MemoryContextSwitchTo(MemoryContext context)
{
    MemoryContext old = CurrentMemoryContext;

    CurrentMemoryContext = context;
    return old;
}
#endif   /* FRONTEND */

In this example <literal>CurrentMemoryContext</literal>, which is only available in the backend, is referenced and the function thus hidden with a <literal>#ifndef FRONTEND</literal>. This rule exists because some compilers emit references to symbols contained in inline functions even if the function is not used. この例では、バックエンドのみで利用可能なCurrentMemoryContextが参照されているため、関数は#ifndef FRONTENDで隠されています。 一部のコンパイラはインライン関数に含まれるシンボルの参照を、その関数が使われていなくても吐き出すため、この規則があります。

シグナルハンドラの作成 #

<title>Writing Signal Handlers</title>

To be suitable to run inside a signal handler code has to be written very carefully. The fundamental problem is that, unless blocked, a signal handler can interrupt code at any time. If code inside the signal handler uses the same state as code outside chaos may ensue. As an example consider what happens if a signal handler tries to acquire a lock that's already held in the interrupted code. シグナルハンドラの内部で実行されるのに適切であるためには、注意深くコードを書く必要があります。 根本的問題は、シグナルハンドラは、ブロックされない限り、いつでもコードに対して割り込むことができるということです。 シグナルハンドラの内側のコードが、外側のコードと同じ状態を使うと、混沌が発生するかもしれません。 例えば、シグナルハンドラが、割り込まれたコードで既に保持されているロックを獲得しようとしたら何が起きるか考えてみてください。

Barring special arrangements code in signal handlers may only call async-signal safe functions (as defined in POSIX) and access variables of type <literal>volatile sig_atomic_t</literal>. A few functions in <command>postgres</command> are also deemed signal safe, importantly <function>SetLatch()</function>. 特別に準備された状況を別にすると、シグナルハンドラのコードは、(POSIXで定義される通りの)非同期シグナルで安全な関数だけを呼ぶことができ、型volatile sig_atomic_tの変数だけにアクセスできます。 postgresでも、いくつかの関数はシグナルで安全とされており、なかでも重要なのはSetLatch()です。

In most cases signal handlers should do nothing more than note that a signal has arrived, and wake up code running outside of the handler using a latch. An example of such a handler is the following: ほとんどの場合、シグナルハンドラはシグナルが到着したことを記録し、ハンドラの外部で動作しているコードをラッチを使って呼び起こす以上のことをすべきではありません。 以下はそのようなハンドラの例です。

static void
handle_sighup(SIGNAL_ARGS)
{
    int         save_errno = errno;

    got_SIGHUP = true;
    SetLatch(MyLatch);

    errno = save_errno;
}

<varname>errno</varname> is saved and restored because <function>SetLatch()</function> might change it. If that were not done interrupted code that's currently inspecting <varname>errno</varname> might see the wrong value. errnoSetLatch()によって変更されるかもしれないので、保存して、リストアされます。 そうしなければ、割り込まれたコードが、現在errnoを参照している場合、誤った値を見ることになるかもしれません。

関数ポインタの呼び出し #

<title>Calling Function Pointers</title>

For clarity, it is preferred to explicitly dereference a function pointer when calling the pointed-to function if the pointer is a simple variable, for example: 明快にするため、ポインタが単純な変数である場合に指し示す関数を呼び出すときには、関数ポインタを以下の例のように明示的に参照することが望ましいです。

(*emit_log_hook) (edata);

(even though <literal>emit_log_hook(edata)</literal> would also work). When the function pointer is part of a structure, then the extra punctuation can and usually should be omitted, for example: emit_log_hook(edata)でも動作するとしても)。 関数ポインタが構造体の一部であるときには、以下のように、追加的な区切りは省略してよいし、通常は省略すべきです。

paramInfo->paramFetch(paramInfo, paramId);