]> granicus.if.org Git - postgresql/commitdiff
Add some notes about coding conventions do the docs.
authorAndres Freund <andres@anarazel.de>
Fri, 11 Sep 2015 19:33:17 +0000 (21:33 +0200)
committerAndres Freund <andres@anarazel.de>
Tue, 22 Sep 2015 09:13:28 +0000 (11:13 +0200)
This deserves to be greatly expanded and improved, but it's a start.

Discussion: 20150827145219.GI2435@awork2.anarazel.de

doc/src/sgml/sources.sgml

index d6461ec3f2a50d16c53e5c40cbd87dae4b126205..fcb3e402f85a132399e3b2a46fbf3627747adb2d 100644 (file)
@@ -851,4 +851,109 @@ BETTER: unrecognized node type: 42
 
   </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>