(setq-default indent-tabs-mode nil)Microsoft Visual C++ users should do the following:
Choose: Tools -- Options -- Tabs Then Set: "Tab size" to 8 and "Indent size" to 2, and indent using spaces.
-?
command line argument, are
provided to the program.
main
function must
always be declared with arguments, e.g.,
int main (int argc, char *argv[]) { [...] return 0; }
If you don't use the argc
and/or argv
arguments, don't declare them, e.g.,
int main (int, char *[]) { [...] return 0; }
Please declare the second argument as char *[]
instead of char **
. Ancient versions of MSC
complained about char **
; I've never seen a
C++ compiler complain about char *[]
.
main
must also return 0 on successful
termination, and non-zero otherwise.
// $Id$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.
To insert that string at the top of a file:
perl -pi -e \ 'if (! $o) {printf "// \$Id\$\n\n";}; $o = 1;' file
#endif
with a /* */
C-style comment. It
should correspond to the condition in the matching
#if
directive. For example,
#if defined (ACE_HAS_THREADS) # if defined (ACE_HAS_STHREADS) # include /**/ <synch.h> # include /**/ <thread.h> # 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 */
char * /* foo */
instead of
char */*foo*/
. MS VC++
complains otherwise.
/**/
between an
#include
and
filename
, as shown in the above
example. This avoids dependency problems with Visual C++.
ACE_
or TAO_
. There are too many system headers out
there that #define OK
, SUCCESS
,
ERROR
, index
, and so on.
#ifdefs
with typedefs
and #defines
. For example, use this:
#if defined(ACE_PSOS) typedef long ACE_NETIF_TYPE; # define ACE_DEFAULT_NETIF 0 #else /* ! ACE_PSOS */ typedef const ASYS_TCHAR* ACE_NETIF_TYPE; # define ACE_DEFAULT_NETIF ASYS_TEXT("le0") #endif /* ! ACE_PSOS */
instead of:
#if defined (ACE_PSOS) // pSOS supports numbers, not names for network interfaces long net_if, #else /* ! ACE_PSOS */ const ASYS_TCHAR *net_if, #endif /* ! ACE_PSOS */
#ifndef FOO_H #define FOO_H [contents of header file] #endif /* FOO_H */
This exact construct (note the #ifndef
)
is optimized by many compilers such they only open the
file once per compilation unit. Thanks to Eric C. Newton
<ecn@smart.net> for pointing that out.
If the header #includes
an ACE library header,
then it's a good idea to include the #pragma once
directive:
#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 */
#pragma once
must be protected, because some
compilers complain about it. The protection depends on
ACE_LACKS_PRAGMA_ONCE
, which is defined in
some ACE config headers. Therefore, the protected
#pragma once
construct should only be used after
an #include
of an ACE library header. Note that
many compilers enable the optimization if the #ifndef
protection construct is used, so for them, #pragma once
is superfluous.
No code can appear after the final
#endif
for the optimization to be effective and
correct.
Files that contain parametric classes should follow this style:
#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 */
Notice that some compilers need to see the code of the template,
hence the .cpp
file must be included from the
header file.
To avoid multiple inclusions of the .cpp
file it
should also be protected as in:
#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/Active_Map_Manager_T.i" #endif /* __ACE_INLINE__ */ ACE_RCSID(lib, Foo_T, "$Id$") // put your template code here #endif /* FOO_T_H */
Finally you may want to include the template header file from a
non-template header file (check
$ACE_ROOT/ace/Synch.h
); in such a case the template
header should be included after the inline
function definitions, as in:
#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 */
for
loops should look like:
for (size_t i = 0; i < Options::instance ()->spawn_count (); ++i) spawn ();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:
for (size_t i = 0; i < Options::instance ()->spawn_count (); ++i) { ACE_ASSERT (spawn () == 0;) }
Similarly, if
statements should have
a space after the ``if'', and no spaces just after
the opening parenthesis and just before the closing parenthesis.
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';
Therefore, use this idiom for iterators, with prefix operator on the loop index:
ACE_Ordered_MultiSet<int> set; ACE_Ordered_MultiSet_Iterator<int> iter(set); for (i = -10; i < 10; ++i) set.insert (2 * i + 1);rather than the postfix operator:
for (i = -10; i < 10; i++) set.insert (2 * i + 1);
.i
file. That file is conditionally included by both the
.h
file, for example:
class ACE_Export ACE_High_Res_Timer { [...] }; #if defined (__ACE_INLINE__) #include "ace/High_Res_Timer.i" #endif /* __ACE_INLINE__ */
and .cpp
file:
#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)
NOTE: 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 g++
with the
-Wall
option, will issue warnings for violations.
ACE_Export
must be inserted between the
class
keyword and class name for all classes that
are exported from libraries, as shown in the example above.
However, do not use
ACE_Export
for template classes!
void object_addr (const ACE_INET_Addr &); // Sets <object_addr_> cache from <host> and <port>. ACE_INET_Addr &object_addr (void); // Returns the <ACE_INET_Addr> for this profile.
instead of the ``set_'' and ``get_'' form.
delete
to deallocate
memory that was allocated with malloc
.
Similarly, never associate free
with
new
.
ACE_NEW
or
ACE_NEW_RETURN
should be used to
allocate memory, and delete
should
be used to deallocate it. And be careful to use the correct form,
delete
or
delete []
to correspond to the
allocation.
ACE_NEW
or
ACE_NEW_RETURN
to allocate memory,
because they check for successful allocation and set errno
appropriately if it fails.
int
.
On all currently supported ACE platforms, it is safe to cast
a pointer to or from a long
.
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)Write it like this:
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)
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.
if (test) { // true branch } else { // false branch }
is preferred over:
if (! test) { // false test branch } else { // true test branch }
int (foo)
. Instead, use
one of the ACE cast macros:
return ACE_static_cast(size_t, this->count_) > that->size_;
The general usage guidelines for the four styles of casts are:
// Disallow copying by not implementing the following . . . ACE_Object_Manager (const ACE_Object_Manager &); ACE_Object_Manager &operator= (const ACE_Object_Manager &);
If the class is a template class, then the
ACE_UNIMPLEMENTED_FUNC
macro should be used:
// = Disallow copying... ACE_UNIMPLEMENTED_FUNC (ACE_TSS (const ACE_TSS<TYPE> &)) ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_TSS<TYPE> &))
ACE_UNIMPLEMENTED_FUNC
can be used with non-template
classes as well. Though for consistency and maximum safety, it
should be avoided for non-template classes.
bool
, BOOL
, or similar
types. (CORBA::Boolean is acceptable). Use int
or u_int
instead for boolean types.
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.
ACE_DEBUG
for printouts,
and ACE_OS::scanf/fprintf ()
for
file I/O. Avoid using iostreams because of implementation
differences across platforms.
ASYS_TCHAR
if
they need to be passed into system API. It expands to
wchar_t
only when
ACE_HAS_MOSTLY_UNICODE_APIS
is defined.
ASYS_TEXT
and
ASYS_WIDE_STRING
for format
strings and other string arguments passed to
ACE_DEBUG
or ACE_ERROR
. For
example,
void ACE_FOO::ace_bar (int err, ASYS_TCHAR *astr) { ACE_TRACE ("ACE_FOO::ace_bar"); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("From ACE_FOO::ace_bar"))); if (err) ACE_ERROR ((LM_ERROR, ASYS_TEXT ("(%P) Printing this string %s\n"), astr)); }
This is because ACE also support platforms which use UNICODE in most of their APIs. On these platforms, ACE also uses UNICODE as its system string type.
ACE_TRACE
handles conversion
between char strings and UNICODE strings automatically.
ASYS_MULTIBYTE_STRING
and
ASYS_ONLY_MULTIBYTE_STRING
. See
the end of OS.h for more details.
#include "iostream.h" class exe_foo { public: exe_foo (int data) : data_ (data) { cerr << "constructor of exception called" << endl; } ~exe_foo () { cerr << "destructor of exception called" << endl; } exe_foo (const exe_foo& foo) : data_ (foo.data_) { cerr << "copy constructor of exception called" << endl; } int data_; }; void good (int a) { throw exe_foo (a); }; void bad (int a) { exe_foo foo (a); throw foo; }; int main () { cout << endl << "First exception" << endl << endl; try { good (0); } catch (exe_foo &foo) { cerr << "exception caught: " << foo.data_ << endl; } cout << endl << "Second exception" << endl << endl; try { good (0); } catch (exe_foo foo) { cerr << "exception caught: " << foo.data_ << endl; } cout << endl << "Third exception" << endl << endl; try { bad (1); } catch (exe_foo &foo) { cerr << "exception caught: " << foo.data_ << endl; } cout << endl << "Fourth exception" << endl << endl; try { bad (1); } catch (exe_foo foo) { cerr << "exception caught: " << foo.data_ << endl; } return 0; }Output is:
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
ACE_OS
(static)
member functions instead of bare OS system calls.
ACE_OS
class are ones that have
direct equivalents on some OS platform. Functions that are
extensions should go in the ACE
class.
ACE_SYNCH_MUTEX
macro,
instead of using one of the specific mutexes, such as
ACE_Thread_Mutex
. This provides
portability between threaded and non-threaded platforms.
ACE_Singleton
,
ACE_TSS_Singleton
, or as an
ACE_Cleanup
object. See the
ACE
Singleton.h
,
Object_Manager.h
, and
Managed_Object.h
header files for more information.
Static instances of built-in types, such as
int
or any pointer type, are fine.
Construction of static instance of a user-defined type should never 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.
ACE_NEW_RETURN (this->name_space_, LOCAL_NAME_SPACE, -1); if (ACE_LOG_MSG->op_status () != 0) ....This snip of code is from
ACE_Naming_Context
.
All failed constructors in ACE (should) call ACE_ERROR. This sets
the thread specific op_status, 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.
ACE_ASSERT
. 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:
ACE_ASSERT (this->next (retv) != 0); // BAD CODE!Instead, the above should be coded this way:
int result = this->next (retv); ACE_ASSERT (result != 0); ACE_UNUSED_ARG (result);
ACE_DEBUG
code:
ACE_DEBUG ((LM_DEBUG, "handling signal: %d iterations left\n", --this->iterations_)); // BAD CODE!Note that this won't work correctly if
ACE_NDEBUG
is
defined, for the same reason that having side-effects in
ACE_ASSERT
s won't work either, i.e., because
the code is removed.
ACE_HANDLE h = open the file (filename);
ACE_OS::unlink (filename);
This avoids leaving the temporary file even if the program crashes.
$(RM)
instead of rm
or
rm -f
in Makefiles.
man perlstyle
to view it.
PATH
:eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' & eval 'exec perl -S $0 $argv:q' if 0;
.[t]cshrc
to be
processed, possibly clobbering a necessary part of
their environment.
require 5.003;
.
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 .
.
Last modified .