summaryrefslogtreecommitdiff
path: root/docs/ACE-guidelines.html
diff options
context:
space:
mode:
authornobody <nobody@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2003-01-16 00:03:09 +0000
committernobody <nobody@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2003-01-16 00:03:09 +0000
commit7813ab75260f5a82b5ff17c83c7c2c39c60094f7 (patch)
tree5062ed2052bebf0eb399411eef7e250600f4b6bb /docs/ACE-guidelines.html
parentaae953155ecb34d716afbd5039774e8fd6def06f (diff)
downloadATCD-TAO-1_3.tar.gz
This commit was manufactured by cvs2svn to create tag 'TAO-1_3'.TAO-1_3
Diffstat (limited to 'docs/ACE-guidelines.html')
-rw-r--r--docs/ACE-guidelines.html1198
1 files changed, 0 insertions, 1198 deletions
diff --git a/docs/ACE-guidelines.html b/docs/ACE-guidelines.html
deleted file mode 100644
index a25ca2ef9a8..00000000000
--- a/docs/ACE-guidelines.html
+++ /dev/null
@@ -1,1198 +0,0 @@
-<!-- $Id$ -->
-
-<html>
- <head>
- <title>ACE Software Development Guidelines</title>
- <link rev=made href="mailto:levine@cs.wustl.edu">
- </head>
-
-<body text = "#000000"
-link="#000fff"
-vlink="#ff0f0f"
-bgcolor="#ffffff">
-
-<hr>
-<h3>ACE Software Development Guidelines</h3>
-
-<ul>
- <li><strong>General</strong><p>
- <ul>
- <li>Every text file must end with a newline.<p>
-
- <li>Use spaces instead of tabs, except in Makefiles. Emacs users
- can add this to their <strong>.emacs</strong>:
-
- <pre>(setq-default indent-tabs-mode nil)</pre></p>
-
- Microsoft Visual C++ users should do the following:
-
- <pre>
- Choose: Tools -- Options -- Tabs
- Then Set: "Tab size" to 8 and "Indent size" to 2, and
- indent using spaces.
- </pre><p>
-
- <li>Do not end text lines with spaces. Emacs users can add this to
- their <strong>.emacs</strong>:
-
- <pre>(setq-default nuke-trailing-whitespace-p t)</pre><p>
-
- <li>Try to limit the length of source code lines to less than 80
- characters. Users with 14 inch monitors appreciate it when
- reading code. And, it avoids mangling problems with email
- and net news.<p>
-
- <li>If you add a comment to code that is directed to, or
- requires the attention of, a particular individual:
- <strong>SEND EMAIL TO THAT INDIVIDUAL!</strong>.<p>
-
- <li>Every program should have a ``usage'' message. It should be
- printed out if erroneous command line arguments, or a
- <strong><code>-?</code></strong> command line argument, are
- provided to the program.<p>
-
- <li>A program entry poing <code>main</code> can take any of the
- three forms:
- <p><pre>
- int main (int argc, char *argv[])
- int wmain (int argc, wchar_t *argv[])
- int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
- </pre></p>
- Of them, the entry point <code>main</code> always gives you
- the command line arguemnt in char strings form. The entry
- point <code>wmain</code> currently can only be used under
- Win32 and it returns the command line arguments in wchar
- strings format. Defining the <code>ACE_TMAIN</code> as the
- program entry point is the more portable form. The command
- line arguments are given in char strings in most cases,
- or wchar strings when <code>ACE_USES_WCHAR</code> is defined.
- See <code>$ACE_ROOT/docs/wchar.txt</code> for more information
- on ACE support on wchar.
-
- <li>The program entry point function, in any form mentioned above, must
- always be declared with arguments, <em>e.g.</em>,
- <pre>
- int
- ACE_TMAIN (int argc, ACE_TCHAR *argv[])
- {
- [...]
-
- return 0;
- }
- </pre><p>
-
- If you don't use the <code>argc</code> and/or <code>argv</code>
- arguments, don't declare them, <em>e.g.</em>,
- <pre>
- int
- ACE_TMAIN (int, ACE_TCHAR *[])
- {
- [...]
-
- return 0;
- }
- </pre><p>
-
- Please declare the second argument as <code>ACE_TCHAR *[]</code>
- instead of <code>ACE_TCHAR **</code> or <code>char *[]</CODE>.
- Ancient versions of MSC
- complained about <code>ACE_TCHAR **</code> and <code>char
- *[]</CODE> is not Unicode-compliant.<p>
-
- <code>main</code> must also return 0 on successful
- termination, and non-zero otherwise.<p>
-
- <li>Avoid use of floating point types (float and double) and operations
- unless absolutely necessary. Not all ACE platforms support them.
- Therefore, wherever they are used, ACE_LACKS_FLOATING_POINT
- conditional code must be also be used.<p>
-
- <li>Avoid including the string ``Error'' in a source code filename.
- GNU Make's error messages start with ``Error''. So, it's much
- easier to search for errors if filenames don't contain ``Error''.<p>
-
- <li>Narrow interfaces are better than wide interfaces. If there
- isn't a need for an interface, leave it out. This eases maintenance,
- minimizes footprint, and reduces the likelihood of interference
- when other interfaces need to be added later. (See the
- <a href="#ACE_Time_Value example">ACE_Time_Value example</a>
- below.<p>
-
- </ul>
-
- <li><strong>Code Documentation</strong><p>
- <ul>
- <li>Use comments and whitespace (:-) liberally. Comments
- should consist of complete sentences, <em>i.e.</em>, start
- with a capital letter and end with a period.<p>
-
- <li>Insert a CVS/RCS keyword string at the top of every source file,
- Makefile, config file, <em>etc</em>. For C++ files, it is:
- <pre>
- // $<!-- -->Id$
- </pre>
- It is not necessary to fill in the fields of the keyword string,
- or modify them when you edit a file that already has one. CVS
- does that automatically when you checkout or update the file.<p>
-
- To insert that string at the top of a file:
- <pre>
- perl -pi -e \
- 'if (! $o) {printf "// \$<!-- -->Id\$\n\n";}; $o = 1;' <em>file</em>
- </pre><p>
-
- <li>Be sure to follow the guidelines and restrictions for use of the
- documentation tools for ACE
- header files, which must follow the
- <a href="http://www.doxygen.org/">Doxygen</a>
- format requirements.
- The complete documentation for Doxygen is available in the
- <a href="http://www.stack.nl/~dimitri/doxygen/download.html#latestman">Doxygen
- manual</a>.
- For an example header file using Doxygen-style comments,
- please refer to <a href="../ace/ACE.h">ACE.h</a>.<p>
- </ul>
-
- <li><strong>Preprocessor</strong><p>
- <ul>
- <li>Never #include standard headers directly, except in a few
- specific ACE files, <em>e.g.</em>, OS.h and stdcpp.h. Let
- those files #include the correct headers. If you do not do
- this, your code will not compile with the Standard C++ Library.<p>
-
- <li>Always follow a preprocessor <strong><code>#endif</code></strong>
- with a <strong><code>/* */</code></strong> C-style comment. It
- should correspond to the condition in the matching
- <strong><code>#if</code></strong> directive. For example,
- <pre>
- #if defined (ACE_HAS_THREADS)
- # if defined (ACE_HAS_STHREADS)
- # include /**/ &lt;synch.h&gt;
- # include /**/ &lt;thread.h&gt;
- # define ACE_SCOPE_PROCESS P_PID
- # define ACE_SCOPE_LWP P_LWPID
- # define ACE_SCOPE_THREAD (ACE_SCOPE_LWP + 1)
- # else
- # define ACE_SCOPE_PROCESS 0
- # define ACE_SCOPE_LWP 1
- # define ACE_SCOPE_THREAD 2
- # endif /* ACE_HAS_STHREADS */
- #endif /* ACE_HAS_THREADS */
- </pre><p>
-
- <li>Be sure to put spaces around comment delimiters, e.g.,
- <strong><code>char * /* foo */</code></strong> instead of
- <strong><code>char */*foo*/</code></strong>. MS VC++
- complains otherwise.<p>
-
- <li>Always insert a <strong><code>/**/</code></strong> between an
- <strong><code>#include</code></strong> and
- <strong><code>filename</code></strong>, as shown in the above
- example. This avoids dependency problems with Visual C++.<p>
-
- <li>Be very careful with names of macros, enum values, and variables
- It's always best to prefix them with something like <code>ACE_</code>
- or <code>TAO_</code>. There are too many system headers out
- there that #define <code>OK</code>, <code>SUCCESS</code>,
- <code>ERROR</code>, <code>index</code>, <code>s_type</code>,
- and so on.<p>
-
- <li>When using macros in an arithmetic expression, be sure to test
- that the macro is defined, using defined(macro) before specifying
- the expression. For example:
-<pre>
-#if __FreeBSD__ &lt; 3
-</pre>
-
-will evaluate true on any platform where __FreeBSD__ is not defined.
-The correct way to write that guard is:
-<pre>
-#if defined (__FreeBSD__) && __FreeBSD__ &lt; 3
-</pre>
-
- <li>Try to centralize <code>#ifdefs</code> with <code>typedefs</code>
- and <code>#defines</code>. For example, use this:
- <pre>
- #if defined(ACE_PSOS)
- typedef long ACE_NETIF_TYPE;
- # define ACE_DEFAULT_NETIF 0
- #else /* ! ACE_PSOS */
- typedef const TCHAR* ACE_NETIF_TYPE;
- # define ACE_DEFAULT_NETIF ASYS_TEXT("le0")
- #endif /* ! ACE_PSOS */
- </pre><p>
-
- instead of:
-
- <pre><p>
- #if defined (ACE_PSOS)
- // pSOS supports numbers, not names for network interfaces
- long net_if,
- #else /* ! ACE_PSOS */
- const TCHAR *net_if,
- #endif /* ! ACE_PSOS */
- </pre><p>
-
- <li>Protect header files against multiple inclusion with this
- construct:
- <pre>
- #ifndef FOO_H
- #define FOO_H
-
- [contents of header file]
-
- #endif /* FOO_H */
- </pre><p>
-
- This exact construct (note the <code>#ifndef</code>)
- is optimized by many compilers such they only open the
- file once per compilation unit. Thanks to Eric C. Newton
- &lt;ecn@smart.net&gt; for pointing that out.<p>
-
- If the header <code>#includes</code> an ACE library header,
- then it's a good idea to include the <code>#pragma once</code>
- directive:
- <pre>
- #ifndef FOO_H
- #define FOO_H
-
- #include "ace/ACE.h"
- #if !defined (ACE_LACKS_PRAGMA_ONCE)
- # pragma once
- #endif /* ACE_LACKS_PRAGMA_ONCE */
-
- [contents of header file]
-
- #endif /* FOO_H */
- </pre><p>
-
- <code>#pragma once</code> must be protected, because some
- compilers complain about it. The protection depends on
- <code>ACE_LACKS_PRAGMA_ONCE</code>, which is defined in
- some ACE config headers. Therefore, the protected
- <code>#pragma once</code> construct should only be used after
- an <code>#include</code> of an ACE library header. Note that
- many compilers enable the optimization if the <code>#ifndef</code>
- protection construct is used, so for them, <code>#pragma once</code>
- is superfluous.<p>
-
- <strong>No</strong> code can appear after the final
- <code>#endif</code> for the optimization to be effective and
- correct.<p>
-
- <li><p>Files that contain parametric classes should follow this style:
- <pre>
- #ifndef FOO_T_H
- #define FOO_T_H
-
- #include "ace/ACE.h"
- #if !defined (ACE_LACKS_PRAGMA_ONCE)
- # pragma once
- #endif /* ACE_LACKS_PRAGMA_ONCE */
-
- // Put your template declarations here...
-
- #if defined (__ACE_INLINE__)
- #include "Foo_T.i"
- #endif /* __ACE_INLINE__ */
-
- #if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
- #include "Foo_T.cpp"
- #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
-
- #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
- #pragma implementation "Foo_T.cpp"
- #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
-
- #endif /* FOO_T_H */
-</pre></p>
- <p>
- Notice that some compilers need to see the code of the template,
- hence the <code>.cpp</code> file must be included from the
- header file.
- </p>
- <p>
- To avoid multiple inclusions of the <code>.cpp</code> file it
- should also be protected as in:
- <pre>
- #ifndef FOO_T_C
- #define FOO_T_C
-
- #include "Foo_T.h"
- #if !defined (ACE_LACKS_PRAGMA_ONCE)
- # pragma once
- #endif /* ACE_LACKS_PRAGMA_ONCE */
-
- #if !defined (__ACE_INLINE__)
- #include "ace/Foo_T.i"
- #endif /* __ACE_INLINE__ */
-
- ACE_RCSID(lib, Foo_T, "$<!-- -->Id$")
-
- // put your template code here
-
- #endif /* FOO_T_H */
-</pre></p>
- <p>Finally, you may want to include the template header file from a
- non-template header file (check
- <code>$ACE_ROOT/ace/Synch.h</code>); in such a case the template
- header should be included <strong>after</strong> the inline
- function definitions, as in:</p>
- <p><pre>
- #ifndef FOO_H
- #define FOO_H
-
- #include "ace/ACE.h"
- #if !defined (ACE_LACKS_PRAGMA_ONCE)
- # pragma once
- #endif /* ACE_LACKS_PRAGMA_ONCE */
-
- // Put your non-template declarations here...
-
- #if defined (__ACE_INLINE__)
- #include "Foo.i"
- #endif /* __ACE_INLINE__ */
-
- #include "Foo_T.h"
-
- #endif /* FOO_H */
-</pre></p></li>
-
- <li>Avoid <code>#include &lt;math.h&gt;</code> if at all possible.
- The <code>/usr/include/math.h</code> on SunOS 5.5.1 through 5.7
- defines a struct name <strong>exception</strong>, which complicates
- use of exceptions.<p>
-
- <li>On a <code>.cpp</code> file always include the corresponding
- header file <em>first</em>, like this:<p>
-<pre>
- // This is Foo.cpp
-
- #include "Foo.h"
- #include "tao/Bar.h"
- #include "ace/Baz.h"
-
- // Here comes the Foo.cpp code....
-</pre><p>
-
- In this way we are sure that the header file is self-contained
- and can be safely included from some place else.
-
- <li>In the TAO library <strong>never</strong> include
- <code>&lt;corba.h&gt</code>, this file should only be included
- by the user and introduces cyclic dependencies in the library
- that we must avoid.<p>
-
- <li>Never include a header file when a forward reference will do,
- remember that templates can be forward referenced too.
- Consult your favorite C++ book to find out when you must include
- the full class definition.<p>
- </ul>
-
- <li><strong>C++ Syntax and Constructs</strong><p>
- <ul>
- <li><strong><code>for</code></strong> loops should look like:
- <pre>
- for (u_int i = 0; i &lt; count; ++i)
- ++total;
- </pre>
- Though, I prefer to always wrap the body of the loop in braces,
- to avoid surprises when other code or debugging statements are
- added, and to maintain sanity when the body consists of a macro,
- such as an ACE_ASSERT without a trailing semicolon:
- <pre>
- for (u_int i = 0; i &lt; count; ++i)
- {
- ACE_ASSERT (++total &lt; UINT_MAX;)
- }
- </pre><p>
-
- Similarly, <strong><code>if</code></strong> statements should have
- a space after the ``<strong>if</strong>'', and no spaces just after
- the opening parenthesis and just before the closing parenthesis.<p>
-
- <li>If a loop index is used after the body of the loop, it
- <strong>must</strong> be declared before the loop. For example,
-
- <pre>
- size_t i = 0;
- for (size_t j = 0; file_name [j] != '\0'; ++i, ++j)
- {
- if (file_name [j] == '\\' && file_name [j + 1] == '\\')
- ++j;
-
- file_name [i] = file_name [j];
- }
-
- // Terminate this string.
- file_name [i] = '\0';
- </pre><p>
-
- <li>Prefix operators are sometimes more efficient than postfix
- operators. Therefore, they are preferred over their postfix
- counterparts where the expression value is not used.<p>
-
- Therefore, use this idiom for iterators, with prefix operator
- on the loop index:
- <pre>
- ACE_Ordered_MultiSet&lt;int&gt; set;
- ACE_Ordered_MultiSet_Iterator&lt;int&gt; iter(set);
-
- for (i = -10; i &lt; 10; ++i)
- set.insert (2 * i + 1);
-
- </pre>
- rather than the postfix operator:
- <pre>
- for (i = -10; i &lt; 10; i++)
- set.insert (2 * i + 1);
- </pre><p>
-
- <li>Prefer using <strong> <code> if (...) else .... </code> </strong>
- instead of <strong> <code> ?: </code> </strong> operator. It is a lot
- less error prone, and will help you avoid bugs caused due to the
- precedence of <strong> <code> ?: </code> </strong>, compared with other
- operators in an expression.
-
- <li>When a class provides operator==, it must also provide
- operator!=. Also, both these operators must be const.
-
- <li>Avoid unnecessary parenthesis. We're not writing Lisp :-)<p>
-
- <li>Put inline member functions in a <strong><code>.i</code></strong>
- file. That file is conditionally included by both the
- <strong><code>.h</code></strong> file, for example:<p>
-
- <pre>
- class ACE_Export ACE_High_Res_Timer
- {
- [...]
- };
-
- #if defined (__ACE_INLINE__)
- #include "ace/High_Res_Timer.i"
- #endif /* __ACE_INLINE__ */
- </pre><p>
-
- and <strong><code>.cpp</code></strong> file:<p>
-
- <pre>
- #define ACE_BUILD_DLL
- #include "ace/High_Res_Timer.h"
-
- #if !defined (__ACE_INLINE__)
- #include "ace/High_Res_Timer.i"
- #endif /* __ACE_INLINE__ */
-
- ACE_ALLOC_HOOK_DEFINE(ACE_High_Res_Timer)
- </pre><p>
-
- <strong>NOTE:</strong> It is very important to ensure than an
- inline function will not be used before its definition is seen.
- Therefore, the inline functions in the .i file should be arranged
- properly. Some compilers, such as <code>g++</code> with the
- <code>-Wall</code> option, will issue warnings for violations.<p>
-
- <li>Some inlining heuristics:<p>
- <ul>
- <li>One liners should almost always be inline, as in:
-<pre>
-ACE_INLINE
-Foo::bar ()
-{
- this-&gt;baz();
-}
-</pre><p>
-
- <li>The notable exception is virtual functions, which should never be
- inlined.<p>
-
- <li>Big (more than 10 lines) and complex function (more than one if ()
- statement, or a switch, or a loop) should not be inlined.<p>
-
- <li>Medium sized stuff depends on how performance critical it is.
- If you know that it's in the critical path, then make it inline.<p>
- </ul>
-
- <li><code>ACE_Export</code> must be inserted between the
- <code>class</code> keyword and class name for all classes that
- are exported from libraries, as shown in the example above.
- <strong>However</strong>, do <strong>not</strong> use
- <code>ACE_Export</code> for template classes!<p>
-
- <li>Mutators and accessors should be of this form:<p>
-
- <pre>
- void object_addr (const ACE_INET_Addr &);
- // Sets &lt;object_addr_&gt; cache from &lt;host&gt; and &lt;port&gt;.
-
- const ACE_INET_Addr &object_addr const (void);
- // Returns the &lt;ACE_INET_Addr&gt; for this profile.
- </pre><p>
-
- instead of the ``set_'' and ``get_'' form.<p>
-
- <li>Never use <strong><code>delete</code></strong> to deallocate
- memory that was allocated with <strong><code>malloc</code></strong>.
- Similarly, never associate <strong><code>free</code></strong> with
- <strong><code>new</code></strong>.
- <strong><code>ACE_NEW</code></strong> or
- <strong><code>ACE_NEW_RETURN</code></strong> should be used to
- allocate memory, and <strong><code>delete</code></strong> should
- be used to deallocate it. And be careful to use the correct form,
- <strong><code>delete</code></strong> or
- <strong><code>delete []</code></strong> to correspond to the
- allocation.<p>
-
- <li>Don't check for a pointer being 0 before deleting it. It's
- always safe to delete a 0 pointer. If the pointer is visible
- outside the local scope, it's often a good idea to 0 it
- _after_ deleting it. Note, the same argument applies to
- free().<p>
-
- <li>Always use <strong><code>ACE_NEW</code></strong> or
- <strong><code>ACE_NEW_RETURN</code></strong> to allocate memory,
- because they check for successful allocation and set errno
- appropriately if it fails.<p>
-
- <li>Never compare or assign a pointer value with <strong>NULL</strong>;
- use <strong>0</strong> instead. The language allows any pointer to
- be compared or assigned with <strong>0</strong>. The definition
- of <strong>NULL</strong> is implementation dependent, so it is
- difficult to use portably without casting.<p>
-
- <li>Never use TRUE, true, or anything else other than 1 to indicate
- true. Never use FALSE, false, or anything else other than 0 to
- indicate false.<p>
-
- <li>Never cast a pointer to or from an <strong><code>int</code></strong>.
- On all currently supported ACE platforms, it is safe to cast
- a pointer to or from a <strong><code>long</code></strong>.<p>
-
- <li>Be very careful when selecting an integer type that must be a
- certain size, <em>e.g.</em>, 4 bytes. <strong>long</strong> is
- not 4 bytes on all platforms; it is 8 bytes on many 64-bit
- machines. ACE_UINT32 is always 4 bytes, and ACE_UINT64 is
- always 8 bytes.<p>
-
- <li>If a class has any virtual functions, and its destructor is
- declared explicitly in the class, then the destructor should
- <strong>always</strong> be virtual as well. And to support
- compiler activities such as generation of virtual tables and,
- in some cases, template instantiation, the virtual destructor
- should <strong>not be inline</strong>. (Actually, any non-pure
- virtual function could be made non-inline for this purpose. But,
- for convenience, if its performance is not critical, it is usually
- easiest just to make the virtual destructor non-inline.)<p>
-
-
- <li><a name="ACE_Time_Value example">Avoid default arguments</a>
- unless there's a good reason. For an example of how they got
- us into a jam is:
- <pre>
- ACE_Time_Value (long sec, long usec = 0);
- </pre>
-
- So, <code>ACE_Time_Value (2.5)</code> has the unfortunate
- effect of coercing the 2.5 to a long with value 2. That's
- probably not what the programmer intended, and many compilers
- don't warn about it.<p>
-
- A nice fix would be to add an <code>ACE_Time_Value (double)</code>
- constructor. But, that would cause ambiguous overloading
- due to the default value for the second argument of
- <code>ACE_Time_Value (long sec, long usec = 0)</code>.
- We're stuck with <code>ACE_Time_Value</code>, but now we
- know that it's easy to avoid.<p>
-
- <li>Constructor initializers must appear in the same order as
- the data members are declared in the class header. This avoids
- subtle errors, because initialization takes place in the order
- of member declaration.<p>
-
- <li>Initialization is usually cleaner than assignment, especially
- in a conditional. So, instead of writing code like this:
-
- <pre>
- ssize_t n_bytes;
-
- // Send multicast of one byte, enough to wake up server.
- if ((n_bytes = multicast.send ((char *) &reply_port,
- sizeof reply_port)) == -1)
- </pre>
-
- Write it like this:
-
- <pre>
- ssize_t n_bytes = multicast.send ((char *) &reply_port,
- sizeof reply_port)
-
- // Send multicast of one byte, enough to wake up server.
- if (n_bytes == -1)
- </pre><p>
-
- But, beware if the initialization is of a static variable.
- A static variable is only initialized the first time its
- declaration is seen. Of course, we should avoid using
- static variables at all.<p>
-
- <li>It is usually clearer to write conditionals that have
- both branches without a negated condition. For example,<p>
-
- <pre>
- if (test)
- {
- // true branch
- }
- else
- {
- // false branch
- }
- </pre><p>
-
- is preferred over:<p>
-
- <pre>
- if (! test)
- {
- // false test branch
- }
- else
- {
- // true test branch
- }
- </pre><p>
-
- <li>If a cast is necessary, avoid use of function-style casts,
- <em>e.g.</em>, <code>int (foo)</code>. Instead, use
- one of the ACE cast macros:
-
- <pre>
- return ACE_static_cast(size_t, this-&gt;count_) &gt; that-&gt;size_;
- </pre><p>
-
- The general usage guidelines for the four styles of casts are:<p>
- <ul>
- <li><strong>ACE_const_cast</strong>: use to cast away
- constness, or volatile-ness.<p>
- <li><strong>ACE_static_cast</strong>: use to cast between
- compatible types, such as downcasting a pointer or narrowing
- an integer.<p>
- <li><strong>ACE_reinterpret_cast</strong>: use only when
- ACE_static_cast is not suitable.<p>
- <li><strong>ACE_dynamic_cast</strong>: avoid, unless you really
- want to type check at run-time.<p>
- </ul>
-
- <li>In general, if instances of a class should not be copied,
- then a private copy constructor and assignment operator should
- be declared for the class, but not implemented. For example:
-
- <pre>
- // Disallow copying by not implementing the following . . .
- ACE_Object_Manager (const ACE_Object_Manager &);
- ACE_Object_Manager &operator= (const ACE_Object_Manager &);
- </pre><p>
-
- If the class is a template class, then the
- <code>ACE_UNIMPLEMENTED_FUNC</code> macro should be used:
-
- <pre>
- // = Disallow copying...
- ACE_UNIMPLEMENTED_FUNC (ACE_TSS (const ACE_TSS&lt;TYPE&gt; &))
- ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_TSS&lt;TYPE&gt; &))
- </pre><p>
-
- <code>ACE_UNIMPLEMENTED_FUNC</code> can be used with non-template
- classes as well. Though for consistency and maximum safety, it
- should be avoided for non-template classes.<p>
-
- <li>Never use <code>bool</code>, <code>BOOL</code>, or similar
- types. (CORBA::Boolean is acceptable). Use <code>int</code>
- or <code>u_int</code> instead for boolean types.<p>
-
- <li>Functions should always return -1 to indicate failure, and
- 0 or greater to indicate success.<p>
-
- <li>Separate the code of your templates from the code for
- non-parametric classes: some compilers get confused when
- template and non-template code is mixed in the same file.<p>
-
- <li>It's a good idea to specify the include path (with <code>-I</code>)
- to include any directory which contains files with template
- definitions. The Compaq Tru64 cxx <code>-ptv</code> compiler option
- may help diagnose missing template instantiation problems.<p>
-
- <li>When referring to member variables and functions, use
- <code>this-&gt;</code><em>member</em>. This makes it clear to the
- reader that a class member is being used. It also makes it crystal
- clear to the compiler which variable/function you mean in cases
- where it might make a difference.
- </ul>
-
- <li><strong>I/O</strong><p>
- <ul>
- <li>Use <strong><code>ACE_DEBUG</code></strong> for printouts,
- and <strong><code>ACE_OS::fprintf ()</code></strong> for
- file I/O. Avoid using iostreams because of implementation
- differences across platforms.<p>
- <li>After attempting to open an existing file, always check for success.
- Take appropriate action if the open failed.<p>
- <li>Notice that <strong><code>ACE_DEBUG</code></strong> and
- <strong><code>ACE_ERROR</code></strong> don't support
- <code>%ld</code> of any other multicharacter format.<p>
- </ul>
-
- <li><strong>WCHAR conformity</strong><p>
-
- <ul>
- <li>For ACE, use ACE_TCHAR instead of char for strings and ACE_TEXT ()
- around string literals. Exceptions are char arrays used for data
- and strings that need to remain as 1 byte characters.
-
- <li>If you have a char string that needs to be converted to ACE_TCHAR,
- use the ACE_TEXT_CHAR_TO_TCHAR () macro. If you have a ACE_TCHAR
- string that needs to be converted to a char string, use the
- ACE_TEXT_ALWAYS_CHAR () macro
-
- <li>Do not use the Win32 TCHAR macros. The wide character-ness of ACE
- is separate from UNICODE and _UNICODE.
-
- <li>For TAO, don't use ACE_TCHAR or ACE_TEXT. The CORBA specification
- defines APIs as using char. So most of the time there is no need
- to use wide characters.
- </ul><P>
-
- <li><strong>Exceptions</strong><p>
-
- <ul>
- <li>There are many ways of throwing and catching exceptions. The
- code below gives several examples. Note that each method has
- different semantics and costs. Whenever possible, use the
- first approach.<p>
-
- <pre>
- #include "iostream.h"
-
- class exe_foo
- {
- public:
- exe_foo (int data) : data_ (data)
- { cerr &lt;&lt; "constructor of exception called" &lt;&lt; endl; }
- ~exe_foo ()
- { cerr &lt;&lt; "destructor of exception called" &lt;&lt; endl; }
- exe_foo (const exe_foo& foo) : data_ (foo.data_)
- { cerr &lt;&lt; "copy constructor of exception called"
- &lt;&lt; endl; }
- int data_;
- };
-
-
- void
- good (int a)
- {
- throw exe_foo (a);
- };
-
- void
- bad (int a)
- {
- exe_foo foo (a);
- throw foo;
- };
-
- int main ()
- {
- cout &lt;&lt; endl &lt;&lt; "First exception" &lt;&lt; endl
- &lt;&lt; endl;
- try
- {
- good (0);
- }
- catch (exe_foo &foo)
- {
- cerr &lt;&lt; "exception caught: " &lt;&lt; foo.data_
- &lt;&lt; endl;
- }
-
- cout &lt;&lt; endl &lt;&lt; "Second exception" &lt;&lt; endl
- &lt;&lt; endl;
- try
- {
- good (0);
- }
- catch (exe_foo foo)
- {
- cerr &lt;&lt; "exception caught: " &lt;&lt; foo.data_
- &lt;&lt; endl;
- }
-
- cout &lt;&lt; endl &lt;&lt; "Third exception" &lt;&lt; endl
- &lt;&lt; endl;
- try
- {
- bad (1);
- }
- catch (exe_foo &foo)
- {
- cerr &lt;&lt; "exception caught: " &lt;&lt; foo.data_
- &lt;&lt; endl;
- }
-
- cout &lt;&lt; endl &lt;&lt; "Fourth exception" &lt;&lt; endl
- &lt;&lt; endl;
- try
- {
- bad (1);
- }
- catch (exe_foo foo)
- {
- cerr &lt;&lt; "exception caught: " &lt;&lt; foo.data_
- &lt;&lt; endl;
- }
-
- return 0;
- }
- </pre>
-
- Output is: <p>
-
- <pre>
- First exception
-
- constructor of exception called
- exception caught: 0
- destructor of exception called
-
- Second exception
-
- constructor of exception called
- copy constructor of exception called
- exception caught: 0
- destructor of exception called
- destructor of exception called
-
- Third exception
-
- constructor of exception called
- copy constructor of exception called
- destructor of exception called
- exception caught: 1
- destructor of exception called
-
- Fourth exception
-
- constructor of exception called
- copy constructor of exception called
- destructor of exception called
- copy constructor of exception called
- exception caught: 1
- destructor of exception called
- destructor of exception called
-
- </pre>
-
- </ul><p>
-
- <li><strong>Compilation</strong><p>
- <ul>
- <li>Whenever you add a new test or example to ACE or TAO, make
- sure that you modify the Makefile or project file in the
- parent directory. This will make sure that your code gets
- compiled on a regular basis. In some cases, this also applies
- to MSVC project files.<p>
- </ul><p>
-</ul>
-
-
-<hr>
-<h3><a href="http://www.cs.wustl.edu/~schmidt/ACE-overview.html">ACE</a>
- Usage Guidelines</h3>
-<ul>
- <li>Always use <strong><code>ACE_OS</code></strong> (static)
- member functions instead of bare OS system calls.<p>
-
- <li>As a general rule, the only functions that should go into the
- <strong><code>ACE_OS</code></strong> class are ones that have
- direct equivalents on some OS platform. Functions that are
- extensions should go in the <strong><code>ACE</code></strong> class.<p>
-
- <li>Use the <strong><code>ACE_SYNCH_MUTEX</code></strong> macro,
- instead of using one of the specific mutexes, such as
- <strong><code>ACE_Thread_Mutex</code></strong>. This provides
- portability between threaded and non-threaded platforms.<p>
-
- <li>Avoid creating a static instance of user-defined (class) type.
- Instead, either create it as an
- <strong><code>ACE_Singleton</code></strong>,
- <strong><code>ACE_TSS_Singleton</code></strong>, or as an
- <strong><code>ACE_Cleanup</code></strong> object. See the
- <strong>ACE</strong>
- <a href="../ace/Singleton.h"><code>Singleton.h</code></a>,
- <a href="../ace/Object_Manager.h"><code>Object_Manager.h</code></a>, and
- <a href="../ace/Managed_Object.h"><code>Managed_Object.h</code></a>
- header files for more information.<p>
-
- Static instances of built-in types, such as
- <strong><code>int</code></strong> or any pointer type, are fine.<p>
-
- Construction of static instance of a user-defined type should
- <em>never</em> spawn threads. Because order of construction of
- statics across files is not defined by the language, it is usually
- assumed that only one thread exists during static construction.
- This allows statics suchs as locks to be safely created. We do not
- want to violate this assumption.<p>
-
- <li>Do not use run-time type identification (RTTI) directly since some platforms
- do not support it. Instead, use the ACE macros, e.g.,
- <CODE>ACE_static_cast()</CODE>, <CODE>ACE_dynamic_cast()</CODE>, etc.<p>
-
- <li>Do not use C++ exception handling directly. Some platforms do
- not support it. And, it can impose an execution speed penalty.
- Instead use the TAO/ACE try/catch macros.<p>
-
- <li>Because ACE does not use exception handling, dealing with
- failures requires a bit of care. This is especially true
- in constructors. Consider the following approach:
-
- <pre>
- ACE_NEW_RETURN (this-&gt;name_space_, LOCAL_NAME_SPACE, -1);
-
- if (ACE_LOG_MSG-&gt;op_status () != 0)
- ....
- </pre>
-
- This snip of code is from
- <a href="../ace/Naming_Context.cpp"><code>ACE_Naming_Context</code></a>.
- All failed constructors in ACE (should) call ACE_ERROR. This sets
- the thread-specific <strong>op_status</strong>, which can be checked
- by the caller. This mechanism allows the caller to check for a failed
- constructor without the requiring the constructor to throw
- exceptions.<p>
-
- <LI>Another consequence of ACE's avoidance of exception handling is
- that you should use <CODE>open()</CODE> methods on classes that
- perform initializations that can fail. This is because <CODE>open()</CODE>
- returns an error code that's easily checked by the caller,
- rather than relying on constructor and thread-specific status
- values. <P>
-
- <li>Avoid using the C++ Standard Template Library (STL) in our
- applications. Some platforms do not support it yet.<p>
-
- <li>Be <em>very</em> careful with <code>ACE_ASSERT</code>. It
- must only be used to check values; it may never be used to
- wrap a function call, or contain any other side effect. That's
- because the statement will disappear when ACE_NDEBUG is enabled.
- For example, this code is BAD:
- <pre>
- ACE_ASSERT (this-&gt;next (retv) != 0); // BAD CODE!
- </pre>
-
- Instead, the above should be coded this way:
-
- <pre>
- int result = this-&gt;next (retv);
- ACE_ASSERT (result != 0);
- ACE_UNUSED_ARG (result);
- </pre><p>
-
- <li>Never put side effects in <code>ACE_DEBUG</code> code:
- <pre>
- ACE_DEBUG ((LM_DEBUG,
- "handling signal: %d iterations left\n",
- --this-&gt;iterations_)); // BAD CODE!
- </pre>
-
- Note that this won't work correctly if <code>ACE_NDEBUG</code> is
- defined, for the same reason that having side-effects in
- <code>ACE_ASSERT</code>s won't work either, <em>i.e.</em>, because
- the code is removed.<p>
-
- <li>Be <strong>very</strong> careful with the code that you put
- in a signal handler. On Solaris, the man pages document systems
- calls as being Async-Signal-Safe if they can be called from signal
- handlers. In general, it's best to just set a flag in a signal
- handler and take appropriate action elsewhere. It's also best
- to avoid using signals, especially asynchronous signals.<p>
-
- <li>Immediately after opening a temporary file, unlink it. For
- example:
- <pre><code>
- ACE_HANDLE h = open the file (filename);
-
- ACE_OS::unlink (filename);
- </code></pre><p>
-
- This avoids leaving the temporary file even if the program crashes.<p>
-
- <li>Always use <code>$(RM)</code> instead of <code>rm</code> or
- <code>rm -f</code> in Makefiles.<p>
-
- <li>Be sure to specify the <code>THR_BOUND</code> thread creation
- flag for time-critical threads. This ensures that the thread competes
- for resources globally on Solaris. It is harmless on other platforms.<p>
-</ul>
-
-
-<hr>
-<h3><a href="http://www.cs.wustl.edu/~schmidt/ACE-overview.html">Other
- ACE</a> and
- <a href="http://www.cs.wustl.edu/~schmidt/TAO-overview.html">TAO</a>
- Guidelines</h3>
-<ul>
- <li>When enhancing, updating, or fixing ACE or TAO, always:<p>
- <ol>
- <li>Test your change on at least one platform. All changes
- <strong>must</strong> be tested with egcs before commiting.
- That means you may need to test on at least two platforms.<p>
- <li>An an entry to the appropriate ChangeLog. TAO and some
- ACE subdirectories, such as <a href="../ASNMP">ASNMP</a>,
- <a href="../apps/JAWS">JAWS</a>, and
- <a href="../apps/gperf">gperf,</a> have their
- own ChangeLogs. If you don't use one of those, use the
- <a href="../ChangeLog">ChangeLog</a> in the top-level
- <a href="..">ACE_wrappers</a> directory.<p>
- <li>Commit your change using a message of this form:<p>
-<code>
-ChangeLogTag: Thu Jul 22 09:55:10 1999 David L. Levine
- &lt;levine@cs.wustl.edu&gt;
-</code><p>
- <li>If the change is in response to a request by someone else:
- <ol>
- <li>Make sure that person is acknowledged in
- <a href="../THANKS">ACE_wrappers/THANKS</a>, and<p>
- <li>Respond to that person.<p>
- </ol>
- </ol>
-
- <li>Never add copyrighted, confidential, or otherwise restricted
- code to the ACE or TAO distributions without written permission
- from the owner.<p>
-</ul>
-
-
-<hr>
-<h3><a href="http://www.cs.wustl.edu/~levine/CVS.html">CVS</a>
- Usage Guidelines</h3>
-<ul>
- <li>Always make sure that a change builds and executes correctly
- on at least one platform before checking it into the CVS repository.
- All changes <strong>must</strong> be tested with egcs before commiting.
- That means you may need to test on at least two platforms.<p>
-</ul>
-
-
-<hr>
-<h3>Script Guidelines</h3>
-<ul>
- <li>In general, it's best to write scripts in Perl. It's
- OK to use Bourne shell. Never, never, never use csh, ksh,
- bash, or any other kind of shell.<p>
-
- <li>Follow the Perl style guide guide as closely as
- possible. <code>man perlstyle</code> to view it.
-
- <li>Don't specify a hard-coded path to Perl itself. Use
- the following code at the top of the script to pick up
- perl from the users <code>PATH</code>:<br>
- <pre>
-eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
- & eval 'exec perl -S $0 $argv:q'
- if 0;
- </pre><p>
-
- <li>Never, never, never start the first line of a script
- with ``#'', unless the first line is ``#! /bin/sh''.
- With just ``#'', t/csh users will spawn a new shell.
- That will cause their <code>.[t]cshrc</code> to be
- processed, possibly clobbering a necessary part of
- their environment.<p>
-
- <li>If your Perl script relies on features only available
- in newer versions of Perl, include the a statement similar
- to the following:<br>
- <pre>
- require 5.003;
- </pre>
-
- <li>Don't depend on <strong><code>.</code></strong> being
- in the user's path. If the script spawns another executable
- that is supposed to be in the current directory, be sure the
- prefix its filename with <strong><code>.</code></strong>.<p>
-</ul>
-
-
-<hr>
-<h3>Software Engineering Guidelines</h3>
-<ul>
- <li><strong>Advise</strong>: Keep other developers informed of problems
- and progress.<p>
-
- <li><strong>Authorize</strong>: We have contractual obligations to not
- unilaterally change interfaces. If you need to change or remove an
- interface, get an OK.<p>
-
- <li><strong>Minimize</strong> risk: Test all changes. Solicit review of
- changes.<p>
-
- <li><strong>Revise</strong> only when necessary: Every change has risk,
- so avoid making any change unless there is a good reason for it.<p>
-
- <li><strong>Normalize</strong>: Factor out commonality. For example,
- maintain a data value in only one place.<p>
-
- <li><strong>Synthesize</strong>: Build stubs and scaffolding early to
- simulate the complete system. Maintain a checked-in version of the
- system that cleanly builds and tests at all times.<p>
-
- <li><strong>Be available</strong>: Breaking compilation in one
- platform or another should be avoided (see above),
- but it is bound to happen when so many platforms are in use.
- Be available after making a change,
- if you won't be available for at least 48 hours after the change
- is made then don't make it!<p>
-</ul>
-
-
-<hr>
-<h3><a href="http://www.cs.wustl.edu/~doc/PACE/">PACE</a>
- Software Development Guidelines</h3>
-
-PACE code should be developed following the ACE guidelines
-above, with these exceptions:
-<ul>
- <li>An <code>if</code> statement that has just one statement must
- be written with the braces:
-
-<pre>
-if (condition)
- {
- statement;
- }
-</pre>
-
-This avoids bugs caused by subsequent insertion of code:
-
-<pre>
- if (condition)
- ACE_OS::fprintf (stderr, "I need to see what's going on here\n");
- statement; /* Ooops! This statement will always be executed!!!! */
-</pre>
-</ul>
-
-
-<hr>
-<h3><a href="http://www.cs.wustl.edu/~schmidt/rules.html">ACE
- Design Rules</a></h3>
-
-
-<hr><p>
- <font size=-1>
- Last modified <!--#echo var="LAST_MODIFIED" -->.<p>
- </font>
-
-Back to <A HREF="index.html">ACE Documentation Home</A>.
-
-</body>
-</html>