Add some notes about coding conventions do the docs.
This deserves to be greatly expanded and improved, but it's a start. Discussion: 20150827145219.GI2435@awork2.anarazel.de
This commit is contained in:
parent
84ae1af8f4
commit
d9cb34abb4
@ -851,4 +851,109 @@ BETTER: unrecognized node type: 42
|
|||||||
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="source-conventions">
|
||||||
|
<title>Miscellaneous Coding Conventions</title>
|
||||||
|
|
||||||
|
<simplesect>
|
||||||
|
<title>C Standard</title>
|
||||||
|
<para>
|
||||||
|
Code in <productname>PostgreSQL</> should only rely on language
|
||||||
|
features available in the C89 standard. That means a conforming
|
||||||
|
C89 compiler has to be able to compile postgres, at least aside
|
||||||
|
from a few platform dependant pieces. Features from later
|
||||||
|
revision of the C standard or compiler specific features can be
|
||||||
|
used, if a fallback is provided.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For example <literal>static inline</> and
|
||||||
|
<literal>_StaticAssert()</literal> are currently used, even
|
||||||
|
though they are from newer revisions of the C standard. If not
|
||||||
|
available we respectively fall back to defining the functions
|
||||||
|
without inline, and to using a C89 compatible replacement that
|
||||||
|
performs the same checks, but emits rather cryptic messages.
|
||||||
|
</para>
|
||||||
|
</simplesect>
|
||||||
|
|
||||||
|
<simplesect>
|
||||||
|
<title>Function-Like Macros and Inline Functions</title>
|
||||||
|
<para>
|
||||||
|
Both, macros with arguments and <literal>static inline</>
|
||||||
|
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
|
||||||
|
<programlisting>
|
||||||
|
#define Max(x, y) ((x) > (y) ? (x) : (y))
|
||||||
|
</programlisting>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
When the definition 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.
|
||||||
|
<programlisting>
|
||||||
|
#ifndef FRONTEND
|
||||||
|
static inline MemoryContext
|
||||||
|
MemoryContextSwitchTo(MemoryContext context)
|
||||||
|
{
|
||||||
|
MemoryContext old = CurrentMemoryContext;
|
||||||
|
|
||||||
|
CurrentMemoryContext = context;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
#endif /* FRONTEND */
|
||||||
|
</programlisting>
|
||||||
|
In this example <literal>CurrentMemoryContext</>, 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.
|
||||||
|
</para>
|
||||||
|
</simplesect>
|
||||||
|
|
||||||
|
<simplesect>
|
||||||
|
<title>Writing Signal Handlers</title>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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 postgres are also deemed signal safe, importantly
|
||||||
|
<literal>SetLatch()</literal>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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:
|
||||||
|
<programlisting>
|
||||||
|
static void
|
||||||
|
handle_sighup(SIGNAL_ARGS)
|
||||||
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
|
got_SIGHUP = true;
|
||||||
|
SetLatch(MyLatch);
|
||||||
|
|
||||||
|
errno = save_errno;
|
||||||
|
}
|
||||||
|
</programlisting>
|
||||||
|
<literal>errno</> is safed and restored because
|
||||||
|
<literal>SetLatch()</> might change it. If that were not done
|
||||||
|
interrupted code that's currently inspecting errno might see the wrong
|
||||||
|
value.
|
||||||
|
</para>
|
||||||
|
</simplesect>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user