From f59c183b282a3ca8e04f1bc32b7f0d8e8493282b Mon Sep 17 00:00:00 2001 From: storri Date: Wed, 9 Jan 2002 20:11:32 +0000 Subject: libACE_OS Initial Entry --- ace/OS/Base_Thread_Adapter.cpp | 125 + ace/OS/Base_Thread_Adapter.h | 167 + ace/OS/Base_Thread_Adapter.inl | 34 + ace/OS/Basic_Types.cpp | 130 + ace/OS/Basic_Types.h | 610 ++ ace/OS/Basic_Types.i | 477 ++ ace/OS/Date_Time.cpp | 10 + ace/OS/Date_Time.h | 105 + ace/OS/Date_Time.i | 162 + ace/OS/Global_Macros.h | 115 + ace/OS/Handle_Gobbler.h | 66 + ace/OS/Handle_Gobbler.i | 88 + ace/OS/Handle_Ops.cpp | 41 + ace/OS/Handle_Ops.h | 43 + ace/OS/Handle_Ops.i | 1 + ace/OS/Handle_Set.cpp | 558 ++ ace/OS/Handle_Set.h | 229 + ace/OS/Handle_Set.i | 176 + ace/OS/Init_ACE.cpp | 44 + ace/OS/Init_ACE.h | 65 + ace/OS/Init_ACE.i | 1 + ace/OS/Makefile | 69 + ace/OS/OS.cpp | 7972 +++++++++++++++++++++++++ ace/OS/OS.h | 7529 ++++++++++++++++++++++++ ace/OS/OS.i | 11666 +++++++++++++++++++++++++++++++++++++ ace/OS/OS_Dirent.cpp | 235 + ace/OS/OS_Dirent.h | 130 + ace/OS/OS_Dirent.inl | 201 + ace/OS/OS_Errno.cpp | 33 + ace/OS/OS_Errno.h | 143 + ace/OS/OS_Errno.inl | 87 + ace/OS/OS_Export.h | 46 + ace/OS/OS_Log_Msg_Attributes.cpp | 9 + ace/OS/OS_Log_Msg_Attributes.h | 89 + ace/OS/OS_Log_Msg_Attributes.inl | 6 + ace/OS/OS_Memory.cpp | 13 + ace/OS/OS_Memory.h | 123 + ace/OS/OS_Memory.inl | 50 + ace/OS/OS_QoS.cpp | 471 ++ ace/OS/OS_QoS.h | 386 ++ ace/OS/OS_String.cpp | 1023 ++++ ace/OS/OS_String.h | 596 ++ ace/OS/OS_String.inl | 731 +++ ace/OS/OS_TLI.cpp | 13 + ace/OS/OS_TLI.h | 195 + ace/OS/OS_TLI.inl | 343 ++ ace/OS/OS_Thread_Adapter.cpp | 178 + ace/OS/OS_Thread_Adapter.h | 78 + ace/OS/OS_Thread_Adapter.inl | 1 + ace/OS/Sched_Params.cpp | 321 + ace/OS/Sched_Params.h | 225 + ace/OS/Sched_Params.i | 136 + ace/OS/Thread_Hook.cpp | 25 + ace/OS/Thread_Hook.h | 56 + ace/OS/gethrtime.cpp | 58 + 55 files changed, 36484 insertions(+) create mode 100644 ace/OS/Base_Thread_Adapter.cpp create mode 100644 ace/OS/Base_Thread_Adapter.h create mode 100644 ace/OS/Base_Thread_Adapter.inl create mode 100644 ace/OS/Basic_Types.cpp create mode 100644 ace/OS/Basic_Types.h create mode 100644 ace/OS/Basic_Types.i create mode 100644 ace/OS/Date_Time.cpp create mode 100644 ace/OS/Date_Time.h create mode 100644 ace/OS/Date_Time.i create mode 100644 ace/OS/Global_Macros.h create mode 100644 ace/OS/Handle_Gobbler.h create mode 100644 ace/OS/Handle_Gobbler.i create mode 100644 ace/OS/Handle_Ops.cpp create mode 100644 ace/OS/Handle_Ops.h create mode 100644 ace/OS/Handle_Ops.i create mode 100644 ace/OS/Handle_Set.cpp create mode 100644 ace/OS/Handle_Set.h create mode 100644 ace/OS/Handle_Set.i create mode 100644 ace/OS/Init_ACE.cpp create mode 100644 ace/OS/Init_ACE.h create mode 100644 ace/OS/Init_ACE.i create mode 100644 ace/OS/Makefile create mode 100644 ace/OS/OS.cpp create mode 100644 ace/OS/OS.h create mode 100644 ace/OS/OS.i create mode 100644 ace/OS/OS_Dirent.cpp create mode 100644 ace/OS/OS_Dirent.h create mode 100644 ace/OS/OS_Dirent.inl create mode 100644 ace/OS/OS_Errno.cpp create mode 100644 ace/OS/OS_Errno.h create mode 100644 ace/OS/OS_Errno.inl create mode 100644 ace/OS/OS_Export.h create mode 100644 ace/OS/OS_Log_Msg_Attributes.cpp create mode 100644 ace/OS/OS_Log_Msg_Attributes.h create mode 100644 ace/OS/OS_Log_Msg_Attributes.inl create mode 100644 ace/OS/OS_Memory.cpp create mode 100644 ace/OS/OS_Memory.h create mode 100644 ace/OS/OS_Memory.inl create mode 100644 ace/OS/OS_QoS.cpp create mode 100644 ace/OS/OS_QoS.h create mode 100644 ace/OS/OS_String.cpp create mode 100644 ace/OS/OS_String.h create mode 100644 ace/OS/OS_String.inl create mode 100644 ace/OS/OS_TLI.cpp create mode 100644 ace/OS/OS_TLI.h create mode 100644 ace/OS/OS_TLI.inl create mode 100644 ace/OS/OS_Thread_Adapter.cpp create mode 100644 ace/OS/OS_Thread_Adapter.h create mode 100644 ace/OS/OS_Thread_Adapter.inl create mode 100644 ace/OS/Sched_Params.cpp create mode 100644 ace/OS/Sched_Params.h create mode 100644 ace/OS/Sched_Params.i create mode 100644 ace/OS/Thread_Hook.cpp create mode 100644 ace/OS/Thread_Hook.h create mode 100644 ace/OS/gethrtime.cpp diff --git a/ace/OS/Base_Thread_Adapter.cpp b/ace/OS/Base_Thread_Adapter.cpp new file mode 100644 index 00000000000..dbe48fe4eb0 --- /dev/null +++ b/ace/OS/Base_Thread_Adapter.cpp @@ -0,0 +1,125 @@ +// $Id$ + +#include "Base_Thread_Adapter.h" +#include "OS.h" + +ACE_RCSID(ace, Base_Thread_Adapter, "$Id$") + +#if !defined (ACE_HAS_INLINED_OSCALLS) +# include "Base_Thread_Adapter.inl" +#endif /* ACE_HAS_INLINED_OS_CALLS */ + +ACE_INIT_LOG_MSG_HOOK ACE_Base_Thread_Adapter::init_log_msg_hook_ = 0; +ACE_INHERIT_LOG_MSG_HOOK ACE_Base_Thread_Adapter::inherit_log_msg_hook_ = 0; +ACE_CLOSE_LOG_MSG_HOOK ACE_Base_Thread_Adapter::close_log_msg_hook_ = 0; +ACE_SYNC_LOG_MSG_HOOK ACE_Base_Thread_Adapter::sync_log_msg_hook_ = 0; +ACE_THR_DESC_LOG_MSG_HOOK ACE_Base_Thread_Adapter::thr_desc_log_msg_hook_ = 0; + +ACE_Base_Thread_Adapter::ACE_Base_Thread_Adapter ( + ACE_THR_FUNC user_func, + void *arg, + ACE_THR_C_FUNC entry_point, + ACE_OS_Thread_Descriptor *td +#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) + , ACE_SEH_EXCEPT_HANDLER selector + , ACE_SEH_EXCEPT_HANDLER handler +#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ + ) + : user_func_ (user_func) + , arg_ (arg) + , entry_point_ (entry_point) + , thr_desc_ (td) +{ + ACE_OS_TRACE ("ACE_Base_Thread_Adapter::ACE_Base_Thread_Adapter"); + + if (ACE_Base_Thread_Adapter::init_log_msg_hook_ != 0) + (*ACE_Base_Thread_Adapter::init_log_msg_hook_) ( + this->log_msg_attributes_ +# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) + , selector + , handler +# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ + ); +} + +ACE_Base_Thread_Adapter::~ACE_Base_Thread_Adapter (void) +{ +} + +void +ACE_Base_Thread_Adapter::inherit_log_msg (void) +{ + if (ACE_Base_Thread_Adapter::inherit_log_msg_hook_ != 0) + (*ACE_Base_Thread_Adapter::inherit_log_msg_hook_)( + this->thr_desc_, + this->log_msg_attributes_); +} + +void +ACE_Base_Thread_Adapter::close_log_msg (void) +{ + if (ACE_Base_Thread_Adapter::close_log_msg_hook_ != 0) + (*ACE_Base_Thread_Adapter::close_log_msg_hook_) (); +} + +void +ACE_Base_Thread_Adapter::sync_log_msg (const ACE_TCHAR *prg) +{ + if (ACE_Base_Thread_Adapter::sync_log_msg_hook_ != 0) + (*ACE_Base_Thread_Adapter::sync_log_msg_hook_) (prg); +} + +ACE_OS_Thread_Descriptor * +ACE_Base_Thread_Adapter::thr_desc_log_msg (void) +{ + if (ACE_Base_Thread_Adapter::thr_desc_log_msg_hook_ != 0) + return (*ACE_Base_Thread_Adapter::thr_desc_log_msg_hook_) (); + return 0; +} + +// Run the thread entry point for the . This must +// be an extern "C" to make certain compilers happy... + +#if defined (ACE_PSOS) +extern "C" void +ace_thread_adapter (unsigned long args) +{ + ACE_OS_TRACE ("ace_thread_adapter"); + +#if defined (ACE_HAS_TSS_EMULATION) + // As early as we can in the execution of the new thread, allocate + // its local TS storage. Allocate it on the stack, to save dynamic + // allocation/dealloction. + void *ts_storage[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX]; + ACE_TSS_Emulation::tss_open (ts_storage); +#endif /* ACE_HAS_TSS_EMULATION */ + + ACE_Base_Thread_Adapter *thread_args = + ACE_static_cast(ACE_Base_Thread_Adapter *, args); + + // Invoke the user-supplied function with the args. + thread_args->invoke (); +} +#else /* ! defined (ACE_PSOS) */ +extern "C" void * +ace_thread_adapter (void *args) +{ + ACE_OS_TRACE ("ace_thread_adapter"); + +#if defined (ACE_HAS_TSS_EMULATION) + // As early as we can in the execution of the new thread, allocate + // its local TS storage. Allocate it on the stack, to save dynamic + // allocation/dealloction. + void *ts_storage[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX]; + ACE_TSS_Emulation::tss_open (ts_storage); +#endif /* ACE_HAS_TSS_EMULATION */ + + ACE_Base_Thread_Adapter *thread_args = + ACE_static_cast (ACE_Base_Thread_Adapter *, args); + + // Invoke the user-supplied function with the args. + void *status = thread_args->invoke (); + + return status; +} +#endif /* ACE_PSOS */ diff --git a/ace/OS/Base_Thread_Adapter.h b/ace/OS/Base_Thread_Adapter.h new file mode 100644 index 00000000000..5993ebf418d --- /dev/null +++ b/ace/OS/Base_Thread_Adapter.h @@ -0,0 +1,167 @@ +//============================================================================= +/** + * @file Base_Thread_Adapter.h + * + * $Id$ + * + * @author Nanbor Wang + */ +//============================================================================= + +#ifndef ACE_BASE_THREAD_ADAPTER_H +#define ACE_BASE_THREAD_ADAPTER_H +#include "ace/pre.h" + +#include "OS_Log_Msg_Attributes.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "OS_Export.h" + +// Run the thread entry point for the . This must +// be an extern "C" to make certain compilers happy... +#if defined (ACE_PSOS) +extern "C" void ace_thread_adapter (unsigned long args); +#else /* ! defined (ACE_PSOS) */ +extern "C" ACE_OS_Export void *ace_thread_adapter (void *args); +#endif /* ACE_PSOS */ + +/** + * @class ACE_OS_Thread_Descriptor + * + * @brief Parent class of all ACE_Thread_Descriptor classes. + * = + * Container for ACE_Thread_Descriptor members that are + * used in ACE_OS. + */ +class ACE_OS_Export ACE_OS_Thread_Descriptor +{ +public: + /// Get the thread creation flags. + long flags (void) const; + +protected: + /// For use by ACE_Thread_Descriptor. + ACE_OS_Thread_Descriptor (long flags = 0); + + /** + * Keeps track of whether this thread was created "detached" or not. + * If a thread is *not* created detached then if someone calls + * , we need to join with that thread (and + * close down the handle). + */ + long flags_; +}; + +/** + * @class ACE_Base_Thread_Adapter + * + * @brief Base class for all the Thread_Adapters. + * + * Converts a C++ function into a function + * function that can be called from a thread creation routine + * (e.g., or <_beginthreadex>) that expects an + * extern "C" entry point. This class also makes it possible to + * transparently provide hooks to register a thread with an + * . + * This class is used in . In general, the + * thread that creates an object of this class is different from + * the thread that calls on this object. Therefore, + * the method is responsible for deleting itself. + */ +class ACE_OS_Export ACE_Base_Thread_Adapter +{ +public: + ACE_Base_Thread_Adapter (ACE_THR_FUNC user_func, + void *arg, + ACE_THR_C_FUNC entry_point = (ACE_THR_C_FUNC) ace_thread_adapter, + ACE_OS_Thread_Descriptor *td = 0 +# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) + , ACE_SEH_EXCEPT_HANDLER selector = 0 + , ACE_SEH_EXCEPT_HANDLER handler = 0 +# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ + /// Constructor. + ); + + /// Virtual method invoked by the thread entry point. + virtual void *invoke (void) = 0; + + /// Accessor for the C entry point function to the OS thread creation + /// routine. + ACE_THR_C_FUNC entry_point (void); + + /// Invoke the close_log_msg_hook, if it is present + static void close_log_msg (void); + + /// Invoke the sync_log_msg_hook, if it is present + static void sync_log_msg (const ACE_TCHAR *prog_name); + + /// Invoke the thr_desc_log_msg_hook, if it is present + static ACE_OS_Thread_Descriptor *thr_desc_log_msg (void); + +protected: + /// Destructor, making it private ensures that objects of this class + /// are allocated on the heap. + virtual ~ACE_Base_Thread_Adapter (void); + + /// Inherit the logging features if the parent thread has an + /// . + void inherit_log_msg (void); + +private: + /// The hooks to inherit and cleanup the Log_Msg attributes + static ACE_INIT_LOG_MSG_HOOK init_log_msg_hook_; + static ACE_INHERIT_LOG_MSG_HOOK inherit_log_msg_hook_; + static ACE_CLOSE_LOG_MSG_HOOK close_log_msg_hook_; + static ACE_SYNC_LOG_MSG_HOOK sync_log_msg_hook_; + static ACE_THR_DESC_LOG_MSG_HOOK thr_desc_log_msg_hook_; + + /// Set the Log_Msg hooks + static void set_log_msg_hooks (ACE_INIT_LOG_MSG_HOOK init_hook, + ACE_INHERIT_LOG_MSG_HOOK inherit_hook, + ACE_CLOSE_LOG_MSG_HOOK close_hook, + ACE_SYNC_LOG_MSG_HOOK sync_hook, + ACE_THR_DESC_LOG_MSG_HOOK thr_desc); + + /// Allow the ACE_Log_Msg class to set its hooks. + friend class ACE_Log_Msg; + +protected: + /// Thread startup function passed in by the user (C++ linkage). + ACE_THR_FUNC user_func_; + + /// Argument to thread startup function. + void *arg_; + + /// Entry point to the underlying OS thread creation call (C + /// linkage). + ACE_THR_C_FUNC entry_point_; + + /** + * Optional thread descriptor. Passing this pointer in will force + * the spawned thread to cache this location in and wait + * until fills in all information in thread + * descriptor. + */ + ACE_OS_Thread_Descriptor *thr_desc_; + + /// The ACE_Log_Msg attributes. + ACE_OS_Log_Msg_Attributes log_msg_attributes_; + + /// Friend declaration to avoid compiler warning: only defines a private + /// destructor and has no friends. + friend class ACE_Thread_Adapter_Has_Private_Destructor; +}; + +# if defined (ACE_HAS_INLINED_OSCALLS) +# if defined (ACE_INLINE) +# undef ACE_INLINE +# endif /* ACE_INLINE */ +# define ACE_INLINE inline +# include "Base_Thread_Adapter.inl" +# endif /* ACE_HAS_INLINED_OSCALLS */ + +#include "ace/post.h" +#endif /* ACE_BASE_THREAD_ADAPTER_H */ diff --git a/ace/OS/Base_Thread_Adapter.inl b/ace/OS/Base_Thread_Adapter.inl new file mode 100644 index 00000000000..1d0d6ba7a49 --- /dev/null +++ b/ace/OS/Base_Thread_Adapter.inl @@ -0,0 +1,34 @@ +// $Id$ + +ACE_INLINE long +ACE_OS_Thread_Descriptor::flags (void) const +{ + return flags_; +} + +ACE_INLINE +ACE_OS_Thread_Descriptor::ACE_OS_Thread_Descriptor (long flags) + : flags_ (flags) +{ +} + +ACE_INLINE void +ACE_Base_Thread_Adapter::set_log_msg_hooks ( + ACE_INIT_LOG_MSG_HOOK init_hook, + ACE_INHERIT_LOG_MSG_HOOK inherit_hook, + ACE_CLOSE_LOG_MSG_HOOK close_hook, + ACE_SYNC_LOG_MSG_HOOK sync_hook, + ACE_THR_DESC_LOG_MSG_HOOK thr_desc_hook) +{ + ACE_Base_Thread_Adapter::init_log_msg_hook_ = init_hook; + ACE_Base_Thread_Adapter::inherit_log_msg_hook_ = inherit_hook; + ACE_Base_Thread_Adapter::close_log_msg_hook_ = close_hook; + ACE_Base_Thread_Adapter::sync_log_msg_hook_ = sync_hook; + ACE_Base_Thread_Adapter::thr_desc_log_msg_hook_ = thr_desc_hook; +} + +ACE_INLINE ACE_THR_C_FUNC +ACE_Base_Thread_Adapter::entry_point (void) +{ + return this->entry_point_; +} diff --git a/ace/OS/Basic_Types.cpp b/ace/OS/Basic_Types.cpp new file mode 100644 index 00000000000..15c23a402b0 --- /dev/null +++ b/ace/OS/Basic_Types.cpp @@ -0,0 +1,130 @@ +// $Id$ + +#include "OS.h" +#if !defined (__ACE_INLINE__) +# include "Basic_Types.i" +#endif /* ! __ACE_INLINE__ */ + +ACE_RCSID(ace, Basic_Types, "$Id$") + +#if 0 +#if defined (ACE_LACKS_LONGLONG_T) +#include "ace/Log_Msg.h" +#if !defined (ACE_LACKS_IOSTREAM_TOTALLY) +# include "ace/streams.h" +#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */ +#endif + +void +ACE_U_LongLong::output (FILE *file) const +{ + if (h_ () > 0) + ACE_OS::fprintf (file, "0x%lx%0*lx", h_ (), 2 * sizeof l_ (), l_ ()); + else + ACE_OS::fprintf (file, "0x%lx", l_ ()); +} + + +ACE_TCHAR * +ACE_U_LongLong::as_string (ACE_TCHAR *output, + u_int base, + u_int uppercase) const +{ + if (*this == 0) + { + ACE_OS::strcpy(output, "0"); + } + else + { + switch(base) + { + case 8: + { + u_int index = 0; + int bshift = 31; + while(bshift >= 1) + { + u_int sval = (this->h_ () >> bshift) & 7; + if (sval > 0 || index != 0) + { + output[index] = sval + '0'; + index++; + } + bshift -= 3; + } + bshift = 30; + while(bshift >= 0) + { + u_int sval = (this->l_ () >> bshift) & 7; + // Combine the last bit of hi with the first 3-bit digit + if (bshift == 30) + { + sval |= (this->h_ () & 1) << 2; + } + if (sval > 0 || index != 0) + { + output[index] = sval + '0'; + index++; + } + bshift -= 3; + } + output[index] = '\0'; + break; + } + case 10: + { + ACE_OS::sprintf(output, "%.0f", *this / 1.0); + break; + } + case 16: + { + if (this->h_ () != 0) + { + ACE_OS::sprintf(output, + (uppercase ? "%lX%0*lX" : "%lx%0*lx"), + this->h_ (), 2 * sizeof this->l_ (), + this->l_ ()); + } + else + { + ACE_OS::sprintf(output, + (uppercase ? "%lX" : "%lx"), this->l_ ()); + + } + break; + } + default: + { + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("Unsupported base = %u\n"), base)); + output[0] = '\0'; + } + } + } + + return output; +} + + +#if !defined (ACE_LACKS_IOSTREAM_TOTALLY) +ostream& +operator<< (ostream& os, const ACE_U_LongLong& ll) +{ + unsigned long flags = os.setf(0); + char buffer[32]; + + if ((flags & ios::oct) != 0) + os << ll.as_string (buffer, 8); + else if ((flags & ios::hex) != 0) + os << ll.as_string (buffer, 16, (flags & ios::uppercase)); + else + os << ll.as_string (buffer); + return os; +} +#endif + + +#endif /* ACE_LACKS_LONGLONG_T */ + +// Explicit template instantiation file +#include "ace/Template_Instantiations.cpp" diff --git a/ace/OS/Basic_Types.h b/ace/OS/Basic_Types.h new file mode 100644 index 00000000000..fedec0cb74d --- /dev/null +++ b/ace/OS/Basic_Types.h @@ -0,0 +1,610 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Basic_Types.h + * + * $Id$ + * + * @author David L. Levine + * + * #defines the list of preprocessor macros below. The config.h file can + * pre-define any of these to short-cut the definitions. This is usually + * only necessary if the preprocessor does all of its math using integers. + * + * Sizes of built-in types: + * - ACE_SIZEOF_CHAR + * - ACE_SIZEOF_WCHAR + * - ACE_SIZEOF_SHORT + * - ACE_SIZEOF_INT + * - ACE_SIZEOF_LONG + * - ACE_SIZEOF_LONG_LONG + * - ACE_SIZEOF_VOID_P + * - ACE_SIZEOF_FLOAT + * - ACE_SIZEOF_DOUBLE + * - ACE_SIZEOF_LONG_DOUBLE + * + * Wrappers for built-in types of specific sizes: + * - ACE_USHORT16 (For backward compatibility. Use ACE_UINT16 instead.) + * - ACE_INT16 + * - ACE_UINT16 + * - ACE_INT32 + * - ACE_UINT32 + * - ACE_UINT64 + * (Note: ACE_INT64 is not defined, because there is no ACE_LongLong for + * platforms that don't have a native 8-byte integer type.) + * + * Byte-order (endian-ness) determination: + * ACE_BYTE_ORDER, to either ACE_BIG_ENDIAN or ACE_LITTLE_ENDIAN + * + * + */ +//============================================================================= + + +#ifndef ACE_BASIC_TYPES_H +# define ACE_BASIC_TYPES_H + +# include "ace/pre.h" + +# include "ace/config-all.h" + +# if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +# endif /* ACE_LACKS_PRAGMA_ONCE */ + +// Pull in definitions +# include /**/ // Integer limits +# include /**/ // Floating point limits +# include /**/ // Other types + +# if defined(ACE_LACKS_LONGLONG_T) +# include /**/ // LynxOS requires this before stdio.h +# include /**/ // For long long emulation +# endif /* ACE_LACKS_LONGLONG_T */ + +# if !defined (ACE_LACKS_SYS_TYPES_H) +# include /**/ +# endif /* ACE_LACKS_SYS_TYPES_H */ + +# include "ace/ACE_export.h" + +// A char always has 1 byte, by definition. +# define ACE_SIZEOF_CHAR 1 + +// Unfortunately, there isn't a portable way to determine the size of a wchar. +// So we just define them on a platform basis. +# if defined (ACE_HAS_WCHAR) +# if !defined (ACE_SIZEOF_WCHAR) +# if defined (ACE_HAS_XPG4_MULTIBYTE_CHAR) +# define ACE_SIZEOF_WCHAR sizeof (wchar_t) +# else +// 0 so the Basic_Types test will catch this. +# define ACE_SIZEOF_WCHAR 0 +# endif /* ACE_HAS_XPG4_MULTIBYTE_CHAR */ +# endif /* !ACE_SIZEOF_WCHAR */ +# endif /* ACE_HAS_WCHAR */ + +// The number of bytes in a short. +# if !defined (ACE_SIZEOF_SHORT) +# if (USHRT_MAX) == 255U +# define ACE_SIZEOF_SHORT 1 +# elif (USHRT_MAX) == 65535U +# define ACE_SIZEOF_SHORT 2 +# elif (USHRT_MAX) == 4294967295U +# define ACE_SIZEOF_SHORT 4 +# elif (USHRT_MAX) == 18446744073709551615U +# define ACE_SIZEOF_SHORT 8 +# else +# error: unsupported short size, must be updated for this platform! +# endif /* USHRT_MAX */ +# endif /* !defined (ACE_SIZEOF_SHORT) */ + +// The number of bytes in an int. +# if !defined (ACE_SIZEOF_INT) +# if (UINT_MAX) == 65535U +# define ACE_SIZEOF_INT 2 +# elif (UINT_MAX) == 4294967295U +# define ACE_SIZEOF_INT 4 +# elif (UINT_MAX) == 18446744073709551615U +# define ACE_SIZEOF_INT 8 +# else +# error: unsupported int size, must be updated for this platform! +# endif /* UINT_MAX */ +# endif /* !defined (ACE_SIZEOF_INT) */ + +// The number of bytes in a long. +// NOTE - since preprocessors only need to do integer math, this is a likely +// place for a preprocessor to not properly support being able to figure out +// the proper size. HP aC++ and GNU gcc have this difficulty so watch out. +# if !defined (ACE_SIZEOF_LONG) +# if (ULONG_MAX) == 65535UL +# define ACE_SIZEOF_LONG 2 +# elif ((ULONG_MAX) == 4294967295UL) +# define ACE_SIZEOF_LONG 4 +# elif ((ULONG_MAX) == 18446744073709551615UL) +# define ACE_SIZEOF_LONG 8 +# else +# error: unsupported long size, must be updated for this platform! +# endif /* ULONG_MAX */ +# endif /* !defined (ACE_SIZEOF_LONG) */ + +// The number of bytes in a long long. +# if !defined (ACE_SIZEOF_LONG_LONG) +# if defined (ACE_LACKS_LONGLONG_T) +# define ACE_SIZEOF_LONG_LONG 8 +# else /* ! ACE_WIN32 && ! ACE_LACKS_LONGLONG_T */ +# if ACE_SIZEOF_LONG == 8 +# define ACE_SIZEOF_LONG_LONG 8 + typedef unsigned long ACE_UINT64; +# elif defined (ULLONG_MAX) && !defined (__GNUG__) + // Some compilers use ULLONG_MAX and others, e.g. Irix, use + // ULONGLONG_MAX. +# if (ULLONG_MAX) == 18446744073709551615ULL +# define ACE_SIZEOF_LONG_LONG 8 +# elif (ULLONG_MAX) == 4294967295ULL +# define ACE_SIZEOF_LONG_LONG 4 +# else +# error Unsupported long long size needs to be updated for this platform +# endif + typedef unsigned long long ACE_UINT64; +# elif defined (ULONGLONG_MAX) && !defined (__GNUG__) + // Irix 6.x, for example. +# if (ULONGLONG_MAX) == 18446744073709551615ULL +# define ACE_SIZEOF_LONG_LONG 8 +# elif (ULONGLONG_MAX) == 4294967295ULL +# define ACE_SIZEOF_LONG_LONG 4 +# else +# error Unsupported long long size needs to be updated for this platform +# endif + typedef unsigned long long ACE_UINT64; +# else + // ACE_SIZEOF_LONG_LONG is not yet known, but the platform doesn't + // claim ACE_LACKS_LONGLONG_T, so assume it has 8-byte long longs. +# define ACE_SIZEOF_LONG_LONG 8 +# if defined (sun) && !defined (ACE_LACKS_U_LONGLONG_T) + // sun #defines u_longlong_t, maybe other platforms do also. + // Use it, at least with g++, so that its -pedantic doesn't + // complain about no ANSI C++ long long. + typedef u_longlong_t ACE_UINT64; +# else + // LynxOS 2.5.0 and Linux don't have u_longlong_t. + typedef unsigned long long ACE_UINT64; +# endif /* sun */ +# endif /* ULLONG_MAX && !__GNUG__ */ +# endif /* ! ACE_WIN32 && ! ACE_LACKS_LONGLONG_T */ +# endif /* !defined (ACE_SIZEOF_LONG_LONG) */ + +// The sizes of the commonly implemented types are now known. Set up +// typedefs for whatever we can. Some of these are needed for certain cases +// of ACE_UINT64, so do them before the 64-bit stuff. + +# if ACE_SIZEOF_SHORT == 2 + typedef short ACE_INT16; + typedef unsigned short ACE_UINT16; +# elif ACE_SIZEOF_INT == 2 + typedef int ACE_INT16; + typedef unsigned int ACE_UINT16; +# elif (ACE_SIZEOF_SHORT) == 4 && defined(_CRAYMPP) + // mpp cray - uses Alpha processors + // Use the real 32-bit quantity for ACE_INT32's, and use a "long" + // for ACE_INT16's. This gets around conflicts with size_t in some ACE + // method signatures, among other things. + typedef long ACE_INT16; + typedef unsigned long ACE_UINT16; + typedef short ACE_INT32; + typedef unsigned short ACE_UINT32; +# elif (ACE_SIZEOF_SHORT) == 8 && defined(_UNICOS) + // vector cray - hard 64-bit, all 64 bit types + typedef short ACE_INT16; + typedef unsigned short ACE_UINT16; +# else +# error Have to add to the ACE_UINT16 type setting +# endif + +typedef ACE_UINT16 ACE_USHORT16; + +// Define a pseudo wide character type when wchar is not supported so we +// can support basic wide character string operations. + +# if defined (ACE_HAS_WCHAR) +# define ACE_WINT_T wint_t +# define ACE_WCHAR_T wchar_t +# else +# define ACE_WINT_T ACE_USHORT16 +# define ACE_WCHAR_T ACE_USHORT16 +# endif /* ACE_HAS_WCHAR */ + +# if ACE_SIZEOF_INT == 4 + typedef int ACE_INT32; + typedef unsigned int ACE_UINT32; +# if defined (__KCC) && !defined (ACE_LACKS_LONGLONG_T) + typedef unsigned long long ACE_UINT64; +# endif /* __KCC */ +# elif ACE_SIZEOF_LONG == 4 + typedef long ACE_INT32; + typedef unsigned long ACE_UINT32; +# elif (ACE_SIZEOF_INT) == 8 && defined(_UNICOS) + // vector cray - hard 64-bit, all 64 bit types +# if !defined(_CRAYMPP) + typedef int ACE_INT32; + typedef unsigned int ACE_UINT32; +# endif + typedef unsigned long long ACE_UINT64; +# else +# error Have to add to the ACE_UINT32 type setting +# endif + +// The number of bytes in a void *. +# ifndef ACE_SIZEOF_VOID_P +# define ACE_SIZEOF_VOID_P ACE_SIZEOF_LONG +# endif /* ACE_SIZEOF_VOID_P */ + +// Type for doing arithmetic on pointers ... as elsewhere, we assume +// that unsigned versions of a type are the same size as the signed +// version of the same type. +#if ACE_SIZEOF_VOID_P == ACE_SIZEOF_INT +# if defined (__SUNPRO_CC) + // For unknown reasons, Sun CC 5.0 won't allow a reintepret cast + // of a 64-bit pointer to a 64-bit int. + typedef u_long ptr_arith_t; +# else /* ! __SUNPRO_CC */ + typedef u_int ptr_arith_t; +# endif /* ! __SUNPRO_CC */ +#elif ACE_SIZEOF_VOID_P == ACE_SIZEOF_LONG + typedef u_long ptr_arith_t; +#elif ACE_SIZEOF_VOID_P == ACE_SIZEOF_LONG_LONG + typedef u_long long ptr_arith_t; +#else +# error "Can't find a suitable type for doing pointer arithmetic." +#endif /* ACE_SIZEOF_VOID_P */ + +#if defined (ACE_LACKS_LONGLONG_T) + // This throws away the high 32 bits. It's very unlikely that a + // pointer will be more than 32 bits wide if the platform does not + // support 64-bit integers. +# define ACE_LONGLONG_TO_PTR(PTR_TYPE, L) \ + ACE_reinterpret_cast (PTR_TYPE, L.lo ()) +#else /* ! ACE_LACKS_LONGLONG_T */ +# define ACE_LONGLONG_TO_PTR(PTR_TYPE, L) \ + ACE_reinterpret_cast (PTR_TYPE, ACE_static_cast (ptr_arith_t, L)) +#endif /* ! ACE_LACKS_LONGLONG_T */ + +// If the platform lacks a long long, define one. +# if defined (ACE_LACKS_LONGLONG_T) +# if defined (ACE_HAS_MINIMUM_IOSTREAMH_INCLUSION) +// Forward declaration for streams +# include "ace/iosfwd.h" +# else /* ACE_HAS_MINIMUM_IOSTREAMH_INCLUSION */ +// Else they will get all the stream header files +# include "ace/streams.h" +# endif /* ACE_HAS_MINIMUM_IOSTREAMH_INCLUSION */ + +/** + * @class ACE_U_LongLong + * + * @brief Unsigned long long for platforms that don't have one. + * + * Provide our own unsigned long long. This is intended to be + * use with ACE_High_Res_Timer, so the division operator assumes + * that the quotient fits into a u_long. + * Please note that the constructor takes (optionally) two values. + * The high one contributes 0x100000000 times its value. So, + * for example, (0, 2) is _not_ 20000000000, but instead + * 0x200000000. To emphasize this, the default values are expressed + * in hex, and output () dumps the value in hex. + */ + class ACE_Export ACE_U_LongLong + { + public: + // = Initialization and termination methods. + ACE_U_LongLong (const ACE_UINT32 lo = 0x0, const ACE_UINT32 hi = 0x0); + ACE_U_LongLong (const ACE_U_LongLong &); + ACE_U_LongLong &operator= (const ACE_U_LongLong &); + ~ACE_U_LongLong (void); + + // = Overloaded relation operators. + int operator== (const ACE_U_LongLong &) const; + int operator== (const ACE_UINT32) const; + int operator!= (const ACE_U_LongLong &) const; + int operator!= (const ACE_UINT32) const; + int operator< (const ACE_U_LongLong &) const; + int operator< (const ACE_UINT32) const; + int operator<= (const ACE_U_LongLong &) const; + int operator<= (const ACE_UINT32) const; + int operator> (const ACE_U_LongLong &) const; + int operator> (const ACE_UINT32) const; + int operator>= (const ACE_U_LongLong &) const; + int operator>= (const ACE_UINT32) const; + + ACE_U_LongLong operator+ (const ACE_U_LongLong &) const; + ACE_U_LongLong operator+ (const ACE_UINT32) const; + ACE_U_LongLong operator- (const ACE_U_LongLong &) const; + ACE_U_LongLong operator- (const ACE_UINT32) const; + ACE_U_LongLong operator* (const ACE_UINT32) const; + ACE_U_LongLong &operator*= (const ACE_UINT32); + + ACE_U_LongLong operator<< (const u_int) const; + ACE_U_LongLong &operator<<= (const u_int); + ACE_U_LongLong operator>> (const u_int) const; + ACE_U_LongLong &operator>>= (const u_int); + + double operator/ (const double) const; + + ACE_U_LongLong &operator+= (const ACE_U_LongLong &); + ACE_U_LongLong &operator+= (const ACE_UINT32); + ACE_U_LongLong &operator-= (const ACE_U_LongLong &); + ACE_U_LongLong &operator-= (const ACE_UINT32); + ACE_U_LongLong &operator++ (); + ACE_U_LongLong &operator-- (); + ACE_U_LongLong &operator|= (const ACE_U_LongLong); + ACE_U_LongLong &operator|= (const ACE_UINT32); + ACE_U_LongLong &operator&= (const ACE_U_LongLong); + ACE_U_LongLong &operator&= (const ACE_UINT32); + + // Note that the following take ACE_UINT32 arguments. These are + // typical use cases, and easy to implement. But, they limit the + // return values to 32 bits as well. There are no checks for + // overflow. + ACE_UINT32 operator/ (const ACE_UINT32) const; + ACE_UINT32 operator% (const ACE_UINT32) const; + + // The following only operate on the lower 32 bits (they take only + // 32 bit arguments). + ACE_UINT32 operator| (const ACE_INT32) const; + ACE_UINT32 operator& (const ACE_INT32) const; + + // The following operators convert their arguments to + // ACE_UINT32. So, there may be information loss if they are + // used. + ACE_U_LongLong operator* (const ACE_INT32) const; + ACE_U_LongLong &operator*= (const ACE_INT32); + ACE_UINT32 operator/ (const ACE_INT32) const; +# if ACE_SIZEOF_INT == 4 + ACE_UINT32 operator/ (const u_long) const; + ACE_UINT32 operator/ (const long) const; +# else /* ACE_SIZEOF_INT != 4 */ + ACE_UINT32 operator/ (const u_int) const; + ACE_UINT32 operator/ (const int) const; +# endif /* ACE_SIZEOF_INT != 4 */ + + // = Helper methods. + /// Outputs the value to the FILE, in hex. + void output (FILE * = stdout) const; + + ACE_TCHAR *as_string (ACE_TCHAR *string, + u_int base = 10, + u_int uppercase = 0) const; + + ACE_UINT32 hi (void) const; + ACE_UINT32 lo (void) const; + + void hi (const ACE_UINT32 hi); + void lo (const ACE_UINT32 lo); + + private: + union + { + struct + { + ACE_UINT32 hi_; + // High 32 bits. + + ACE_UINT32 lo_; + // Low 32 bits. + } data_; + // To ensure alignment on 8-byte boundary. + + // double isn't usually usable with ACE_LACKS_FLOATING_POINT, + // but this seems OK. + double for_alignment_; + // To ensure alignment on 8-byte boundary. + }; + + // NOTE: the following four accessors are inlined here in + // order to minimize the extent of the data_ struct. It's + // only used here; the .i and .cpp files use the accessors. + + /// Internal utility function to hide access through struct. + const ACE_UINT32 &h_ () const { return data_.hi_; } + + /// Internal utility function to hide access through struct. + ACE_UINT32 &h_ () { return data_.hi_; } + + /// Internal utility function to hide access through struct. + const ACE_UINT32 &l_ () const { return data_.lo_; } + + /// Internal utility function to hide access through struct. + ACE_UINT32 &l_ () { return data_.lo_; } + + // NOTE: the above four accessors are inlined here in + // order to minimize the extent of the data_ struct. It's + // only used here; the .i and .cpp files use the accessors. + + /// These functions are used to implement multiplication. + ACE_UINT32 ul_shift (ACE_UINT32 a, + ACE_UINT32 c_in, + ACE_UINT32 *c_out) const; + ACE_U_LongLong ull_shift (ACE_U_LongLong a, + ACE_UINT32 c_in, + ACE_UINT32 *c_out) const; + ACE_U_LongLong ull_add (ACE_U_LongLong a, + ACE_U_LongLong b, + ACE_UINT32 *carry) const; + ACE_U_LongLong ull_mult (ACE_U_LongLong a, + ACE_UINT32 b, + ACE_UINT32 *carry) const; + }; + + typedef ACE_U_LongLong ACE_UINT64; + +#if !defined (ACE_LACKS_IOSTREAM_TOTALLY) + ostream &operator<< (ostream &, const ACE_U_LongLong &); +#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */ + +# endif /* ACE_LACKS_LONGLONG_T */ + +// Conversions from ACE_UINT64 to ACE_UINT32. ACE_CU64_TO_CU32 should +// be used on const ACE_UINT64's. +# if defined (ACE_LACKS_LONGLONG_T) +# define ACE_U64_TO_U32(n) ((n).lo ()) +# define ACE_CU64_TO_CU32(n) ((n).lo ()) +# else /* ! ACE_LACKS_LONGLONG_T */ +# define ACE_U64_TO_U32(n) (ACE_static_cast (ACE_UINT32, (n))) +# define ACE_CU64_TO_CU32(n) \ + (ACE_static_cast (ACE_CAST_CONST ACE_UINT32, (n))) +# endif /* ! ACE_LACKS_LONGLONG_T */ + +// 64-bit literals require special marking on some platforms. +# if defined (ACE_LACKS_LONGLONG_T) + // Can only specify 32-bit arguments. +# define ACE_UINT64_LITERAL(n) (ACE_U_LongLong (n)) + // This one won't really work, but it'll keep + // some compilers happy until we have better support +# define ACE_INT64_LITERAL(n) (ACE_U_LongLong (n)) +# elif defined (ACE_WIN32) +# if defined (__IBMCPP__) && (__IBMCPP__ >= 400) +# define ACE_UINT64_LITERAL(n) n ## LL +# define ACE_INT64_LITERAL(n) n ## LL +# elif defined (__MINGW32__) +# define ACE_UINT64_LITERAL(n) n ## ull +# define ACE_INT64_LITERAL(n) n ## ll +# else +# define ACE_UINT64_LITERAL(n) n ## ui64 +# define ACE_INT64_LITERAL(n) n ## i64 +# endif /* defined (__IBMCPP__) && (__IBMCPP__ >= 400) */ +# else /* ! ACE_WIN32 && ! ACE_LACKS_LONGLONG_T */ +# define ACE_UINT64_LITERAL(n) n ## ull +# define ACE_INT64_LITERAL(n) n ## ll +# endif /* ! ACE_WIN32 && ! ACE_LACKS_LONGLONG_T */ + +#if !defined (ACE_UINT64_FORMAT_SPECIFIER) +# define ACE_UINT64_FORMAT_SPECIFIER ACE_LIB_TEXT ("%llu") +#endif /* ACE_UINT64_FORMAT_SPECIFIER */ + +#if !defined (ACE_INT64_FORMAT_SPECIFIER) +# define ACE_INT64_FORMAT_SPECIFIER ACE_LIB_TEXT ("%lld") +#endif /* ACE_INT64_FORMAT_SPECIFIER */ + +#if !defined (ACE_SSIZE_T_FORMAT_SPECIFIER) +# define ACE_SSIZE_T_FORMAT_SPECIFIER ACE_LIB_TEXT ("%d") +#endif /* ACE_SSIZE_T_FORMAT_SPECIFIER */ + +#if !defined (ACE_SIZE_T_FORMAT_SPECIFIER) +# define ACE_SIZE_T_FORMAT_SPECIFIER ACE_LIB_TEXT ("%u") +#endif /* ACE_SIZE_T_FORMAT_SPECIFIER */ + +// Cast from UINT64 to a double requires an intermediate cast to INT64 +// on some platforms. +# if defined (ACE_LACKS_LONGLONG_T) + // Only use the low 32 bits. +# define ACE_UINT64_DBLCAST_ADAPTER(n) ACE_U64_TO_U32 (n) +# elif defined (ACE_WIN32) +# define ACE_UINT64_DBLCAST_ADAPTER(n) ACE_static_cast (__int64, n) +# else /* ! ACE_WIN32 && ! ACE_LACKS_LONGLONG_T */ +# define ACE_UINT64_DBLCAST_ADAPTER(n) (n) +# endif /* ! ACE_WIN32 && ! ACE_LACKS_LONGLONG_T */ + + +// The number of bytes in a float. +# ifndef ACE_SIZEOF_FLOAT +# if FLT_MAX_EXP == 128 +# define ACE_SIZEOF_FLOAT 4 +# elif FLT_MAX_EXP == 1024 +# define ACE_SIZEOF_FLOAT 8 +# else +# error: unsupported float size, must be updated for this platform! +# endif /* FLT_MAX_EXP */ +# endif /* ACE_SIZEOF_FLOAT */ + +// The number of bytes in a double. +# ifndef ACE_SIZEOF_DOUBLE +# if DBL_MAX_EXP == 128 +# define ACE_SIZEOF_DOUBLE 4 +# elif DBL_MAX_EXP == 1024 +# define ACE_SIZEOF_DOUBLE 8 +# else +# error: unsupported double size, must be updated for this platform! +# endif /* DBL_MAX_EXP */ +# endif /* ACE_SIZEOF_DOUBLE */ + +// The number of bytes in a long double. +# ifndef ACE_SIZEOF_LONG_DOUBLE +# if LDBL_MAX_EXP == 128 +# define ACE_SIZEOF_LONG_DOUBLE 4 +# elif LDBL_MAX_EXP == 1024 +# define ACE_SIZEOF_LONG_DOUBLE 8 +# elif LDBL_MAX_EXP == 16384 +# if defined (LDBL_DIG) && LDBL_DIG == 18 +# if defined (__ia64) +# define ACE_SIZEOF_LONG_DOUBLE 16 +# else /* ! __ia64 */ +# define ACE_SIZEOF_LONG_DOUBLE 12 +# endif /* __ia64 */ +# else /* ! LDBL_DIG || LDBL_DIG != 18 */ +# define ACE_SIZEOF_LONG_DOUBLE 16 +# endif /* ! LDBL_DIG || LDBL_DIG != 18 */ +# else +# error: unsupported double size, must be updated for this platform! +# endif /* LDBL_MAX_EXP */ +# endif /* ACE_SIZEOF_LONG_DOUBLE */ + +// Max and min sizes for the ACE integer types. +#define ACE_CHAR_MAX 0x7F +#define ACE_CHAR_MIN -(ACE_CHAR_MAX)-1 +#define ACE_OCTET_MAX 0xFF +#define ACE_INT16_MAX 0x7FFF +#define ACE_INT16_MIN -(ACE_INT16_MAX)-1 +#define ACE_UINT16_MAX 0xFFFF +#define ACE_WCHAR_MAX ACE_UINT16_MAX +#define ACE_INT32_MAX 0x7FFFFFFF +#define ACE_INT32_MIN -(ACE_INT32_MAX)-1 +#define ACE_UINT32_MAX 0xFFFFFFFF +#define ACE_INT64_MAX ACE_INT64_LITERAL(0x7FFFFFFFFFFFFFFF) +#define ACE_INT64_MIN -(ACE_INT64_MAX)-1 +#define ACE_UINT64_MAX ACE_UINT64_LITERAL(0xFFFFFFFFFFFFFFFF) +// These use ANSI/IEEE format. +#define ACE_FLT_MAX 3.402823466e+38F +#define ACE_DBL_MAX 1.7976931348623158e+308 + +// Byte-order (endian-ness) determination. +# if defined (BYTE_ORDER) +# if (BYTE_ORDER == LITTLE_ENDIAN) +# define ACE_LITTLE_ENDIAN 0x0123 +# define ACE_BYTE_ORDER ACE_LITTLE_ENDIAN +# elif (BYTE_ORDER == BIG_ENDIAN) +# define ACE_BIG_ENDIAN 0x3210 +# define ACE_BYTE_ORDER ACE_BIG_ENDIAN +# else +# error: unknown BYTE_ORDER! +# endif /* BYTE_ORDER */ +# elif defined (__BYTE_ORDER) +# if (__BYTE_ORDER == __LITTLE_ENDIAN) +# define ACE_LITTLE_ENDIAN 0x0123 +# define ACE_BYTE_ORDER ACE_LITTLE_ENDIAN +# elif (__BYTE_ORDER == __BIG_ENDIAN) +# define ACE_BIG_ENDIAN 0x3210 +# define ACE_BYTE_ORDER ACE_BIG_ENDIAN +# else +# error: unknown __BYTE_ORDER! +# endif /* __BYTE_ORDER */ +# else /* ! BYTE_ORDER && ! __BYTE_ORDER */ + // We weren't explicitly told, so we have to figure it out . . . +# if defined (i386) || defined (__i386__) || defined (_M_IX86) || \ + defined (vax) || defined (__alpha) || defined (__LITTLE_ENDIAN__) + // We know these are little endian. +# define ACE_LITTLE_ENDIAN 0x0123 +# define ACE_BYTE_ORDER ACE_LITTLE_ENDIAN +# else + // Otherwise, we assume big endian. +# define ACE_BIG_ENDIAN 0x3210 +# define ACE_BYTE_ORDER ACE_BIG_ENDIAN +# endif +# endif /* ! BYTE_ORDER && ! __BYTE_ORDER */ + +# if defined (__ACE_INLINE__) +# include "Basic_Types.i" +# endif /* __ACE_INLINE__ */ + +# include "ace/post.h" +#endif /* ACE_BASIC_TYPES_H */ diff --git a/ace/OS/Basic_Types.i b/ace/OS/Basic_Types.i new file mode 100644 index 00000000000..f5a0b0837d4 --- /dev/null +++ b/ace/OS/Basic_Types.i @@ -0,0 +1,477 @@ +/* -*- C++ -*- */ +// $Id$ + +#if defined (ACE_LACKS_LONGLONG_T) + +ACE_INLINE +ACE_U_LongLong::ACE_U_LongLong (const ACE_UINT32 lo, const ACE_UINT32 hi) +{ + h_ () = hi; + l_ () = lo; +} + +ACE_INLINE ACE_UINT32 +ACE_U_LongLong::hi (void) const +{ + return h_ (); +} + +ACE_INLINE ACE_UINT32 +ACE_U_LongLong::lo (void) const +{ + return l_ (); +} + +ACE_INLINE void +ACE_U_LongLong::hi (const ACE_UINT32 hi) +{ + h_ () = hi; +} + +ACE_INLINE void +ACE_U_LongLong::lo (const ACE_UINT32 lo) +{ + l_ () = lo; +} + +ACE_INLINE +ACE_U_LongLong::~ACE_U_LongLong (void) +{ +} + +ACE_INLINE int +ACE_U_LongLong::operator== (const ACE_U_LongLong &n) const +{ + return h_ () == n.h_ () && l_ () == n.l_ (); +} + +ACE_INLINE int +ACE_U_LongLong::operator== (const ACE_UINT32 n) const +{ + return h_ () == 0 && l_ () == n; +} + +ACE_INLINE int +ACE_U_LongLong::operator!= (const ACE_U_LongLong &n) const +{ + return ! (*this == n); +} + +ACE_INLINE int +ACE_U_LongLong::operator!= (const ACE_UINT32 n) const +{ + return ! (*this == n); +} + +ACE_INLINE int +ACE_U_LongLong::operator< (const ACE_U_LongLong &n) const +{ + return h_ () < n.h_ () ? 1 + : h_ () > n.h_ () ? 0 + : l_ () < n.l_ (); +} + +ACE_INLINE int +ACE_U_LongLong::operator< (const ACE_UINT32 n) const +{ + return operator< (ACE_static_cast (const ACE_U_LongLong, n)); +} + +ACE_INLINE int +ACE_U_LongLong::operator<= (const ACE_U_LongLong &n) const +{ + return h_ () < n.h_ () ? 1 + : h_ () > n.h_ () ? 0 + : l_ () <= n.l_ (); +} + +ACE_INLINE int +ACE_U_LongLong::operator<= (const ACE_UINT32 n) const +{ + return operator<= (ACE_static_cast (const ACE_U_LongLong, n)); +} + +ACE_INLINE int +ACE_U_LongLong::operator> (const ACE_U_LongLong &n) const +{ + return h_ () > n.h_ () ? 1 + : h_ () < n.h_ () ? 0 + : l_ () > n.l_ (); +} + +ACE_INLINE int +ACE_U_LongLong::operator> (const ACE_UINT32 n) const +{ + return operator> (ACE_static_cast (const ACE_U_LongLong, n)); +} + +ACE_INLINE int +ACE_U_LongLong::operator>= (const ACE_U_LongLong &n) const +{ + return h_ () > n.h_ () ? 1 + : h_ () < n.h_ () ? 0 + : l_ () >= n.l_ (); +} + +ACE_INLINE int +ACE_U_LongLong::operator>= (const ACE_UINT32 n) const +{ + return operator>= (ACE_static_cast (const ACE_U_LongLong, n)); +} + +ACE_INLINE +ACE_U_LongLong::ACE_U_LongLong (const ACE_U_LongLong &n) +{ + h_ () = n.h_ (); + l_ () = n.l_ (); +} + +ACE_INLINE ACE_U_LongLong & +ACE_U_LongLong::operator= (const ACE_U_LongLong &n) +{ + h_ () = n.h_ (); + l_ () = n.l_ (); + + return *this; +} + +ACE_INLINE ACE_U_LongLong +ACE_U_LongLong::operator+ (const ACE_U_LongLong &n) const +{ + ACE_U_LongLong ret (l_ () + n.l_ (), h_ () + n.h_ ()); + if (ret.l_ () < n.l_ ()) /* carry */ ++ret.h_ (); + + return ret; +} + +ACE_INLINE ACE_U_LongLong +ACE_U_LongLong::operator+ (const ACE_UINT32 n) const +{ + return operator+ (ACE_static_cast (const ACE_U_LongLong, n)); +} + +ACE_INLINE ACE_U_LongLong +ACE_U_LongLong::operator- (const ACE_U_LongLong &n) const +{ + ACE_U_LongLong ret (l_ () - n.l_ (), h_ () - n.h_ ()); + if (l_ () < n.l_ ()) /* borrow */ --ret.h_ (); + + return ret; +} + +ACE_INLINE ACE_U_LongLong +ACE_U_LongLong::operator- (const ACE_UINT32 n) const +{ + return operator- (ACE_static_cast (const ACE_U_LongLong, n)); +} + +ACE_INLINE ACE_U_LongLong +ACE_U_LongLong::operator<< (const u_int n) const +{ + const ACE_UINT32 carry_mask = l_ () >> (32 - n); + ACE_U_LongLong ret (n < 32 ? l_ () << n : 0, + n < 32 ? (h_ () << n) | carry_mask : carry_mask); + + return ret; +} + +ACE_INLINE ACE_U_LongLong & +ACE_U_LongLong::operator<<= (const u_int n) +{ + const ACE_UINT32 carry_mask = l_ () >> (32 - n); + h_ () = n < 32 ? (h_ () << n) | carry_mask : carry_mask; + + // g++ 2.7.2.3/Solaris 2.5.1 doesn't modify l_ () if shifted by 32. + l_ () = n < 32 ? l_ () << n : 0; + + return *this; +} + +ACE_INLINE ACE_U_LongLong +ACE_U_LongLong::operator>> (const u_int n) const +{ + const ACE_UINT32 carry_mask = h_ () << (32 - n); + ACE_U_LongLong ret (n < 32 ? (l_ () >> n) | carry_mask : 0, + n < 32 ? h_ () >> n : 0); + + return ret; +} + +ACE_INLINE ACE_U_LongLong & +ACE_U_LongLong::operator>>= (const u_int n) +{ + const ACE_UINT32 carry_mask = h_ () << (32 - n); + l_ () = n < 32 ? (l_ () >> n) | carry_mask : carry_mask; + h_ () = n < 32 ? h_ () >> n : 0; + + return *this; +} + +ACE_INLINE double +ACE_U_LongLong::operator/ (const double n) const +{ + // See the derivation above in operator/ (const ACE_UINT32). + + return ((double) 0xffffffffu - n + 1.0) / n * h_ () + + (double) h_ () + (double) l_ () / n; +} + +ACE_INLINE ACE_U_LongLong & +ACE_U_LongLong::operator+= (const ACE_U_LongLong &n) +{ + h_ () += n.h_ (); + l_ () += n.l_ (); + if (l_ () < n.l_ ()) /* carry */ ++h_ (); + + return *this; +} + +ACE_INLINE ACE_U_LongLong & +ACE_U_LongLong::operator+= (const ACE_UINT32 n) +{ + return operator+= (ACE_static_cast (const ACE_U_LongLong, n)); +} + +#define ACE_HIGHBIT (~(~0UL >> 1)) + +ACE_INLINE ACE_UINT32 +ACE_U_LongLong::ul_shift (ACE_UINT32 a, ACE_UINT32 c_in, ACE_UINT32 *c_out) const +{ + const ACE_UINT32 b = (a << 1) | c_in; + *c_out = (*c_out << 1) + ((a & ACE_HIGHBIT) > 0); + + return b; +} + +ACE_INLINE ACE_U_LongLong +ACE_U_LongLong::ull_shift (ACE_U_LongLong a, + ACE_UINT32 c_in, + ACE_UINT32 *c_out) const +{ + ACE_U_LongLong b; + + b.l_ () = (a.l_ () << 1) | c_in; + c_in = ((a.l_ () & ACE_HIGHBIT) > 0); + b.h_ () = (a.h_ () << 1) | c_in; + *c_out = (*c_out << 1) + ((a.h_ () & ACE_HIGHBIT) > 0); + + return b; +} + +ACE_INLINE ACE_U_LongLong +ACE_U_LongLong::ull_add (ACE_U_LongLong a, ACE_U_LongLong b, ACE_UINT32 *carry) const +{ + ACE_U_LongLong r (0, 0); + ACE_UINT32 c1, c2, c3, c4; + + c1 = a.l_ () % 2; + c2 = b.l_ () % 2; + c3 = 0; + + r.l_ () = a.l_ ()/2 + b.l_ ()/2 + (c1+c2)/2; + r.l_ () = ul_shift (r.l_ (), (c1+c2)%2, &c3); + + c1 = a.h_ () % 2; + c2 = b.h_ () % 2; + c4 = 0; + + r.h_ () = a.h_ ()/2 + b.h_ ()/2 + (c1+c2+c3)/2; + r.h_ () = ul_shift (r.h_ (), (c1+c2+c3)%2, &c4); + + *carry = c4; + + return r; +} + +ACE_INLINE ACE_U_LongLong +ACE_U_LongLong::ull_mult (ACE_U_LongLong a, ACE_UINT32 b, ACE_UINT32 *carry) const +{ + register ACE_UINT32 mask = ACE_HIGHBIT; + const ACE_U_LongLong zero (0, 0); + ACE_U_LongLong accum (0, 0); + ACE_UINT32 c; + + *carry = 0; + if (b > 0) + do + { + accum = ull_shift (accum, 0U, carry); + if (b & mask) + accum = ull_add (accum, a, &c); + else + accum = ull_add (accum, zero, &c); + *carry += c; + mask >>= 1; + } + while (mask > 0); + + return accum; +} + +ACE_INLINE ACE_U_LongLong +ACE_U_LongLong::operator* (const ACE_UINT32 n) const +{ + ACE_UINT32 carry; // will throw the carry away + + return ull_mult (*this, n, &carry); +} + +ACE_INLINE ACE_U_LongLong & +ACE_U_LongLong::operator*= (const ACE_UINT32 n) +{ + ACE_UINT32 carry; // will throw the carry away + + return *this = ull_mult (*this, n, &carry); +} + +ACE_INLINE ACE_U_LongLong & +ACE_U_LongLong::operator-= (const ACE_U_LongLong &n) +{ + h_ () -= n.h_ (); + if (l_ () < n.l_ ()) /* borrow */ --h_ (); + l_ () -= n.l_ (); + + return *this; +} + +ACE_INLINE ACE_U_LongLong & +ACE_U_LongLong::operator-= (const ACE_UINT32 n) +{ + return operator-= (ACE_static_cast (const ACE_U_LongLong, n)); +} + +ACE_INLINE ACE_U_LongLong & +ACE_U_LongLong::operator++ () +{ + ++l_ (); + if (l_ () == 0) /* carry */ ++h_ (); + + return *this; +} + +ACE_INLINE ACE_U_LongLong & +ACE_U_LongLong::operator-- () +{ + if (l_ () == 0) /* borrow */ --h_ (); + --l_ (); + + return *this; +} + +ACE_INLINE ACE_U_LongLong & +ACE_U_LongLong::operator|= (const ACE_U_LongLong n) +{ + l_ () |= n.l_ (); + h_ () |= n.h_ (); + + return *this; +} + +ACE_INLINE ACE_U_LongLong & +ACE_U_LongLong::operator|= (const ACE_UINT32 n) +{ + return operator|= (ACE_static_cast (const ACE_U_LongLong, n)); +} + +ACE_INLINE ACE_U_LongLong & +ACE_U_LongLong::operator&= (const ACE_U_LongLong n) +{ + l_ () &= n.l_ (); + h_ () &= n.h_ (); + + return *this; +} + +ACE_INLINE ACE_U_LongLong & +ACE_U_LongLong::operator&= (const ACE_UINT32 n) +{ + return operator&= (ACE_static_cast (const ACE_U_LongLong, n)); +} + +ACE_INLINE ACE_UINT32 +ACE_U_LongLong::operator/ (const ACE_UINT32 n) const +{ + // This takes advantage of the fact that the return type has only 32 + // bits. Replace 0x100000000 with 0xffffffff + 1 because the former + // has 33 bits. + // Quotient = (0x100000000u * hi_ + lo_) / n + // = ((0x100000000u - n + n) * hi_ + lo_) / n + // = ((0x100000000u - n) / n * hi_ + hi_ * n / n + lo_ / n + // = (0x100000000u - n) / n * hi_ + hi_ + lo_ / n + // = (0xffffffffu - n + 1) / n * hi_ + hi_ + lo_ / n + + return (0xffffffffu - n + 1) / n * h_ () + h_ () + l_ () / n; +} + +ACE_INLINE ACE_UINT32 +ACE_U_LongLong::operator% (const ACE_UINT32 n) const +{ + // Because the argument is an ACE_UINT32, the result can never be + // bigger than 32 bits. Replace 0x100000000 with 0xffffffff + 1 + // because the former has 33 bits. + // Mod = (0x100000000u * hi_ + lo_) % n + // = (0x100000000u % n * hi_ + lo_ % n) % n + // = ((0x100000000u - n) % n * hi_ + lo_ % n) % n + // = ((0xffffffffu - n + 1) % n * hi_ + lo_ % n) % n + + return ((0xffffffff - n + 1) % n * h_ () + l_ () % n) % n; +} + +ACE_INLINE ACE_UINT32 +ACE_U_LongLong::operator| (const ACE_INT32 n) const +{ + return l_ () | n; +} + +ACE_INLINE ACE_UINT32 +ACE_U_LongLong::operator& (const ACE_INT32 n) const +{ + return l_ () & n; +} + +ACE_INLINE ACE_U_LongLong +ACE_U_LongLong::operator* (const ACE_INT32 n) const +{ + return operator* ((ACE_UINT32) n); +} + +ACE_INLINE ACE_U_LongLong & +ACE_U_LongLong::operator*= (const ACE_INT32 n) +{ + return operator*= ((ACE_UINT32) n); +} + +ACE_INLINE ACE_UINT32 +ACE_U_LongLong::operator/ (const ACE_INT32 n) const +{ + return operator/ ((ACE_UINT32) n); +} + +#if ACE_SIZEOF_INT == 4 +ACE_INLINE ACE_UINT32 +ACE_U_LongLong::operator/ (const u_long n) const +{ + return operator/ ((ACE_UINT32) n); +} + +ACE_INLINE ACE_UINT32 +ACE_U_LongLong::operator/ (const long n) const +{ + return operator/ ((ACE_UINT32) n); +} + +#else /* ACE_SIZEOF_INT != 4 */ +ACE_INLINE ACE_UINT32 +ACE_U_LongLong::operator/ (const u_int n) const +{ + return operator/ ((ACE_UINT32) n); +} + +ACE_INLINE ACE_UINT32 +ACE_U_LongLong::operator/ (const int n) const +{ + return operator/ ((ACE_UINT32) n); +} +#endif /* ACE_SIZEOF_INT != 4 */ + +#endif /* ACE_LACKS_LONGLONG_T */ diff --git a/ace/OS/Date_Time.cpp b/ace/OS/Date_Time.cpp new file mode 100644 index 00000000000..22b6532c610 --- /dev/null +++ b/ace/OS/Date_Time.cpp @@ -0,0 +1,10 @@ +// Date_Time.cpp +// $Id$ + +#include "Date_Time.h" + +#if defined (ACE_LACKS_INLINE_FUNCTIONS) +#include "Date_Time.i" +#endif + +ACE_RCSID(ace, Date_Time, "$Id$") diff --git a/ace/OS/Date_Time.h b/ace/OS/Date_Time.h new file mode 100644 index 00000000000..52d42ec3f89 --- /dev/null +++ b/ace/OS/Date_Time.h @@ -0,0 +1,105 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file Date_Time.h + * + * $Id$ + * + * @author Tim Harrison (harrison@cs.wustl.edu) (and he's darn proud of this ;-)) + * + */ +//============================================================================= + +#ifndef ACE_DATE_TIME_H +#define ACE_DATE_TIME_H +#include "ace/pre.h" + +#include "ace/ACE.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +/** + * @class ACE_Date_Time + * + * @brief System independent representation of date and time. + */ +class ACE_Export ACE_Date_Time +{ +public: + /// Constructor initializes current time/date info. + ACE_Date_Time (void); + + /// Constructor with init values, no check for validy + /// Set/get portions of ACE_Date_Time, no check for validity. + ACE_Date_Time (long day, + long month = 0, + long year = 0, + long hour = 0, + long minute = 0, + long second = 0, + long microsec = 0); + + /// Update to the current time/date. + void update (void); + + /// Get day. + long day (void) const; + + /// Set day. + void day (long day); + + /// Get month. + long month (void) const; + + /// Set month. + void month (long month); + + /// Get year. + long year (void) const; + + /// Set year. + void year (long year); + + /// Get hour. + long hour (void) const; + + /// Set hour. + void hour (long hour); + + /// Get minute. + long minute (void) const; + + /// Set minute. + void minute (long minute); + + /// Get second. + long second (void) const; + + /// Set second. + void second (long second); + + /// Get microsec. + long microsec (void) const; + + /// Set microsec. + void microsec (long microsec); + +private: + long day_; + long month_; + long year_; + long hour_; + long minute_; + long second_; + long microsec_; +}; + +#if !defined (ACE_LACKS_INLINE_FUNCTIONS) +#include "Date_Time.i" +#endif + +#include "ace/post.h" +#endif /* ACE_DATE_TIME_H */ diff --git a/ace/OS/Date_Time.i b/ace/OS/Date_Time.i new file mode 100644 index 00000000000..9913f129327 --- /dev/null +++ b/ace/OS/Date_Time.i @@ -0,0 +1,162 @@ +/* -*- C++ -*- */ +// $Id$ + +// Date_Time.i + +ASYS_INLINE void +ACE_Date_Time::update (void) +{ + ACE_TRACE ("ACE_Date_Time::update"); + + ACE_Time_Value now = ACE_OS::gettimeofday (); + time_t time = now.sec (); + struct tm *tm_time = ACE_OS::localtime (&time); + this->day_ = tm_time->tm_mday; + this->month_ = tm_time->tm_mon + 1; // localtime's months are 0-11 + this->year_ = tm_time->tm_year + 1900; // localtime reports years since 1900 + this->hour_ = tm_time->tm_hour; + this->minute_ = tm_time->tm_min; + this->second_ = tm_time->tm_sec; + this->microsec_ = now.usec (); +} + +ASYS_INLINE +ACE_Date_Time::ACE_Date_Time (void) +{ + ACE_TRACE ("ACE_Date_Time::ACE_Date_Time"); + this->update (); +} + +// Constructor with init values, no check for validy +ASYS_INLINE +ACE_Date_Time::ACE_Date_Time (long day, + long month, + long year, + long hour, + long minute, + long second, + long microsec) + : day_ (day), + month_ (month), + year_ (year), + hour_ (hour), + minute_ (minute), + second_ (second), + microsec_ (microsec) +{ + ACE_TRACE ("ACE_Date_Time::ACE_Date_Time"); +} + +// set/get portions of ACE_Date_Time, no check for validy + +// get day +ASYS_INLINE long +ACE_Date_Time::day (void) const +{ + ACE_TRACE ("ACE_Date_Time::day"); + return day_; +} + +// set day +ASYS_INLINE void +ACE_Date_Time::day (long day) +{ + ACE_TRACE ("ACE_Date_Time::day"); + day_ = day; +} + +// get month +ASYS_INLINE long +ACE_Date_Time::month (void) const +{ + ACE_TRACE ("ACE_Date_Time::month"); + return month_; +} + +// set month +ASYS_INLINE void +ACE_Date_Time::month (long month) +{ + ACE_TRACE ("ACE_Date_Time::month"); + month_ = month; +} + +// get year +ASYS_INLINE long +ACE_Date_Time::year (void) const +{ + ACE_TRACE ("ACE_Date_Time::year"); + return year_; +} + +// set year +ASYS_INLINE void +ACE_Date_Time::year (long year) +{ + ACE_TRACE ("ACE_Date_Time::year"); + year_ = year; +} + +// get hour +ASYS_INLINE long +ACE_Date_Time::hour (void) const +{ + ACE_TRACE ("ACE_Date_Time::hour"); + return hour_; +} + +// set hour +ASYS_INLINE void +ACE_Date_Time::hour (long hour) +{ + ACE_TRACE ("ACE_Date_Time::hour"); + hour_ = hour; +} + +// get minute +ASYS_INLINE long +ACE_Date_Time::minute (void) const +{ + ACE_TRACE ("ACE_Date_Time::minute"); + return minute_; +} + +// set minute +ASYS_INLINE void +ACE_Date_Time::minute (long minute) +{ + ACE_TRACE ("ACE_Date_Time::minute"); + minute_ = minute; +} + +// get second +ASYS_INLINE long +ACE_Date_Time::second (void) const +{ + ACE_TRACE ("ACE_Date_Time::second"); + return second_; +} + +// set second +ASYS_INLINE void +ACE_Date_Time::second (long second) +{ + ACE_TRACE ("ACE_Date_Time::second"); + second_ = second; +} + +// get microsec +ASYS_INLINE long +ACE_Date_Time::microsec (void) const +{ + ACE_TRACE ("ACE_Date_Time::microsec"); + return microsec_; +} + +// set microsec +ASYS_INLINE void +ACE_Date_Time::microsec (long microsec) +{ + ACE_TRACE ("ACE_Date_Time::microsec"); + microsec_ = microsec; +} diff --git a/ace/OS/Global_Macros.h b/ace/OS/Global_Macros.h new file mode 100644 index 00000000000..7715199b128 --- /dev/null +++ b/ace/OS/Global_Macros.h @@ -0,0 +1,115 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Global_Macros.h + * + * $Id$ + * + * @author Douglas C. Schmidt + * @author Jesper S. M|ller + * @author and a cast of thousands... + * @This one is split from the famous OS.h + */ +//============================================================================= + +#ifndef ACE_GLOBAL_MACROS_H +#define ACE_GLOBAL_MACROS_H +#include "ace/pre.h" + +// Included just keep compilers that see #pragma dierctive first +// happy. +#include "ace/config-all.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + + +// Start Global Macros +# define ACE_BEGIN_DUMP ACE_LIB_TEXT ("\n====\n(%P|%t|%x)") +# define ACE_END_DUMP ACE_LIB_TEXT ("====\n") + + + +# if defined (ACE_NDEBUG) +# define ACE_DB(X) +# else +# define ACE_DB(X) X +# endif /* ACE_NDEBUG */ + +// ACE_NO_HEAP_CHECK macro can be used to suppress false report of +// memory leaks. It turns off the built-in heap checking until the +// block is left. The old state will then be restored Only used for +// Win32 (in the moment). +# if defined (ACE_WIN32) + +# if defined (_DEBUG) && !defined (ACE_HAS_WINCE) && !defined (__BORLANDC__) +# include /**/ + +class ACE_OS_Export ACE_No_Heap_Check +{ +public: + ACE_No_Heap_Check (void) + : old_state (_CrtSetDbgFlag (_CRTDBG_REPORT_FLAG)) + { _CrtSetDbgFlag (old_state & ~_CRTDBG_ALLOC_MEM_DF);} + ~ACE_No_Heap_Check (void) { _CrtSetDbgFlag (old_state);} +private: + int old_state; +}; +# define ACE_NO_HEAP_CHECK ACE_No_Heap_Check ____no_heap; +# else /* !_DEBUG */ +# define ACE_NO_HEAP_CHECK +# endif /* _DEBUG */ +# else /* !ACE_WIN32 */ +# define ACE_NO_HEAP_CHECK +# endif /* ACE_WIN32 */ + +// Turn a number into a string. +# define ACE_ITOA(X) #X + +// Create a string of a server address with a "host:port" format. +# define ACE_SERVER_ADDRESS(H,P) H":"P + +// A couple useful inline functions for checking whether bits are +// enabled or disabled. + +// Efficiently returns the least power of two >= X... +# define ACE_POW(X) (((X) == 0)?1:(X-=1,X|=X>>1,X|=X>>2,X|=X>>4,X|=X>>8,X|=X>>16,(++X))) +# define ACE_EVEN(NUM) (((NUM) & 1) == 0) +# define ACE_ODD(NUM) (((NUM) & 1) == 1) +# define ACE_BIT_ENABLED(WORD, BIT) (((WORD) & (BIT)) != 0) +# define ACE_BIT_DISABLED(WORD, BIT) (((WORD) & (BIT)) == 0) +# define ACE_BIT_CMP_MASK(WORD, BIT, MASK) (((WORD) & (BIT)) == MASK) +# define ACE_SET_BITS(WORD, BITS) (WORD |= (BITS)) +# define ACE_CLR_BITS(WORD, BITS) (WORD &= ~(BITS)) + +# if !defined (ACE_ENDLESS_LOOP) +# define ACE_ENDLESS_LOOP +# endif /* ! ACE_ENDLESS_LOOP */ + +# if defined (ACE_NEEDS_FUNC_DEFINITIONS) + // It just evaporated ;-) Not pleasant. +# define ACE_UNIMPLEMENTED_FUNC(f) +# else +# define ACE_UNIMPLEMENTED_FUNC(f) f; +# endif /* ACE_NEEDS_FUNC_DEFINITIONS */ + +// Easy way to designate that a class is used as a pseudo-namespace. +// Insures that g++ "friendship" anamolies are properly handled. +# define ACE_CLASS_IS_NAMESPACE(CLASSNAME) \ +private: \ +CLASSNAME (void); \ +CLASSNAME (const CLASSNAME&); \ +friend class ace_dewarn_gplusplus + + +# if (ACE_NTRACE == 1) +# define ACE_TRACE(X) +# else +# define ACE_TRACE(X) ACE_Trace ____ (ACE_LIB_TEXT (X), __LINE__, ACE_LIB_TEXT (__FILE__)) +# endif /* ACE_NTRACE */ + + +#include "ace/post.h" +#endif /*ACE_GLOBAL_MACROS_H*/ diff --git a/ace/OS/Handle_Gobbler.h b/ace/OS/Handle_Gobbler.h new file mode 100644 index 00000000000..f007f2f0e96 --- /dev/null +++ b/ace/OS/Handle_Gobbler.h @@ -0,0 +1,66 @@ + +//============================================================================= +/** + * @file Handle_Gobbler.h + * + * $Id$ + * + * @author Kirthika Parameswaran + * @author Irfan Pyarali + */ +//============================================================================= + + +#ifndef ACE_HANDLE_GOBBLER_H +#define ACE_HANDLE_GOBBLER_H +#include "ace/pre.h" + +#include "OS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Unbounded_Set.h" + +/** + * @class ACE_Handle_Gobbler + * + * @brief This class gobbles up handles. + * + * This is useful when we need to control the number of handles + * available for a process. This class is mostly used for + * testing purposes. + */ +class ACE_Handle_Gobbler +{ +public: + + /// Destructor. Cleans up any remaining handles. + inline ~ACE_Handle_Gobbler (void); + + /** + * Handles are opened continously until the process runs out of + * them, and then handles are closed + * (freed) thereby making them usable in the future. + */ + inline int consume_handles (size_t n_handles_to_keep_available); + + /// Free up . + inline int free_handles (size_t n_handles); + + /// All remaining handles are closed. + inline void close_remaining_handles (void); + +private: + + typedef ACE_Unbounded_Set HANDLE_SET; + + /// The container which holds the open descriptors. + HANDLE_SET handle_set_; +}; + +#include "Handle_Gobbler.i" + +#include "ace/post.h" +#endif /* ACE_HANDLE_GOBBLER_H */ diff --git a/ace/OS/Handle_Gobbler.i b/ace/OS/Handle_Gobbler.i new file mode 100644 index 00000000000..f4af340a012 --- /dev/null +++ b/ace/OS/Handle_Gobbler.i @@ -0,0 +1,88 @@ +// $Id$ + +// Since this is only included in Handle_Gobbler.h, these should be +// inline, not ACE_INLINE. +// FUZZ: disable check_for_inline + +inline void +ACE_Handle_Gobbler::close_remaining_handles (void) +{ + HANDLE_SET::iterator iterator = + this->handle_set_.begin (); + + HANDLE_SET::iterator end = + this->handle_set_.end (); + + for (; + iterator != end; + ++iterator) + { + ACE_OS::close (*iterator); + } +} + +inline +ACE_Handle_Gobbler::~ACE_Handle_Gobbler (void) +{ + this->close_remaining_handles (); +} + +inline int +ACE_Handle_Gobbler::free_handles (size_t n_handles) +{ + HANDLE_SET::iterator iterator = + this->handle_set_.begin (); + + HANDLE_SET::iterator end = + this->handle_set_.end (); + + for (; + iterator != end && n_handles > 0; + ++iterator, --n_handles) + { + int result = ACE_OS::close (*iterator); + if (result != 0) + return result; + } + + return 0; +} + +inline int +ACE_Handle_Gobbler::consume_handles (size_t n_handles_to_keep_available) +{ + int result = 0; + +#if defined(ACE_WIN32) + // On Win32, this style of gobbling doesn't seem to work. + ACE_UNUSED_ARG(n_handles_to_keep_available); + +#else + + while (1) + { + ACE_HANDLE handle = ACE_OS::open (ACE_DEV_NULL, O_WRONLY); + + if (handle == ACE_INVALID_HANDLE) + { + if (ACE::out_of_handles (errno)) + { + result = this->free_handles (n_handles_to_keep_available); + break; + } + else + { + result = -1; + break; + } + } + + result = this->handle_set_.insert (handle); + if (result == -1) + break; + } + +#endif /* ACE_WIN32 */ + + return result; +} diff --git a/ace/OS/Handle_Ops.cpp b/ace/OS/Handle_Ops.cpp new file mode 100644 index 00000000000..81ff14423aa --- /dev/null +++ b/ace/OS/Handle_Ops.cpp @@ -0,0 +1,41 @@ +// $Id$ + +#include "Handle_Ops.h" + +#if defined (ACE_LACKS_INLINE_FUNCTIONS) +#include "Handle_Ops.i" +#endif /* ACE_LACKS_INLINE_FUNCTIONS */ + +ACE_RCSID(ace, Handle_Ops, "$Id$") + +ACE_HANDLE +ACE_Handle_Ops::handle_timed_open (ACE_Time_Value *timeout, + const ACE_TCHAR *name, + int flags, + int perms) +{ + ACE_TRACE ("ACE_Handle_Ops::handle_timed_open"); + + if (timeout != 0) + { +#if !defined (ACE_WIN32) + // On Win32, ACE_NONBLOCK gets recognized as O_WRONLY so we + // don't use it there + flags |= ACE_NONBLOCK; +#endif /* ACE_WIN32 */ + + // Open the named pipe or file using non-blocking mode... + ACE_HANDLE handle = ACE_OS::open (name, + flags, + perms); + if (handle == ACE_INVALID_HANDLE + && (errno == EWOULDBLOCK + && (timeout->sec () > 0 || timeout->usec () > 0))) + // This expression checks if we were polling. + errno = ETIMEDOUT; + + return handle; + } + else + return ACE_OS::open (name, flags, perms); +} diff --git a/ace/OS/Handle_Ops.h b/ace/OS/Handle_Ops.h new file mode 100644 index 00000000000..f89af054d99 --- /dev/null +++ b/ace/OS/Handle_Ops.h @@ -0,0 +1,43 @@ + +//============================================================================= +/** + * @file Handle_Ops.h + * + * $Id$ + * + * This class consolidates the operations on the Handles. + * + * + * @author Priyanka Gontla + */ +//============================================================================= + + +#ifndef ACE_HANDLE_OPS_H +#define ACE_HANDLE_OPS_H +#include "ace/pre.h" + +#include "OS.h" + +class ACE_Export ACE_Handle_Ops +{ +public: + // = Operations on HANDLEs. + + /** + * Wait up to amount of time to actively open a device. + * This method doesn't perform the , it just does the timed + * wait... + */ + static ACE_HANDLE handle_timed_open (ACE_Time_Value *timeout, + const ACE_TCHAR *name, + int flags, + int perms); +}; + +#if !defined (ACE_LACKS_INLINE_FUNCTIONS) +#include "Handle_Ops.i" +#endif /* ACE_LACKS_INLINE_FUNCTIONS */ + +#include "ace/post.h" +#endif /* ACE_HANDLE_OPS_H */ diff --git a/ace/OS/Handle_Ops.i b/ace/OS/Handle_Ops.i new file mode 100644 index 00000000000..cfa1da318d3 --- /dev/null +++ b/ace/OS/Handle_Ops.i @@ -0,0 +1 @@ +// $Id$ diff --git a/ace/OS/Handle_Set.cpp b/ace/OS/Handle_Set.cpp new file mode 100644 index 00000000000..9528a2feff1 --- /dev/null +++ b/ace/OS/Handle_Set.cpp @@ -0,0 +1,558 @@ +// Handle_Set.cpp +// $Id$ + +#include "Handle_Set.h" + +#if 0 +#include "ace/Logging/Log_Msg.h" +#endif + +#if !defined (__ACE_INLINE__) +#include "Handle_Set.i" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID(ace, Handle_Set, "$Id$") + +ACE_ALLOC_HOOK_DEFINE(ACE_Handle_Set) + +#if defined (linux) && __GLIBC__ > 1 && __GLIBC_MINOR__ >= 1 && !defined (_XOPEN_SOURCE) + // XPG4.2 requires the fds_bits member name, so it is not enabled by + // default on Linux/glibc-2.1.x systems. Instead use "__fds_bits." + // Ugly, but "what are you going to do?" 8-) +#define fds_bits __fds_bits +#endif /* linux && __GLIBC__ > 1 && __GLIBC_MINOR__ >= 1 && !_GNU_SOURCE */ + +#if 0 +void +ACE_Handle_Set::dump (void) const +{ + ACE_TRACE ("ACE_Handle_Set::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nsize_ = %d"), this->size_)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nmax_handle_ = %d"), this->max_handle_)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n[ "))); + +#if defined (ACE_WIN32) + for (size_t i = 0; i < (size_t) this->mask_.fd_count + 1; i++) + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT (" %x "), this->mask_.fd_array[i])); +#else /* !ACE_WIN32 */ + for (ACE_HANDLE i = 0; i < this->max_handle_ + 1; i++) + if (this->is_set (i)) + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT (" %d "), i)); +#endif /* ACE_WIN32 */ + + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT (" ]\n"))); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} +#endif + +// Table that maps bytes to counts of the enabled bits in each value +// from 0 to 255, +// +// nbits_[0] == 0 +// +// because there are no bits enabled for the value 0. +// +// nbits_[5] == 2 +// +// because there are 2 bits enabled in the value 5, i.e., it's +// 101 in binary. + +const char ACE_Handle_Set::nbits_[256] = +{ + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8}; + +// Constructor, initializes the bitmask to all 0s. + +ACE_Handle_Set::ACE_Handle_Set (void) +{ + ACE_TRACE ("ACE_Handle_Set::ACE_Handle_Set"); + this->reset (); +} + +ACE_Handle_Set::ACE_Handle_Set (const ACE_FD_SET_TYPE &fd_mask) +{ + ACE_TRACE ("ACE_Handle_Set::ACE_Handle_Set"); + this->reset (); + ACE_OS::memcpy ((void *) &this->mask_, + (void *) &fd_mask, + sizeof this->mask_); +#if !defined (ACE_WIN32) + this->sync (ACE_Handle_Set::MAXSIZE); +#if defined (ACE_HAS_BIG_FD_SET) + this->min_handle_ = 0; +#endif /* ACE_HAS_BIG_FD_SET */ +#endif /* !ACE_WIN32 */ +} + +// Counts the number of bits enabled in N. Uses a table lookup to +// speed up the count. + +int +ACE_Handle_Set::count_bits (u_long n) +{ + + ACE_TRACE ("ACE_Handle_Set::count_bits"); +#if defined (ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT) + register int rval = 0; + + // Count the number of enabled bits in . This algorithm is very + // fast, i.e., O(enabled bits in n). + + for (register u_long m = n; + m != 0; + m &= m - 1) + rval++; + + return rval; +#else + return (ACE_Handle_Set::nbits_[n & 0xff] + + ACE_Handle_Set::nbits_[(n >> 8) & 0xff] + + ACE_Handle_Set::nbits_[(n >> 16) & 0xff] + + ACE_Handle_Set::nbits_[(n >> 24) & 0xff]); +#endif /* ACE_HAS_HANDLE_SET_OPTIMIZED_FOR_SELECT */ +} + +#if defined (ACE_HAS_BIG_FD_SET) +// Find the bit position counting from right to left worst case +// (1<<31) is 8. + +int +ACE_Handle_Set::bitpos (u_long bit) +{ + register int l = 0; + register u_long n = bit - 1; + + // This is a fast count method when have the most significative bit. + + while (n >> 8) + { + n >>= 8; + l += 8; + } + + // Is greater than 15? + if (n & 16) + { + n >>= 4; + l += 4; + } + + // Count number remaining bits. + while (n != 0) + { + n &= n - 1; + l++; + } + return l; +} +#endif /* ACE_HAS_BIG_FD_SET */ + +// Synchronize the underlying FD_SET with the MAX_FD and the SIZE. + +#if defined (ACE_USE_SHIFT_FOR_EFFICIENCY) +// These don't work because shifting right 3 bits is not the same as +// dividing by 3, e.g., dividing by 8 requires shifting right 3 bits. +// In order to do the shift, we need to calculate the number of bits +// at some point. +#define ACE_DIV_BY_WORDSIZE(x) ((x) >> ((int) ACE_Handle_Set::WORDSIZE)) +#define ACE_MULT_BY_WORDSIZE(x) ((x) << ((int) ACE_Handle_Set::WORDSIZE)) +#else +#define ACE_DIV_BY_WORDSIZE(x) ((x) / ((int) ACE_Handle_Set::WORDSIZE)) +#define ACE_MULT_BY_WORDSIZE(x) ((x) * ((int) ACE_Handle_Set::WORDSIZE)) +#endif /* ACE_USE_SHIFT_FOR_EFFICIENCY */ + +void +ACE_Handle_Set::sync (ACE_HANDLE max) +{ + ACE_TRACE ("ACE_Handle_Set::sync"); +#if !defined (ACE_WIN32) + fd_mask *maskp = (fd_mask *)(this->mask_.fds_bits); + this->size_ = 0; + + for (int i = ACE_DIV_BY_WORDSIZE (max - 1); + i >= 0; + i--) + this->size_ += ACE_Handle_Set::count_bits (maskp[i]); + + this->set_max (max); +#else + ACE_UNUSED_ARG (max); +#endif /* !ACE_WIN32 */ +} + +// Resets the MAX_FD after a clear of the original MAX_FD. + +void +ACE_Handle_Set::set_max (ACE_HANDLE current_max) +{ + ACE_TRACE ("ACE_Handle_Set::set_max"); +#if !defined(ACE_WIN32) + fd_mask * maskp = (fd_mask *)(this->mask_.fds_bits); + + if (this->size_ == 0) + this->max_handle_ = ACE_INVALID_HANDLE; + else + { + int i; + + for (i = ACE_DIV_BY_WORDSIZE (current_max - 1); + maskp[i] == 0; + i--) + continue; + +#if defined (ACE_PSOS) + this->max_handle_ = ACE_MULT_BY_WORDSIZE (i); + for (fd_mask val = maskp[i]; + (val & ACE_MSB_MASK) != 0; + val = (val << 1)) + this->max_handle_++; +#elif 1 /* !defined(ACE_HAS_BIG_FD_SET) */ + this->max_handle_ = ACE_MULT_BY_WORDSIZE (i); + for (fd_mask val = maskp[i]; + (val & ~1) != 0; // This obscure code is needed since "bit 0" is in location 1... + val = (val >> 1) & ACE_MSB_MASK) + this->max_handle_++; +#else + register u_long val = this->mask_.fds_bits[i]; + this->max_handle_ = ACE_MULT_BY_WORDSIZE (i) + + ACE_Handle_Set::bitpos(val & ~(val - 1)); +#endif /* 1 */ + } + + // Do some sanity checking... + if (this->max_handle_ >= ACE_Handle_Set::MAXSIZE) + this->max_handle_ = ACE_Handle_Set::MAXSIZE - 1; +#else + ACE_UNUSED_ARG (current_max); +#endif /* !ACE_WIN32 */ +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Handle_Set_Iterator) + +#if 0 +void +ACE_Handle_Set_Iterator::dump (void) const +{ + ACE_TRACE ("ACE_Handle_Set_Iterator::dump"); + + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); +#if defined(ACE_WIN32) || !defined(ACE_HAS_BIG_FD_SET) + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nhandle_index_ = %d"), this->handle_index_)); +#elif defined(ACE_HAS_BIG_FD_SET) + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nword_max_ = %d"), this->word_max_)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nword_val_ = %d"), this->word_val_)); +#endif + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nword_num_ = %d"), this->word_num_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +} +#endif + +ACE_HANDLE +ACE_Handle_Set_Iterator::operator () (void) +{ + ACE_TRACE ("ACE_Handle_Set_Iterator::operator"); +#if defined (ACE_WIN32) + if (this->handle_index_ < this->handles_.mask_.fd_count) + // Return the handle and advance the iterator. + return (ACE_HANDLE) this->handles_.mask_.fd_array[this->handle_index_++]; + else + return ACE_INVALID_HANDLE; + +#elif !defined (ACE_HAS_BIG_FD_SET) /* !ACE_WIN32 */ + // No sense searching further than the max_handle_ + 1; + ACE_HANDLE maxhandlep1 = this->handles_.max_handle_ + 1; + + // HP-UX 11 plays some games with the fd_mask type - fd_mask is + // defined as an int_32t, but the fds_bits is an array of longs. + // This makes plainly indexing through the array by hand tricky, + // since the FD_* macros treat the array as int32_t. So the bits + // are in the right place for int32_t, even though the array is + // long. This, they say, is to preserve the same in-memory layout + // for 32-bit and 64-bit processes. So, we play the same game as + // the FD_* macros to get the bits right. On all other systems, + // this amounts to practically a NOP, since this is what would have + // been done anyway, without all this type jazz. + fd_mask * maskp = (fd_mask *)(this->handles_.mask_.fds_bits); + + if (this->handle_index_ >= maxhandlep1) + // We've seen all the handles we're interested in seeing for this + // iterator. + return ACE_INVALID_HANDLE; + else + { + ACE_HANDLE result = this->handle_index_; + + // Increment the iterator and advance to the next bit in this + // word. + this->handle_index_++; +# if defined (ACE_PSOS) + this->word_val_ = (this->word_val_ << 1); +# else + this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK; +# endif /* ACE_PSOS */ + + // If we've examined all the bits in this word, we'll go onto + // the next word. + + if (this->word_val_ == 0) + { + // Start the handle_index_ at the beginning of the next word + // and then loop until we've found the first non-zero bit or + // we run past the of the bitset. + + for (this->handle_index_ = ACE_MULT_BY_WORDSIZE(++this->word_num_); + this->handle_index_ < maxhandlep1 + && maskp[this->word_num_] == 0; + this->word_num_++) + this->handle_index_ += ACE_Handle_Set::WORDSIZE; + + // If the bit index becomes >= the maxhandlep1 that means + // there weren't any more bits set that we want to consider. + // Therefore, we'll just store the maxhandlep1, which will + // cause to return + // immediately next time it's called. + if (this->handle_index_ >= maxhandlep1) + { + this->handle_index_ = maxhandlep1; + return result; + } + else + // Load the bits of the next word. + this->word_val_ = maskp[this->word_num_]; + } + + // Loop until we get to have its least significant + // bit enabled, keeping track of which this + // represents (this information is used by subsequent calls to + // ). + +# if defined (ACE_PSOS) // bits are in reverse order, MSB (sign bit) = bit 0. + for (; + this->word_val_ > 0; + this->word_val_ = (this->word_val_ << 1)) + this->handle_index_++; +# else + for (; + ACE_BIT_DISABLED (this->word_val_, 1); + this->handle_index_++) + this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK; +# endif /* ACE_PSOS */ + + return result; + } +#else /* !ACE_HAS_BIG_FD_SET */ + // Find the first word in fds_bits with bit on + register u_long lsb = this->word_val_; + + if (lsb == 0) + { + do + { + // We have exceeded the word count in Handle_Set? + if (++this->word_num_ >= this->word_max_) + return ACE_INVALID_HANDLE; + + lsb = this->handles_.mask_.fds_bits[this->word_num_]; + } + while (lsb == 0); + + // Set index to word boundary. + this->handle_index_ = ACE_MULT_BY_WORDSIZE(this->word_num_); + + // Put new word_val. + this->word_val_ = lsb; + + // Find the least significative bit. + lsb &= ~(lsb - 1); + + // Remove least significative bit. + this->word_val_ ^= lsb; + + // Save to calculate bit distance. + this->oldlsb_ = lsb; + + // Move index to least significative bit. + while (lsb >>= 1) + this->handle_index_++; + } + else + { + // Find the least significative bit. + lsb &= ~(lsb - 1); + + // Remove least significative bit. + this->word_val_ ^= lsb; + + register u_long n = lsb - this->oldlsb_; + + // Move index to bit distance between new lsb and old lsb. + do + { + this->handle_index_++; + n &= n >> 1; + } + while (n != 0); + + this->oldlsb_ = lsb; + } + + return this->handle_index_; +#endif /* ACE_WIN32 */ +} + +void +ACE_Handle_Set_Iterator::operator++ (void) +{ + ACE_TRACE ("ACE_Handle_Set_Iterator::operator++"); + + // This is now a no-op. +} + +ACE_Handle_Set_Iterator::ACE_Handle_Set_Iterator (const ACE_Handle_Set &hs) + : handles_ (hs), +#if !defined (ACE_HAS_BIG_FD_SET) || defined (ACE_WIN32) + handle_index_ (0), + word_num_ (-1) +#elif defined (ACE_HAS_BIG_FD_SET) + oldlsb_ (0), + word_max_ (hs.max_handle_ == ACE_INVALID_HANDLE + ? 0 + : ((ACE_DIV_BY_WORDSIZE (hs.max_handle_)) + 1)) +#endif /* ACE_HAS_BIG_FD_SET */ +{ + ACE_TRACE ("ACE_Handle_Set_Iterator::ACE_Handle_Set_Iterator"); +#if !defined (ACE_WIN32) && !defined (ACE_HAS_BIG_FD_SET) + // No sense searching further than the max_handle_ + 1; + ACE_HANDLE maxhandlep1 = + this->handles_.max_handle_ + 1; + + fd_mask *maskp = + (fd_mask *)(this->handles_.mask_.fds_bits); + + // Loop until we've found the first non-zero bit or we run past the + // of the bitset. + while (this->handle_index_ < maxhandlep1 + && maskp[++this->word_num_] == 0) + this->handle_index_ += ACE_Handle_Set::WORDSIZE; + + // If the bit index becomes >= the maxhandlep1 that means there + // weren't any bits set. Therefore, we'll just store the + // maxhandlep1, which will cause to return + // immediately. + if (this->handle_index_ >= maxhandlep1) + this->handle_index_ = maxhandlep1; + else + // Loop until we get to have its least significant bit + // enabled, keeping track of which this represents + // (this information is used by ). +# if defined (ACE_PSOS) // bits are in reverse order, MSB (sign bit) = bit 0. + for (this->word_val_ = maskp[this->word_num_]; + this->word_val_ > 0; + this->word_val_ = (this->word_val_ << 1)) + this->handle_index_++; +# else + for (this->word_val_ = maskp[this->word_num_]; + ACE_BIT_DISABLED (this->word_val_, 1) + && this->handle_index_ < maxhandlep1; + this->handle_index_++) + this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK; +# endif /* ACE_PSOS */ +#elif !defined (ACE_WIN32) && defined (ACE_HAS_BIG_FD_SET) + if (this->word_max_==0) + { + this->word_num_ = -1; + this->word_val_ = 0; + } + else + { + this->word_num_ = + ACE_DIV_BY_WORDSIZE (this->handles_.min_handle_) - 1; + this->word_val_ = 0; + } +#endif /* !ACE_WIN32 && !ACE_HAS_BIG_FD_SET */ +} + + +void +ACE_Handle_Set_Iterator::reset_state (void) +{ + ACE_TRACE ("ACE_Handle_Set_Iterator::reset_state"); + +#if !defined (ACE_HAS_BIG_FD_SET) || defined (ACE_WIN32) + this->handle_index_ = 0; + this->word_num_ = -1; +#elif defined (ACE_HAS_BIG_FD_SET) + this->oldlsb_ = 0; + this->word_max_ = + this->handles_.max_handle_ == ACE_INVALID_HANDLE ? 0 + : ((ACE_DIV_BY_WORDSIZE (this->handles_.max_handle_)) + 1); +#endif /* ACE_HAS_BIG_FD_SET */ + +#if !defined (ACE_WIN32) && !defined (ACE_HAS_BIG_FD_SET) + // No sense searching further than the max_handle_ + 1; + ACE_HANDLE maxhandlep1 = + this->handles_.max_handle_ + 1; + + fd_mask *maskp = + (fd_mask *)(this->handles_.mask_.fds_bits); + + // Loop until we've found the first non-zero bit or we run past the + // of the bitset. + while (this->handle_index_ < maxhandlep1 + && maskp[++this->word_num_] == 0) + this->handle_index_ += ACE_Handle_Set::WORDSIZE; + + // If the bit index becomes >= the maxhandlep1 that means there + // weren't any bits set. Therefore, we'll just store the + // maxhandlep1, which will cause to return + // immediately. + if (this->handle_index_ >= maxhandlep1) + this->handle_index_ = maxhandlep1; + else + // Loop until we get to have its least significant bit + // enabled, keeping track of which this represents + // (this information is used by ). +# if defined (ACE_PSOS) // bits are in reverse order, MSB (sign bit) = bit 0. + for (this->word_val_ = maskp[this->word_num_]; + this->word_val_ > 0; + this->word_val_ = (this->word_val_ << 1)) + this->handle_index_++; +# else + for (this->word_val_ = maskp[this->word_num_]; + ACE_BIT_DISABLED (this->word_val_, 1) + && this->handle_index_ < maxhandlep1; + this->handle_index_++) + this->word_val_ = (this->word_val_ >> 1) & ACE_MSB_MASK; +# endif /* ACE_PSOS */ +#elif !defined (ACE_WIN32) && defined (ACE_HAS_BIG_FD_SET) + if (this->word_max_==0) + { + this->word_num_ = -1; + this->word_val_ = 0; + } + else + { + this->word_num_ = + ACE_DIV_BY_WORDSIZE (this->handles_.min_handle_) - 1; + this->word_val_ = 0; + } +#endif /* !ACE_WIN32 && !ACE_HAS_BIG_FD_SET */ +} diff --git a/ace/OS/Handle_Set.h b/ace/OS/Handle_Set.h new file mode 100644 index 00000000000..a9a0d35a84d --- /dev/null +++ b/ace/OS/Handle_Set.h @@ -0,0 +1,229 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file Handle_Set.h + * + * $Id$ + * + * @author Douglas C. Schmidt + */ +//============================================================================= + +#ifndef ACE_HANDLE_SET_H +#define ACE_HANDLE_SET_H +#include "ace/pre.h" + +#include "OS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +/** + * @class ACE_Handle_Set + * + * @brief C++ wrapper facade for the socket abstraction. + * + * This abstraction is a very efficient wrapper facade over + * . In particular, no range checking is performed, so + * it's important not to set or clear bits that are outside the + * . + */ +class ACE_Export ACE_Handle_Set +{ +public: + friend class ACE_Handle_Set_Iterator; + + // = Initialization and termination. + + enum + { + MAXSIZE = ACE_DEFAULT_SELECT_REACTOR_SIZE + }; + + // = Initialization methods. + /// Constructor, initializes the bitmask to all 0s. + ACE_Handle_Set (void); + + /** + * Constructor, initializes the handle set from a given mask. + * is a based on the platform's native + * type used for masks passed to modifies the . + */ + void sync (ACE_HANDLE max); + + /// Returns a pointer to the underlying . Returns 0 if + /// there are no handle bits set ( == 0). + operator fd_set *(); + + /// Returns a pointer to the underlying . Returns 0 if + /// there are no handle bits set ( == 0). + fd_set *fdset (void); + +#if defined (ACE_HAS_BIG_FD_SET) + /// Assignment operator optimizes for cases where == 0. + ACE_Handle_Set & operator= (const ACE_Handle_Set &); +#endif /* ACE_HAS_BIG_FD_SET */ + + /// Dump the state of an object. + void dump (void) const; + + /// Declare the dynamic allocation hooks. + ACE_ALLOC_HOOK_DECLARE; + +private: + /// Size of the set, i.e., a count of the number of enabled bits. + int size_; + + /// Current max handle. + ACE_HANDLE max_handle_; + +#if defined (ACE_HAS_BIG_FD_SET) + /// Current min handle. + ACE_HANDLE min_handle_; +#endif /* ACE_HAS_BIG_FD_SET */ + + /// Bitmask. + fd_set mask_; + + enum + { + WORDSIZE = NFDBITS, +#if !defined (ACE_WIN32) + NUM_WORDS = howmany (MAXSIZE, NFDBITS), +#endif /* ACE_WIN32 */ + NBITS = 256 + }; + + /// Counts the number of bits enabled in N. Uses a table lookup to + /// speed up the count. + static int count_bits (u_long n); + +#if defined (ACE_HAS_BIG_FD_SET) + /// Find the position of the bit counting from right to left. + static int bitpos (u_long bit); +#endif /* ACE_HAS_BIG_FD_SET */ + + /// Resets the after a clear of the original + /// . + void set_max (ACE_HANDLE max); + + /// Table that maps bytes to counts of the enabled bits in each value + /// from 0 to 255. + static const char nbits_[NBITS]; +}; + +/** + * @class ACE_Handle_Set_Iterator + * + * @brief Iterator for the abstraction. + */ +class ACE_Export ACE_Handle_Set_Iterator +{ +public: + /// Constructor. + ACE_Handle_Set_Iterator (const ACE_Handle_Set &hs); + + /// Default dtor. + ~ACE_Handle_Set_Iterator (void); + + /// Reset the state of the iterator by reinitializing the state + /// that we maintain. + void reset_state (void); + + /** + * "Next" operator. Returns the next unseen in the + * up to ). When all the + * handles have been seen returns . Advances + * the iterator automatically, so you need not call + * (which is now obsolete). + */ + ACE_HANDLE operator () (void); + + /// This is a no-op and no longer does anything. It's only here for + /// backwards compatibility. + void operator++ (void); + + /// Dump the state of an object. + void dump (void) const; + + /// Declare the dynamic allocation hooks. + ACE_ALLOC_HOOK_DECLARE; + +private: + /// The we are iterating through. + const ACE_Handle_Set &handles_; + +#if defined (ACE_WIN32) + u_int handle_index_; +#elif !defined (ACE_HAS_BIG_FD_SET) + int handle_index_; +#elif defined (ACE_HAS_BIG_FD_SET) + int handle_index_; + u_long oldlsb_; +#endif /* ACE_WIN32 */ + // Index of the bit we're examining in the current word. + + /// Number of the word we're iterating over (typically between 0..7). + int word_num_; + +#if defined (ACE_HAS_BIG_FD_SET) + /// Number max of the words with a possible bit on. + int word_max_; +#endif /* ACE_HAS_BIG_FD_SET */ + +#if !defined (ACE_WIN32) && !defined (ACE_HAS_BIG_FD_SET) + /// Value of the bits in the word we're iterating on. + fd_mask word_val_; +#elif !defined (ACE_WIN32) && defined (ACE_HAS_BIG_FD_SET) + /// Value of the bits in the word we're iterating on. + u_long word_val_; +#endif /* !ACE_WIN32 && !ACE_HAS_BIG_FD_SET */ +}; + +#if defined (__ACE_INLINE__) +#include "Handle_Set.i" +#endif /* __ACE_INLINE__ */ + +#include "ace/post.h" +#endif /* ACE_HANDLE_SET */ diff --git a/ace/OS/Handle_Set.i b/ace/OS/Handle_Set.i new file mode 100644 index 00000000000..ce845d95279 --- /dev/null +++ b/ace/OS/Handle_Set.i @@ -0,0 +1,176 @@ +/* -*- C++ -*- */ +// $Id$ + +// Handle_Set.i + +// Initialize the bitmask to all 0s and reset the associated fields. + +#if defined (ACE_HAS_WINCE) +ACE_INLINE +ACE_Handle_Set::~ACE_Handle_Set (void) +{ + ACE_TRACE ("ACE_Handle_Set::~ACE_Handle_Set"); +} +#endif /* ACE_HAS_WINCE */ + +ACE_INLINE void +ACE_Handle_Set::reset (void) +{ + ACE_TRACE ("ACE_Handle_Set::reset"); + this->max_handle_ = + ACE_INVALID_HANDLE; +#if defined (ACE_HAS_BIG_FD_SET) + this->min_handle_ = + NUM_WORDS * WORDSIZE; +#endif /* ACE_HAS_BIG_FD_SET */ + this->size_ = 0; + // #if !defined (ACE_HAS_BIG_FD_SET) Why is this here? -Steve Huston + FD_ZERO (&this->mask_); + // #endif /* ACE_HAS_BIG_FD_SET */ +} + +#if defined (ACE_HAS_BIG_FD_SET) +ACE_INLINE ACE_Handle_Set & +ACE_Handle_Set::operator = (const ACE_Handle_Set &rhs) +{ + ACE_TRACE ("ACE_Handle_Set::operator ="); + + if (rhs.size_ > 0) + { + this->size_ = + rhs.size_; + this->max_handle_ = + rhs.max_handle_; + this->min_handle_ = + rhs.min_handle_; + this->mask_ = + rhs.mask_; + } + else + this->reset (); + + return *this; +} +#endif /* ACE_HAS_BIG_FD_SET */ + +// Returns the number of the large bit. + +ACE_INLINE ACE_HANDLE +ACE_Handle_Set::max_set (void) const +{ + ACE_TRACE ("ACE_Handle_Set::max_set"); + return this->max_handle_; +} + +// Checks whether handle is enabled. + +ACE_INLINE int +ACE_Handle_Set::is_set (ACE_HANDLE handle) const +{ + ACE_TRACE ("ACE_Handle_Set::is_set"); +#if defined (ACE_HAS_BIG_FD_SET) + return FD_ISSET (handle, + &this->mask_) + && this->size_ > 0; +#else + return FD_ISSET (handle, + &this->mask_); +#endif /* ACE_HAS_BIG_FD_SET */ +} + +// Enables the handle. + +ACE_INLINE void +ACE_Handle_Set::set_bit (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_Handle_Set::set_bit"); + if ((handle != ACE_INVALID_HANDLE) + && (!this->is_set (handle))) + { +#if defined (ACE_WIN32) + FD_SET ((SOCKET) handle, + &this->mask_); + this->size_++; +#else /* ACE_WIN32 */ +#if defined (ACE_HAS_BIG_FD_SET) + if (this->size_ == 0) + FD_ZERO (&this->mask_); + + if (handle < this->min_handle_) + this->min_handle_ = handle; +#endif /* ACE_HAS_BIG_FD_SET */ + + FD_SET (handle, + &this->mask_); + this->size_++; + + if (handle > this->max_handle_) + this->max_handle_ = handle; +#endif /* ACE_WIN32 */ + } +} + +// Disables the handle. + +ACE_INLINE void +ACE_Handle_Set::clr_bit (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_Handle_Set::clr_bit"); + + if ((handle != ACE_INVALID_HANDLE) && + (this->is_set (handle))) + { + FD_CLR ((ACE_SOCKET) handle, + &this->mask_); + this->size_--; + +#if !defined (ACE_WIN32) + if (handle == this->max_handle_) + this->set_max (this->max_handle_); +#endif /* !ACE_WIN32 */ + } +} + +// Returns a count of the number of enabled bits. + +ACE_INLINE int +ACE_Handle_Set::num_set (void) const +{ + ACE_TRACE ("ACE_Handle_Set::num_set"); +#if defined (ACE_WIN32) + return this->mask_.fd_count; +#else /* !ACE_WIN32 */ + return this->size_; +#endif /* ACE_WIN32 */ +} + +// Returns a pointer to the underlying fd_set. + +ACE_INLINE +ACE_Handle_Set::operator fd_set *() +{ + ACE_TRACE ("ACE_Handle_Set::operator fd_set *"); + + if (this->size_ > 0) + return (fd_set *) &this->mask_; + else + return (fd_set *) NULL; +} + +// Returns a pointer to the underlying fd_set. + +ACE_INLINE fd_set * +ACE_Handle_Set::fdset (void) +{ + ACE_TRACE ("ACE_Handle_Set::fdset"); + + if (this->size_ > 0) + return (fd_set *) &this->mask_; + else + return (fd_set *) NULL; +} + +ACE_INLINE +ACE_Handle_Set_Iterator::~ACE_Handle_Set_Iterator (void) +{ +} diff --git a/ace/OS/Init_ACE.cpp b/ace/OS/Init_ACE.cpp new file mode 100644 index 00000000000..d40ba6fbfb9 --- /dev/null +++ b/ace/OS/Init_ACE.cpp @@ -0,0 +1,44 @@ +// $Id$ + +#include "Init_ACE.h" + +#include "ace/Utils/Object_Manager.h" + +#if defined (ACE_LACKS_INLINE_FUNCTIONS) +#include "Init_ACE.i" +#endif /* ACE_LACKS_INLINE_FUNCTIONS */ + +ACE_RCSID(ace, Init_ACE, "$Id$") + + // Static data members. + u_int ACE_Init_ACE::init_fini_count_ = 0; +int +ACE_Init_ACE::init (void) +{ + // Don't use ACE_TRACE, because Object_Manager might not have been + // instantiated yet. + // ACE_TRACE ("ACE_Init_ACE::init"); + + ++init_fini_count_; + + return ACE_Object_Manager::instance ()->init (); +} + +int +ACE_Init_ACE::fini (void) +{ + ACE_TRACE ("ACE_Init_ACE::fini"); + + if (init_fini_count_ > 0) + { + if (--init_fini_count_ == 0) + return ACE_Object_Manager::instance ()->fini (); + else + // Wait for remaining fini () calls. + return 1; + } + else + // More ACE_Init_ACE::fini () calls than ACE_Init_ACE::init () calls. Bad + // application! + return -1; +} diff --git a/ace/OS/Init_ACE.h b/ace/OS/Init_ACE.h new file mode 100644 index 00000000000..b383faf799d --- /dev/null +++ b/ace/OS/Init_ACE.h @@ -0,0 +1,65 @@ + +//============================================================================= +/** + * @file Init_ACE.h + * + * $Id$ + * + * This class consolidates the operations on the Handles. + * + * + * @author Priyanka Gontla + */ +//============================================================================= + + +#ifndef ACE_INIT_ACE_H +#define ACE_INIT_ACE_H +#include "ace/pre.h" + +#include "OS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +/** + * @class ACE_Init_ACE + * + * @brief Initialize ACE library services. Can be called only once + * per program invocation. + * + */ +class ACE_Export ACE_Init_ACE +{ +public: + /// Returns 0 on success, -1 on failure, and 1 if it had already been called. + /** + * This class implements the fucntions for the initialization and + * shutting down ACE. These functions are called only once per ACE + * invokation. + */ + static int init (void); + + /// Returns 0 on success, -1 on failure, and 1 if it had already been called. + /** + * Shut down ACE library services. Can be called only once per + * program invocation. + */ + static int fini (void); + +private: + /** + * Counter to match / calls. must increment it; + * must decrement it. then does nothing until it + * reaches 0. + */ + static u_int init_fini_count_; +}; + +#if !defined (ACE_LACKS_INLINE_FUNCTIONS) +#include "Init_ACE.i" +#endif /* ACE_LACKS_INLINE_FUNCTIONS */ + +#include "ace/post.h" +#endif /* ACE_INIT_ACE_H */ diff --git a/ace/OS/Init_ACE.i b/ace/OS/Init_ACE.i new file mode 100644 index 00000000000..cfa1da318d3 --- /dev/null +++ b/ace/OS/Init_ACE.i @@ -0,0 +1 @@ +// $Id$ diff --git a/ace/OS/Makefile b/ace/OS/Makefile new file mode 100644 index 00000000000..72d06ca2e30 --- /dev/null +++ b/ace/OS/Makefile @@ -0,0 +1,69 @@ +# $Id$ + +#---------------------------------------------------------------------------- +# Makefile for the libACE_OS +#---------------------------------------------------------------------------- + +MAKEFILE = Makefile +LIBOS = libACE_OS +LIB = $(LIBOS).a +SHLIB = $(LIBOS).$(SOEXT) + + +OS_FILES = \ + Base_Thread_Adapter\ + Basic_Types\ + Date_Time\ + gethrtime\ + Handle_Ops\ + Handle_Set\ + Init_ACE\ + OS\ + OS_Dirent\ + OS_Errno\ + OS_Log_Msg_Attributes\ + OS_Memory\ + OS_QoS\ + OS_String\ + OS_Thread_Adapter\ + OS_TLI\ + Sched_Params\ + Thread_Hook + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- + +include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU + +#### +#### ACE_COMPONENTS support. +#### +FILES += $(OS_FILES) + +LSRC = $(addsuffix .cpp,$(FILES)) + +include $(ACE_ROOT)/include/makeinclude/macros.GNU +include $(ACE_ROOT)/include/makeinclude/rules.common.GNU +include $(ACE_ROOT)/include/makeinclude/rules.nested.GNU +include $(ACE_ROOT)/include/makeinclude/rules.lib.GNU +include $(ACE_ROOT)/include/makeinclude/rules.local.GNU + +INSTALL = + +clean: + $(RM) -f libACE_OS.a libACE_OS.so + +#---------------------------------------------------------------------------- +# Local targets +#---------------------------------------------------------------------------- + + + +#---------------------------------------------------------------------------- +# Dependencies +#---------------------------------------------------------------------------- +# DO NOT DELETE THIS LINE -- g++dep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + + diff --git a/ace/OS/OS.cpp b/ace/OS/OS.cpp new file mode 100644 index 00000000000..3aa48fb3ef6 --- /dev/null +++ b/ace/OS/OS.cpp @@ -0,0 +1,7972 @@ +// $Id$ + +#include "OS.h" +#include "Sched_Params.h" +#include "OS_Thread_Adapter.h" +#include "OS_QoS.h" + +// Perhaps we should *always* include ace/OS.i in order to make sure +// we can always link against the OS symbols? +#if !defined (ACE_HAS_INLINED_OSCALLS) +# include "OS.i" +#endif /* ACE_HAS_INLINED_OS_CALLS */ + +ACE_RCSID(ace, OS, "$Id$") + +#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) +# if defined (ACE_HAS_WINCE) +const wchar_t *ACE_OS::day_of_week_name[] = {ACE_LIB_TEXT ("Sun"), ACE_LIB_TEXT ("Mon"), + ACE_LIB_TEXT ("Tue"), ACE_LIB_TEXT ("Wed"), + ACE_LIB_TEXT ("Thu"), ACE_LIB_TEXT ("Fri"), + ACE_LIB_TEXT ("Sat")}; +const wchar_t *ACE_OS::month_name[] = {ACE_LIB_TEXT ("Jan"), ACE_LIB_TEXT ("Feb"), + ACE_LIB_TEXT ("Mar"), ACE_LIB_TEXT ("Apr"), + ACE_LIB_TEXT ("May"), ACE_LIB_TEXT ("Jun"), + ACE_LIB_TEXT ("Jul"), ACE_LIB_TEXT ("Aug"), + ACE_LIB_TEXT ("Sep"), ACE_LIB_TEXT ("Oct"), + ACE_LIB_TEXT ("Nov"), ACE_LIB_TEXT ("Dec") }; + +static const ACE_TCHAR *ACE_OS_CTIME_R_FMTSTR = ACE_LIB_TEXT ("%3s %3s %02d %02d:%02d:%02d %04d\n"); +# endif /* ACE_HAS_WINCE */ + +# if defined (ACE_WIN32) +OSVERSIONINFO ACE_OS::win32_versioninfo_; +// Cached win32 version information. + +HINSTANCE ACE_OS::win32_resource_module_; + +# if defined (ACE_OS_HAS_DLL) && (ACE_OS_HAS_DLL == 1) && !defined (ACE_HAS_WINCE) +// This function is called by the OS when the ACE DLL is loaded. We +// use it to determine the default module containing ACE's resources. +BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID) +{ + if (reason == DLL_PROCESS_ATTACH) + ACE_OS::set_win32_resource_module(instance); + return TRUE; +} +# endif /* ACE_OS_HAS_DLL && ACE_OS_HAS_DLL == 1 */ +# endif /* ACE_WIN32 */ + +class ACE_OS_Thread_Mutex_Guard +{ + // = TITLE + // This data structure is meant to be used within an ACE_OS + // function. It performs automatic aquisition and release of + // an ACE_thread_mutex_t. + // + // = DESCRIPTION + // For internal use only by ACE_OS. +public: + ACE_OS_Thread_Mutex_Guard (ACE_thread_mutex_t &m); + // Implicitly and automatically acquire the lock. + + ~ACE_OS_Thread_Mutex_Guard (void); + // Implicitly release the lock. + + int acquire (void); + // Explicitly acquire the lock. + + int release (void); + // Explicitly release the lock. + +protected: + ACE_thread_mutex_t &lock_; + // Reference to the mutex. + + int owner_; + // Keeps track of whether we acquired the lock or failed. + + // = Prevent assignment and initialization. + ACE_OS_Thread_Mutex_Guard &operator= (const ACE_OS_Thread_Mutex_Guard &); + ACE_OS_Thread_Mutex_Guard (const ACE_OS_Thread_Mutex_Guard &); +}; + +#if defined (ACE_IS_SPLITTING) +# define ACE_SPECIAL_INLINE +#else +# define ACE_SPECIAL_INLINE inline +#endif + +ACE_SPECIAL_INLINE +int +ACE_OS_Thread_Mutex_Guard::acquire (void) +{ + return owner_ = ACE_OS::thread_mutex_lock (&lock_); +} + +ACE_SPECIAL_INLINE +int +ACE_OS_Thread_Mutex_Guard::release (void) +{ + if (owner_ == -1) + return 0; + else + { + owner_ = -1; + return ACE_OS::thread_mutex_unlock (&lock_); + } +} + +ACE_SPECIAL_INLINE +ACE_OS_Thread_Mutex_Guard::ACE_OS_Thread_Mutex_Guard (ACE_thread_mutex_t &m) + : lock_ (m) +{ + acquire (); +} + +ACE_OS_Thread_Mutex_Guard::~ACE_OS_Thread_Mutex_Guard () +{ + release (); +} + +class ACE_OS_Recursive_Thread_Mutex_Guard +{ + // = TITLE + // This data structure is meant to be used within an ACE_OS + // function. It performs automatic aquisition and release of + // an ACE_recursive_thread_mutex_t. + // + // = DESCRIPTION + // For internal use only by ACE_OS. +public: + ACE_OS_Recursive_Thread_Mutex_Guard (ACE_recursive_thread_mutex_t &m); + // Implicitly and automatically acquire the lock. + + ~ACE_OS_Recursive_Thread_Mutex_Guard (void); + // Implicitly release the lock. + + int acquire (void); + // Explicitly acquire the lock. + + int release (void); + // Explicitly release the lock. + +protected: + ACE_recursive_thread_mutex_t &lock_; + // Reference to the mutex. + + int owner_; + // Keeps track of whether we acquired the lock or failed. + + // = Prevent assignment and initialization. + ACE_OS_Recursive_Thread_Mutex_Guard &operator= ( + const ACE_OS_Recursive_Thread_Mutex_Guard &); + ACE_OS_Recursive_Thread_Mutex_Guard ( + const ACE_OS_Recursive_Thread_Mutex_Guard &); +}; + +ACE_SPECIAL_INLINE +int +ACE_OS_Recursive_Thread_Mutex_Guard::acquire (void) +{ + return owner_ = ACE_OS::recursive_mutex_lock (&lock_); +} + +ACE_SPECIAL_INLINE +int +ACE_OS_Recursive_Thread_Mutex_Guard::release (void) +{ + if (owner_ == -1) + return 0; + else + { + owner_ = -1; + return ACE_OS::recursive_mutex_unlock (&lock_); + } +} + +ACE_SPECIAL_INLINE +ACE_OS_Recursive_Thread_Mutex_Guard::ACE_OS_Recursive_Thread_Mutex_Guard ( + ACE_recursive_thread_mutex_t &m) + : lock_ (m), + owner_ (-1) +{ + acquire (); +} + +ACE_OS_Recursive_Thread_Mutex_Guard::~ACE_OS_Recursive_Thread_Mutex_Guard () +{ + release (); +} + +#define ACE_OS_GUARD \ + ACE_OS_Thread_Mutex_Guard ace_os_guard__ (*(ACE_thread_mutex_t *) \ + ACE_OS_Object_Manager::preallocated_object[ \ + ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]); + +#define ACE_TSS_CLEANUP_GUARD \ + ACE_OS_Recursive_Thread_Mutex_Guard ace_tss_cleanup_guard__ (*(ACE_recursive_thread_mutex_t *) \ + ACE_OS_Object_Manager::preallocated_object[ \ + ACE_OS_Object_Manager::ACE_TSS_CLEANUP_LOCK]); + +#define ACE_TSS_BASE_GUARD \ + ACE_OS_Recursive_Thread_Mutex_Guard ace_tss_base_guard__ (*(ACE_recursive_thread_mutex_t *) \ + ACE_OS_Object_Manager::preallocated_object[ \ + ACE_OS_Object_Manager::ACE_TSS_BASE_LOCK]); + + +# if defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) +int +ACE_OS::netdb_acquire (void) +{ + return ACE_OS::thread_mutex_lock ((ACE_thread_mutex_t *) + ACE_OS_Object_Manager::preallocated_object[ + ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]); +} + +int +ACE_OS::netdb_release (void) +{ + return ACE_OS::thread_mutex_unlock ((ACE_thread_mutex_t *) + ACE_OS_Object_Manager::preallocated_object[ + ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]); +} +# endif /* defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) */ +#else /* ! ACE_MT_SAFE */ +# define ACE_OS_GUARD +# define ACE_TSS_CLEANUP_GUARD +# define ACE_TSS_BASE_GUARD +#endif /* ! ACE_MT_SAFE */ + +ACE_EXIT_HOOK ACE_OS::exit_hook_ = 0; + +// Static constant representing `zero-time'. +// Note: this object requires static construction. +const ACE_Time_Value ACE_Time_Value::zero; + +// Constant for maximum time representable. Note that this time +// is not intended for use with select () or other calls that may +// have *their own* implementation-specific maximum time representations. +// Its primary use is in time computations such as those used by the +// dynamic subpriority strategies in the ACE_Dynamic_Message_Queue class. +// Note: this object requires static construction. +const ACE_Time_Value ACE_Time_Value::max_time (LONG_MAX, + ACE_ONE_SECOND_IN_USECS - 1); + +ACE_ALLOC_HOOK_DEFINE(ACE_Time_Value) + +// Increment microseconds (the only reason this is here is to allow +// the use of ACE_Atomic_Op with ACE_Time_Value). + +ACE_Time_Value +ACE_Time_Value::operator ++ (int) +{ + ACE_OS_TRACE ("ACE_Time_Value::operator ++ (int)"); + usec (usec () + 1); + normalize (); + return *this; +} + +ACE_Time_Value & +ACE_Time_Value::operator ++ (void) +{ + ACE_OS_TRACE ("ACE_Time_Value::operator ++ (void)"); + usec (usec () + 1); + normalize (); + return *this; +} + +// Decrement microseconds (the only reason this is here is / to allow +// the use of ACE_Atomic_Op with ACE_Time_Value). + +ACE_Time_Value +ACE_Time_Value::operator -- (int) +{ + ACE_OS_TRACE ("ACE_Time_Value::operator -- (int)"); + usec (usec () - 1); + normalize (); + return *this; +} + +ACE_Time_Value & +ACE_Time_Value::operator -- (void) +{ + ACE_OS_TRACE ("ACE_Time_Value::operator -- (void)"); + usec (usec () - 1); + normalize (); + return *this; +} + +#if defined (ACE_WIN32) +// Static constant to remove time skew between FILETIME and POSIX +// time. POSIX and Win32 use different epochs (Jan. 1, 1970 v.s. +// Jan. 1, 1601). The following constant defines the difference +// in 100ns ticks. +// +// In the beginning (Jan. 1, 1601), there was no time and no computer. +// And Bill said: "Let there be time," and there was time.... +# if defined (ACE_LACKS_LONGLONG_T) +const ACE_U_LongLong ACE_Time_Value::FILETIME_to_timval_skew = +ACE_U_LongLong (0xd53e8000, 0x19db1de); +# else +const DWORDLONG ACE_Time_Value::FILETIME_to_timval_skew = +ACE_INT64_LITERAL (0x19db1ded53e8000); +# endif + +// Initializes the ACE_Time_Value object from a Win32 FILETIME + +ACE_Time_Value::ACE_Time_Value (const FILETIME &file_time) +{ + // ACE_OS_TRACE ("ACE_Time_Value::ACE_Time_Value"); + this->set (file_time); +} + +void ACE_Time_Value::set (const FILETIME &file_time) +{ + // Initializes the ACE_Time_Value object from a Win32 FILETIME +#if defined (ACE_LACKS_LONGLONG_T) + ACE_U_LongLong LL_100ns(file_time.dwLowDateTime, file_time.dwHighDateTime); + LL_100ns -= ACE_Time_Value::FILETIME_to_timval_skew; + // Convert 100ns units to seconds; + this->tv_.tv_sec = (long) (LL_100ns / ((double) (10000 * 1000))); + // Convert remainder to microseconds; + this->tv_.tv_usec = (long)((LL_100ns % ((ACE_UINT32)(10000 * 1000))) / 10); +#else + // Don't use a struct initializer, gcc don't like it. + ULARGE_INTEGER _100ns; + _100ns.LowPart = file_time.dwLowDateTime; + _100ns.HighPart = file_time.dwHighDateTime; + + _100ns.QuadPart -= ACE_Time_Value::FILETIME_to_timval_skew; + + // Convert 100ns units to seconds; + this->tv_.tv_sec = (long) (_100ns.QuadPart / (10000 * 1000)); + // Convert remainder to microseconds; + this->tv_.tv_usec = (long) ((_100ns.QuadPart % (10000 * 1000)) / 10); +#endif // ACE_LACKS_LONGLONG_T +} + +// Returns the value of the object as a Win32 FILETIME. + +ACE_Time_Value::operator FILETIME () const +{ + FILETIME file_time; + ACE_OS_TRACE ("ACE_Time_Value::operator FILETIME"); + +#if defined (ACE_LACKS_LONGLONG_T) + ACE_U_LongLong LL_sec(this->tv_.tv_sec); + ACE_U_LongLong LL_usec(this->tv_.tv_usec); + ACE_U_LongLong LL_100ns = LL_sec * (ACE_UINT32)(10000 * 1000) + + LL_usec * (ACE_UINT32)10 + + ACE_Time_Value::FILETIME_to_timval_skew; + file_time.dwLowDateTime = LL_100ns.lo(); + file_time.dwHighDateTime = LL_100ns.hi(); +#else + ULARGE_INTEGER _100ns; + _100ns.QuadPart = (((DWORDLONG) this->tv_.tv_sec * (10000 * 1000) + + this->tv_.tv_usec * 10) + + ACE_Time_Value::FILETIME_to_timval_skew); + + file_time.dwLowDateTime = _100ns.LowPart; + file_time.dwHighDateTime = _100ns.HighPart; +#endif //ACE_LACKS_LONGLONG_T + + return file_time; +} + +#endif /* ACE_WIN32 */ + +ACE_Cleanup_Info::ACE_Cleanup_Info (void) + : object_ (0), + cleanup_hook_ (0), + param_ (0) +{ +} + +int +ACE_Cleanup_Info::operator== (const ACE_Cleanup_Info &o) const +{ + return o.object_ == this->object_ + && o.cleanup_hook_ == this->cleanup_hook_ + && o.param_ == this->param_; +} + +int +ACE_Cleanup_Info::operator!= (const ACE_Cleanup_Info &o) const +{ + return !(*this == o); +} + +class ACE_Cleanup_Info_Node +{ + // = TITLE + // For maintaining a list of ACE_Cleanup_Info items. + // + // = DESCRIPTION + // For internal use by ACE_Object_Manager. +public: + ACE_Cleanup_Info_Node (void); + ACE_Cleanup_Info_Node (const ACE_Cleanup_Info &new_info, + ACE_Cleanup_Info_Node *next); + ~ACE_Cleanup_Info_Node (void); + ACE_Cleanup_Info_Node *insert (const ACE_Cleanup_Info &); +private: + ACE_Cleanup_Info cleanup_info_; + ACE_Cleanup_Info_Node *next_; + + friend class ACE_OS_Exit_Info; +}; + +ACE_Cleanup_Info_Node::ACE_Cleanup_Info_Node (void) + : cleanup_info_ (), + next_ (0) +{ +} + +ACE_Cleanup_Info_Node::ACE_Cleanup_Info_Node (const ACE_Cleanup_Info &new_info, + ACE_Cleanup_Info_Node *next) + : cleanup_info_ (new_info), + next_ (next) +{ +} + +ACE_Cleanup_Info_Node::~ACE_Cleanup_Info_Node (void) +{ + delete next_; +} + +ACE_Cleanup_Info_Node * +ACE_Cleanup_Info_Node::insert (const ACE_Cleanup_Info &new_info) +{ + ACE_Cleanup_Info_Node *new_node; + + ACE_NEW_RETURN (new_node, + ACE_Cleanup_Info_Node (new_info, this), + 0); + + return new_node; +} + +ACE_OS_Exit_Info::ACE_OS_Exit_Info (void) +{ + ACE_NEW (registered_objects_, ACE_Cleanup_Info_Node); +} + +ACE_OS_Exit_Info::~ACE_OS_Exit_Info (void) +{ + delete registered_objects_; + registered_objects_ = 0; +} + +int +ACE_OS_Exit_Info::at_exit_i (void *object, + ACE_CLEANUP_FUNC cleanup_hook, + void *param) +{ + ACE_Cleanup_Info new_info; + new_info.object_ = object; + new_info.cleanup_hook_ = cleanup_hook; + new_info.param_ = param; + + // Return -1 and sets errno if unable to allocate storage. Enqueue + // at the head and dequeue from the head to get LIFO ordering. + + ACE_Cleanup_Info_Node *new_node; + + if ((new_node = registered_objects_->insert (new_info)) == 0) + return -1; + else + { + registered_objects_ = new_node; + return 0; + } +} + +int +ACE_OS_Exit_Info::find (void *object) +{ + // Check for already in queue, and return 1 if so. + for (ACE_Cleanup_Info_Node *iter = registered_objects_; + iter && iter->next_ != 0; + iter = iter->next_) + { + if (iter->cleanup_info_.object_ == object) + { + // The object has already been registered. + return 1; + } + } + + return 0; +} + +void +ACE_OS_Exit_Info::call_hooks () +{ + // Call all registered cleanup hooks, in reverse order of + // registration. + for (ACE_Cleanup_Info_Node *iter = registered_objects_; + iter && iter->next_ != 0; + iter = iter->next_) + { + ACE_Cleanup_Info &info = iter->cleanup_info_; + if (info.cleanup_hook_ == ACE_reinterpret_cast (ACE_CLEANUP_FUNC, + ace_cleanup_destroyer)) + // The object is an ACE_Cleanup. + ace_cleanup_destroyer (ACE_reinterpret_cast (ACE_Cleanup *, + info.object_), + info.param_); + else if (info.object_ == &ace_exit_hook_marker) + // The hook is an ACE_EXIT_HOOK. + (* ACE_reinterpret_cast (ACE_EXIT_HOOK, info.cleanup_hook_)) (); + else + (*info.cleanup_hook_) (info.object_, info.param_); + } +} + +void +ACE_Time_Value::dump (void) const +{ + ACE_OS_TRACE ("ACE_Time_Value::dump"); +#if 0 + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ntv_sec_ = %d"), this->tv_.tv_sec)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ntv_usec_ = %d\n"), this->tv_.tv_usec)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +#endif /* 0 */ +} + +void +ACE_Time_Value::normalize (void) +{ + // ACE_OS_TRACE ("ACE_Time_Value::normalize"); + // New code from Hans Rohnert... + + if (this->tv_.tv_usec >= ACE_ONE_SECOND_IN_USECS) + { + do + { + this->tv_.tv_sec++; + this->tv_.tv_usec -= ACE_ONE_SECOND_IN_USECS; + } + while (this->tv_.tv_usec >= ACE_ONE_SECOND_IN_USECS); + } + else if (this->tv_.tv_usec <= -ACE_ONE_SECOND_IN_USECS) + { + do + { + this->tv_.tv_sec--; + this->tv_.tv_usec += ACE_ONE_SECOND_IN_USECS; + } + while (this->tv_.tv_usec <= -ACE_ONE_SECOND_IN_USECS); + } + + if (this->tv_.tv_sec >= 1 && this->tv_.tv_usec < 0) + { + this->tv_.tv_sec--; + this->tv_.tv_usec += ACE_ONE_SECOND_IN_USECS; + } + else if (this->tv_.tv_sec < 0 && this->tv_.tv_usec > 0) + { + this->tv_.tv_sec++; + this->tv_.tv_usec -= ACE_ONE_SECOND_IN_USECS; + } +} + +ACE_Countdown_Time::ACE_Countdown_Time (ACE_Time_Value *max_wait_time) + : max_wait_time_ (max_wait_time), + stopped_ (0) +{ + this->start (); +} + +ACE_Countdown_Time::~ACE_Countdown_Time (void) +{ + this->stop (); +} + +#if defined (ACE_HAS_POWERPC_TIMER) && defined (ghs) +void +ACE_OS::readPPCTimeBase (u_long &most, u_long &least) +{ + ACE_OS_TRACE ("ACE_OS::readPPCTimeBase"); + + // This function can't be inline because it depends on the arguments + // being in particular registers (r3 and r4), in conformance with the + // EABI standard. It would be nice if we knew how to put the variable + // names directly into the assembler instructions . . . + asm("aclock:"); + asm("mftb r5,TBU"); + asm("mftb r6,TBL"); + asm("mftb r7,TBU"); + asm("cmpw r5,r7"); + asm("bne aclock"); + + asm("stw r5, 0(r3)"); + asm("stw r6, 0(r4)"); +} +#elif defined (ACE_HAS_POWERPC_TIMER) && defined (__GNUG__) +void +ACE_OS::readPPCTimeBase (u_long &most, u_long &least) +{ + ACE_OS_TRACE ("ACE_OS::readPPCTimeBase"); + + // This function can't be inline because it defines a symbol, + // aclock. If there are multiple calls to the function in a + // compilation unit, then that symbol would be multiply defined if + // the function was inline. + asm volatile ("aclock:\n" + "mftbu 5\n" /* upper time base register */ + "mftb 6\n" /* lower time base register */ + "mftbu 7\n" /* upper time base register */ + "cmpw 5,7\n" /* check for rollover of upper */ + "bne aclock\n" + "stw 5,%0\n" /* most */ + "stw 6,%1" /* least */ + : "=m" (most), "=m" (least) /* outputs */ + : /* no inputs */ + : "5", "6", "7", "memory" /* constraints */); +} +#endif /* ACE_HAS_POWERPC_TIMER && (ghs or __GNUG__) */ + +#if defined (ACE_WIN32) || defined (VXWORKS) || defined (CHORUS) || defined (ACE_PSOS) +// Don't inline on those platforms because this function contains +// string literals, and some compilers, e.g., g++, don't handle those +// efficiently in unused inline functions. +int +ACE_OS::uname (ACE_utsname *name) +{ + ACE_OS_TRACE ("ACE_OS::uname"); +# if defined (ACE_WIN32) + size_t maxnamelen = sizeof name->nodename; + ACE_OS::strcpy (name->sysname, + ACE_LIB_TEXT ("Win32")); + + OSVERSIONINFO vinfo; + vinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + ::GetVersionEx (&vinfo); + + SYSTEM_INFO sinfo; +# if defined (ACE_HAS_PHARLAP) + // PharLap doesn't do GetSystemInfo. What's really wanted is the + // CPU architecture, so we can get that with EtsGetSystemInfo. Fill + // in what's wanted in the SYSTEM_INFO structure, and carry on. Note + // that the CPU type values in EK_KERNELINFO have the same values + // are the ones defined for SYSTEM_INFO. + EK_KERNELINFO ets_kern; + EK_SYSTEMINFO ets_sys; + EtsGetSystemInfo (&ets_kern, &ets_sys); + sinfo.wProcessorLevel = ACE_static_cast (WORD, ets_kern.CpuType); + sinfo.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL; + sinfo.dwProcessorType = ets_kern.CpuType * 100 + 86; +# else + ::GetSystemInfo(&sinfo); + + ACE_OS::strcpy (name->sysname, ACE_LIB_TEXT ("Win32")); +# endif /* ACE_HAS_PHARLAP */ + + const ACE_TCHAR* unknown = ACE_LIB_TEXT ("???"); + + if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + // Get information from the two structures + ACE_OS::sprintf (name->release, +# if defined (ACE_HAS_WINCE) + ACE_LIB_TEXT ("Windows CE %d.%d"), +# else + ACE_LIB_TEXT ("Windows NT %d.%d"), +# endif /* ACE_HAS_WINCE */ + (int) vinfo.dwMajorVersion, + (int) vinfo.dwMinorVersion); + ACE_OS::sprintf (name->version, + ACE_LIB_TEXT ("Build %d %s"), + (int) vinfo.dwBuildNumber, + vinfo.szCSDVersion); + + // We have to make sure that the size of (processor + subtype) + // is not greater than the size of name->machine. So we give + // half the space to the processor and half the space to + // subtype. The -1 is necessary for because of the space + // between processor and subtype in the machine name. + const int bufsize = ((sizeof (name->machine) / sizeof (ACE_TCHAR)) / 2) - 1; + ACE_TCHAR processor[bufsize] = ACE_LIB_TEXT ("Unknown"); + ACE_TCHAR subtype[bufsize] = ACE_LIB_TEXT ("Unknown"); + +# if defined (ghs) + WORD arch = sinfo.u.s.wProcessorArchitecture; +# else + WORD arch = sinfo.wProcessorArchitecture; +# endif + + switch (arch) + { + case PROCESSOR_ARCHITECTURE_INTEL: + ACE_OS::strcpy (processor, ACE_LIB_TEXT ("Intel")); + if (sinfo.wProcessorLevel == 3) + ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("80386")); + else if (sinfo.wProcessorLevel == 4) + ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("80486")); + else if (sinfo.wProcessorLevel == 5) + ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("Pentium")); + else if (sinfo.wProcessorLevel == 6) + ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("Pentium Pro")); + else if (sinfo.wProcessorLevel == 7) // I'm guessing here + ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("Pentium II")); + break; + case PROCESSOR_ARCHITECTURE_MIPS: + ACE_OS::strcpy (processor, ACE_LIB_TEXT ("MIPS")); + ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("R4000")); + break; + case PROCESSOR_ARCHITECTURE_ALPHA: + ACE_OS::strcpy (processor, ACE_LIB_TEXT ("Alpha")); + ACE_OS::sprintf (subtype, ACE_LIB_TEXT ("%d"), sinfo.wProcessorLevel); + break; + case PROCESSOR_ARCHITECTURE_PPC: + ACE_OS::strcpy (processor, ACE_LIB_TEXT ("PPC")); + if (sinfo.wProcessorLevel == 1) + ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("601")); + else if (sinfo.wProcessorLevel == 3) + ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("603")); + else if (sinfo.wProcessorLevel == 4) + ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("604")); + else if (sinfo.wProcessorLevel == 6) + ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("603+")); + else if (sinfo.wProcessorLevel == 9) + ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("804+")); + else if (sinfo.wProcessorLevel == 20) + ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("620")); + break; + case PROCESSOR_ARCHITECTURE_UNKNOWN: + default: + // @@ We could provide WinCE specific info here. But let's + // defer that to some later point. + ACE_OS::strcpy (processor, ACE_LIB_TEXT ("Unknown")); + break; + } + ACE_OS::sprintf (name->machine, + ACE_LIB_TEXT ("%s %s"), + processor, subtype); + } + else if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) + { + if (vinfo.dwMajorVersion == 4 && vinfo.dwMinorVersion == 0) + { + ACE_OS::strcpy (name->release, ACE_LIB_TEXT ("Windows 95")); + if (vinfo.szCSDVersion[1] == 'C') + ACE_OS::strcat (name->release, ACE_LIB_TEXT (" OSR2")); + } + else if (vinfo.dwMajorVersion == 4 && vinfo.dwMinorVersion == 10) + { + ACE_OS::strcpy (name->release, ACE_LIB_TEXT ("Windows 98")); + if (vinfo.szCSDVersion[1] == 'A') + ACE_OS::strcat (name->release, ACE_LIB_TEXT (" SE")); + } + else if (vinfo.dwMajorVersion == 4 && vinfo.dwMinorVersion == 90) + { + ACE_OS::strcpy (name->release, ACE_LIB_TEXT ("Windows Me")); + } + else + { + ACE_OS::strcpy (name->release, unknown); + } + + ACE_OS::sprintf (name->version, ACE_LIB_TEXT ("%d"), + LOWORD (vinfo.dwBuildNumber)); + if (sinfo.dwProcessorType == PROCESSOR_INTEL_386) + ACE_OS::strcpy (name->machine, ACE_LIB_TEXT ("Intel 80386")); + else if (sinfo.dwProcessorType == PROCESSOR_INTEL_486) + ACE_OS::strcpy (name->machine, ACE_LIB_TEXT ("Intel 80486")); + else if (sinfo.dwProcessorType == PROCESSOR_INTEL_PENTIUM) + ACE_OS::strcpy (name->machine, ACE_LIB_TEXT ("Intel Pentium")); + else + ACE_OS::strcpy (name->machine, unknown); + } + else + { + // We don't know what this is! + + ACE_OS::strcpy (name->release, unknown); + ACE_OS::strcpy (name->version, unknown); + ACE_OS::strcpy (name->machine, unknown); + } + +# if defined (ACE_LACKS_HOSTNAME) + return 0; +# else /* ACE_LACKS_HOSTNAME */ + return ACE_OS::hostname (name->nodename, maxnamelen); +# endif /* ACE_LACKS_HOSTNAME */ + +# elif defined (VXWORKS) + size_t maxnamelen = sizeof name->nodename; + ACE_OS::strcpy (name->sysname, "VxWorks"); + ACE_OS::strcpy (name->release, "???"); + ACE_OS::strcpy (name->version, sysBspRev ()); + ACE_OS::strcpy (name->machine, sysModel ()); + + return ACE_OS::hostname (name->nodename, maxnamelen); +# elif defined (CHORUS) + size_t maxnamelen = sizeof name->nodename; + ACE_OS::strcpy (name->sysname, "CHORUS/ClassiX"); + ACE_OS::strcpy (name->release, "???"); + ACE_OS::strcpy (name->version, "???"); + ACE_OS::strcpy (name->machine, "???"); + + return ACE_OS::hostname (name->nodename, maxnamelen); +#elif defined (ACE_PSOS) + const unsigned long buflen(64); + char buf[buflen]; + unsigned long len; + sys_info(PSOS_VERSION,(void *)buf,buflen,&len); + ACE_OS::strcpy (name->sysname, "pSOS"); + ACE_OS::strcpy (name->release, "???"); + ACE_OS::strcpy (name->version, buf); + ACE_OS::strcpy (name->machine, "PPC 405"); // a bit of a hack + +#endif /* ACE_WIN32 */ +} +#endif /* ACE_WIN32 || VXWORKS */ + + +#if defined (VXWORKS) +struct hostent * +ACE_OS::gethostbyname (const char *name) +{ + ACE_OS_TRACE ("ACE_OS::gethostbyname"); + + // not thread safe! + static hostent ret; + static int first_addr; + static char *hostaddr[2]; + static char *aliases[1]; + + ACE_OSCALL (::hostGetByName ((char *) name), int, -1, first_addr); + if (first_addr == -1) + return 0; + + hostaddr[0] = (char *) &first_addr; + hostaddr[1] = 0; + aliases[0] = 0; + + // Might not be official: just echo input arg. + ret.h_name = (char *) name; + ret.h_addrtype = AF_INET; + ret.h_length = 4; // VxWorks 5.2/3 doesn't define IP_ADDR_LEN; + ret.h_addr_list = hostaddr; + ret.h_aliases = aliases; + + return &ret; +} + +struct hostent * +ACE_OS::gethostbyaddr (const char *addr, int length, int type) +{ + ACE_OS_TRACE ("ACE_OS::gethostbyaddr"); + + if (length != 4 || type != AF_INET) + { + errno = EINVAL; + return 0; + } + + // not thread safe! + static hostent ret; + static char name [MAXNAMELEN + 1]; + static char *hostaddr[2]; + static char *aliases[1]; + + if (::hostGetByAddr (*(int *) addr, name) != 0) + { + // errno will have been set to S_hostLib_UNKNOWN_HOST. + return 0; + } + + // Might not be official: just echo input arg. + hostaddr[0] = (char *) addr; + hostaddr[1] = 0; + aliases[0] = 0; + + ret.h_name = name; + ret.h_addrtype = AF_INET; + ret.h_length = 4; // VxWorks 5.2/3 doesn't define IP_ADDR_LEN; + ret.h_addr_list = hostaddr; + ret.h_aliases = aliases; + + return &ret; +} + +struct hostent * +ACE_OS::gethostbyaddr_r (const char *addr, int length, int type, + hostent *result, ACE_HOSTENT_DATA buffer, + int *h_errnop) +{ + ACE_OS_TRACE ("ACE_OS::gethostbyaddr_r"); + if (length != 4 || type != AF_INET) + { + errno = EINVAL; + return 0; + } + + if (ACE_OS::netdb_acquire ()) + return 0; + else + { + // buffer layout: + // buffer[0-3]: h_addr_list[0], the first (and only) addr. + // buffer[4-7]: h_addr_list[1], the null terminator for the h_addr_list. + // buffer[8]: the name of the host, null terminated. + + // Call ::hostGetByAddr (), which puts the (one) hostname into + // buffer. + if (::hostGetByAddr (*(int *) addr, &buffer[8]) == 0) + { + // Store the return values in result. + result->h_name = &buffer[8]; // null-terminated host name + result->h_addrtype = AF_INET; + result->h_length = 4; // VxWorks 5.2/3 doesn't define IP_ADDR_LEN. + + result->h_addr_list = (char **) buffer; + // Might not be official: just echo input arg. + result->h_addr_list[0] = (char *) addr; + // Null-terminate the list of addresses. + result->h_addr_list[1] = 0; + // And no aliases, so null-terminate h_aliases. + result->h_aliases = &result->h_addr_list[1]; + } + else + { + // errno will have been set to S_hostLib_UNKNOWN_HOST. + result = 0; + } + } + + ACE_OS::netdb_release (); + *h_errnop = errno; + return result; +} + +struct hostent * +ACE_OS::gethostbyname_r (const char *name, hostent *result, + ACE_HOSTENT_DATA buffer, + int *h_errnop) +{ + ACE_OS_TRACE ("ACE_OS::gethostbyname_r"); + + if (ACE_OS::netdb_acquire ()) + return 0; + else + { + int addr; + ACE_OSCALL (::hostGetByName ((char *) name), int, -1, addr); + + if (addr == -1) + { + // errno will have been set to S_hostLib_UNKNOWN_HOST + result = 0; + } + else + { + // Might not be official: just echo input arg. + result->h_name = (char *) name; + result->h_addrtype = AF_INET; + result->h_length = 4; // VxWorks 5.2/3 doesn't define IP_ADDR_LEN; + + // buffer layout: + // buffer[0-3]: h_addr_list[0], pointer to the addr. + // buffer[4-7]: h_addr_list[1], null terminator for the h_addr_list. + // buffer[8-11]: the first (and only) addr. + + // Store the address list in buffer. + result->h_addr_list = (char **) buffer; + // Store the actual address _after_ the address list. + result->h_addr_list[0] = (char *) &result->h_addr_list[2]; + result->h_addr_list[2] = (char *) addr; + // Null-terminate the list of addresses. + result->h_addr_list[1] = 0; + // And no aliases, so null-terminate h_aliases. + result->h_aliases = &result->h_addr_list[1]; + } + } + + ACE_OS::netdb_release (); + *h_errnop = errno; + return result; +} +#endif /* VXWORKS */ + +void +ACE_OS::ace_flock_t::dump (void) const +{ + ACE_OS_TRACE ("ACE_OS::ace_flock_t::dump"); + +#if 0 + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("handle_ = %u"), this->handle_)); +#if defined (ACE_WIN32) + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nInternal = %d"), this->overlapped_.Internal)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nInternalHigh = %d"), this->overlapped_.InternalHigh)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nOffsetHigh = %d"), this->overlapped_.OffsetHigh)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nhEvent = %d"), this->overlapped_.hEvent)); +#elif !defined (CHORUS) + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nl_whence = %d"), this->lock_.l_whence)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nl_start = %d"), this->lock_.l_start)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nl_len = %d"), this->lock_.l_len)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nl_type = %d"), this->lock_.l_type)); +#endif /* ACE_WIN32 */ + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +#endif /* 0 */ +} + +void +ACE_OS::mutex_lock_cleanup (void *mutex) +{ + ACE_OS_TRACE ("ACE_OS::mutex_lock_cleanup"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + pace_pthread_mutex_t *p_lock = (pace_pthread_mutex_t *) mutex; + pace_pthread_mutex_unlock (p_lock); +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) + ACE_mutex_t *p_lock = (ACE_mutex_t *) mutex; + ACE_OS::mutex_unlock (p_lock); +# else + ACE_UNUSED_ARG (mutex); +# endif /* ACE_HAS_PTHREADS */ +# else + ACE_UNUSED_ARG (mutex); +# endif /* ACE_HAS_PACE && !ACE_WIN32 */ +} + +#if defined (ACE_HAS_WINCE) +FILE * +ACE_OS::fopen (const ACE_TCHAR *filename, + const ACE_TCHAR *mode) +{ + return ::_wfopen (filename, mode); +} + +#elif defined (ACE_WIN32) +FILE * +ACE_OS::fopen (const ACE_TCHAR *filename, + const ACE_TCHAR *mode) +{ + ACE_OS_TRACE ("ACE_OS::fopen"); + int hmode = _O_TEXT; + + for (const ACE_TCHAR *mode_ptr = mode; *mode_ptr != 0; mode_ptr++) + ACE_OS::fopen_mode_to_open_mode_converter (*mode_ptr, hmode); + + ACE_HANDLE handle = ACE_OS::open (filename, hmode); + if (handle != ACE_INVALID_HANDLE) + { + hmode &= _O_TEXT | _O_RDONLY | _O_APPEND; + int fd = _open_osfhandle ((long) handle, hmode); + if (fd != -1) + { +# if defined (__BORLANDC__) && !defined (ACE_USES_WCHAR) + FILE *fp = ::_fdopen (fd, ACE_const_cast (char *, mode)); +# elif defined (__BORLANDC__) && defined (ACE_USES_WCHAR) + FILE *fp = ::_wfdopen (fd, ACE_const_cast (wchar_t *, mode)); +# elif defined (ACE_USES_WCHAR) + FILE *fp = ::_wfdopen (fd, mode); +# else + FILE *fp = ::fdopen (fd, mode); +# endif /* defined(__BORLANDC__) && !defined (ACE_USES_WCHAR)) */ + if (fp != NULL) + return fp; + _close (fd); + } + ACE_OS::close (handle); + } + return NULL; +} +#endif /* ACE_WIN32 */ + +// The following *printf functions aren't inline because +// they use varargs. + +int +ACE_OS::fprintf (FILE *fp, const char *format, ...) +{ + ACE_OS_TRACE ("ACE_OS::fprintf"); +#if defined (ACE_HAS_WINCE) + ACE_NOTSUP_RETURN (-1); +# else /* ACE_HAS_WINCE */ + int result = 0; + va_list ap; + va_start (ap, format); +# if defined (ACE_HAS_PACE) + ACE_OSCALL (::pace_vfprintf (fp, format, ap), int, -1, result); +# else + ACE_OSCALL (::vfprintf (fp, format, ap), int, -1, result); +# endif /* ACE_HAS_PACE */ + va_end (ap); + return result; +# endif /* ACE_HAS_WINCE */ +} + +#if defined (ACE_HAS_WCHAR) +int +ACE_OS::fprintf (FILE *fp, const wchar_t *format, ...) +{ + ACE_OS_TRACE ("ACE_OS::fprintf"); + +# if !defined (ACE_HAS_VFWPRINTF) + ACE_UNUSED_ARG (fp); + ACE_UNUSED_ARG (format); + ACE_NOTSUP_RETURN (-1); + +# else + int result = 0; + va_list ap; + va_start (ap, format); + ACE_OSCALL (::vfwprintf (fp, format, ap), int, -1, result); + va_end (ap); + return result; + +# endif /* ACE_HAS_VFWPRINTF */ +} +#endif /* ACE_HAS_WCHAR */ + +int +ACE_OS::printf (const char *format, ...) +{ + ACE_OS_TRACE ("ACE_OS::printf"); + int result; + va_list ap; + va_start (ap, format); +#if defined (ACE_HAS_PACE) + ACE_OSCALL (::pace_vprintf (format, ap), int, -1, result); +#else + ACE_OSCALL (::vprintf (format, ap), int, -1, result); +#endif /* ACE_HAS_PACE */ + va_end (ap); + return result; +} + +int +ACE_OS::sprintf (char *buf, const char *format, ...) +{ + // ACE_OS_TRACE ("ACE_OS::sprintf"); + + int result; + va_list ap; + va_start (ap, format); +#if defined (ACE_HAS_PACE) + ACE_OSCALL (ACE_SPRINTF_ADAPTER (::pace_vsprintf (buf, format, ap)), int, -1, result); +#else + ACE_OSCALL (ACE_SPRINTF_ADAPTER (::vsprintf (buf, format, ap)), int, -1, result); +#endif /* ACE_HAS_PACE */ + va_end (ap); + return result; +} + +#if defined (ACE_HAS_WCHAR) +int +ACE_OS::sprintf (wchar_t *buf, const wchar_t *format, ...) +{ + ACE_OS_TRACE ("ACE_OS::sprintf"); + +# if defined (ACE_HAS_VSWPRINTF) + + int result; + va_list ap; + va_start (ap, format); + ACE_OSCALL (::vswprintf (buf, format, ap), int, -1, result); + va_end (ap); + return result; + +# else + + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (format); + ACE_NOTSUP_RETURN (-1); + +# endif /* ACE_HAS_VSWPRINTF */ +} +#endif /* ACE_HAS_WCHAR */ + +char * +ACE_OS::gets (char *str, int n) +{ + ACE_OS_TRACE ("ACE_OS::gets"); +#if defined (ACE_HAS_PACE) + return pace_fgets (str, n, stdin); +#else + int c; + char *s = str; + + if (str == 0 || n < 0) n = 0; + if (n == 0) str = 0; + else n--; + + while ((c = getchar ()) != '\n') + { + + if (c == EOF && errno == EINTR) + { +# if defined (ACE_HAS_SIGNAL_SAFE_OS_CALLS) + continue; +# else + break; +# endif /* ACE_HAS_SIGNAL_SAFE_OS_CALLS */ + } + + if (c == EOF) + break; + + if (n > 0) + n--, *s++ = c; + } + if (s) *s = '\0'; + + return (c == EOF) ? 0 : str; +#endif /* ACE_HAS_PACE */ +} + +int +ACE_OS::execl (const char * /* path */, const char * /* arg0 */, ...) +{ + ACE_OS_TRACE ("ACE_OS::execl"); +#if defined (ACE_WIN32) || defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + ACE_NOTSUP_RETURN (-1); + // Need to write this code. + // ACE_OSCALL_RETURN (::execv (path, argv), int, -1); +#endif /* ACE_WIN32 */ +} + +int +ACE_OS::execle (const char * /* path */, const char * /* arg0 */, ...) +{ + ACE_OS_TRACE ("ACE_OS::execle"); +#if defined (ACE_WIN32) || defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + ACE_NOTSUP_RETURN (-1); + // Need to write this code. + // ACE_OSCALL_RETURN (::execve (path, argv, envp), int, -1); +#endif /* ACE_WIN32 */ +} + +int +ACE_OS::execlp (const char * /* file */, const char * /* arg0 */, ...) +{ + ACE_OS_TRACE ("ACE_OS::execlp"); +#if defined (ACE_WIN32) || defined (VXWORKS) + ACE_NOTSUP_RETURN (-1); +#else + ACE_NOTSUP_RETURN (-1); + // Need to write this code. + // ACE_OSCALL_RETURN (::execvp (file, argv), int, -1); +#endif /* ACE_WIN32 */ +} + +int +ACE_OS::scheduling_class (const char *class_name, ACE_id_t &id) +{ +#if defined (ACE_HAS_PRIOCNTL) + // Get the priority class ID. + pcinfo_t pcinfo; + // The following is just to avoid Purify warnings about unitialized + // memory reads. + ACE_OS::memset (&pcinfo, 0, sizeof pcinfo); + + ACE_OS::strcpy (pcinfo.pc_clname, class_name); + if (ACE_OS::priority_control (P_ALL /* ignored */, + P_MYID /* ignored */, + PC_GETCID, + (char *) &pcinfo) == -1) + { + return -1; + } + else + { + id = pcinfo.pc_cid; + return 0; + } +#else /* ! ACE_HAS_PRIOCNTL */ + ACE_UNUSED_ARG (class_name); + ACE_UNUSED_ARG (id); + ACE_NOTSUP_RETURN (-1); +#endif /* ! ACE_HAS_PRIOCNTL */ +} + +int +ACE_OS::set_scheduling_params (const ACE_Sched_Params &sched_params, + ACE_id_t id) +{ +#if defined (ACE_HAS_PRIOCNTL) + // Set priority class, priority, and quantum of this LWP or process as + // specified in sched_params. + + // Get the priority class ID. + ACE_id_t class_id; + if (ACE_OS::scheduling_class (sched_params.policy() == ACE_SCHED_OTHER ? + "TS" : + "RT", class_id) == -1) + { + return -1; + } + + pcparms_t pcparms; + // The following is just to avoid Purify warnings about unitialized + // memory reads. + ACE_OS::memset (&pcparms, 0, sizeof pcparms); + + pcparms.pc_cid = class_id; + + if (sched_params.policy () == ACE_SCHED_OTHER && + sched_params.quantum () == ACE_Time_Value::zero) + // SunOS doesn't support non-zero quantums in time-sharing class: use + // real-time class instead. + { + tsparms_t tsparms; + // The following is just to avoid Purify warnings about unitialized + // memory reads. + ACE_OS::memset (&tsparms, 0, sizeof tsparms); + + // Don't change ts_uprilim (user priority limit) + tsparms.ts_uprilim = TS_NOCHANGE; + tsparms.ts_upri = sched_params.priority (); + + // Package up the TS class ID and parameters for the + // priority_control () call. + ACE_OS::memcpy (pcparms.pc_clparms, &tsparms, sizeof tsparms); + } + else if (sched_params.policy () == ACE_SCHED_FIFO || + (sched_params.policy () == ACE_SCHED_RR && + sched_params.quantum () != ACE_Time_Value::zero)) + // must have non-zero quantum for RR, to make it meaningful + // A zero quantum with FIFO has special significance: it actually + // means infinite time quantum, i.e., run-to-completion. + { + rtparms_t rtparms; + // The following is just to avoid Purify warnings about unitialized + // memory reads. + ACE_OS::memset (&rtparms, 0, sizeof rtparms); + + rtparms.rt_pri = sched_params.priority (); + + if (sched_params.quantum () == ACE_Time_Value::zero) + { + // rtparms.rt_tqsecs is ignored with RT_TQINF + rtparms.rt_tqnsecs = RT_TQINF; + } + else + { + rtparms.rt_tqsecs = (ulong) sched_params.quantum ().sec (); + rtparms.rt_tqnsecs = sched_params.quantum ().usec () * 1000; + } + + // Package up the RT class ID and parameters for the + // priority_control () call. + ACE_OS::memcpy (pcparms.pc_clparms, &rtparms, sizeof rtparms); + } + else + { + errno = EINVAL; + return -1; + } + + if (ACE_OS::priority_control ((idtype_t) (sched_params.scope () == ACE_SCOPE_THREAD + ? ACE_SCOPE_PROCESS + : sched_params.scope ()), + id, + PC_SETPARMS, + (char *) &pcparms) < 0) + { + return ACE_OS::last_error (); + } + + return 0; +#else /* ! ACE_HAS_PRIOCNTL */ + ACE_UNUSED_ARG (sched_params); + ACE_UNUSED_ARG (id); + ACE_NOTSUP_RETURN (-1); +#endif /* ! ACE_HAS_PRIOCNTL */ +} + +int +ACE_OS::thr_setprio (const ACE_Sched_Priority prio) +{ + // Set the thread priority on the current thread. + ACE_hthread_t my_thread_id; + ACE_OS::thr_self (my_thread_id); + + int status = ACE_OS::thr_setprio (my_thread_id, prio); + +# if defined (ACE_NEEDS_LWP_PRIO_SET) + // If the thread is in the RT class, then set the priority on its + // LWP. (Instead of doing this if the thread is in the RT class, it + // should be done for all bound threads. But, there doesn't appear + // to be an easy way to determine if the thread is bound.) + + if (status == 0) + { + // Find what scheduling class the thread's LWP is in. + ACE_Sched_Params sched_params (ACE_SCHED_OTHER, 0); + if (ACE_OS::lwp_getparams (sched_params) == -1) + { + return -1; + } + else if (sched_params.policy () == ACE_SCHED_FIFO || + sched_params.policy () == ACE_SCHED_RR) + { + // This thread's LWP is in the RT class, so we need to set + // its priority. + sched_params.priority (prio); + return ACE_OS::lwp_setparams (sched_params); + } + // else this is not an RT thread. Nothing more needs to be + // done. + } +# endif /* ACE_NEEDS_LWP_PRIO_SET */ + + return status; +} + +int +ACE_OS::sched_params (const ACE_Sched_Params &sched_params, + ACE_id_t id) +{ + ACE_OS_TRACE ("ACE_OS::sched_params"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_UNUSED_ARG (id); + if (sched_params.quantum () != ACE_Time_Value::zero) + { + // quantums not supported + errno = EINVAL; + return -1; + } + + // Thanks to Thilo Kielmann for + // providing this code for 1003.1c PThreads. Please note that this + // has only been tested for POSIX 1003.1c threads, and may cause problems + // with other PThreads flavors! + + struct sched_param param; + param.sched_priority = sched_params.priority (); + + if (sched_params.scope () == ACE_SCOPE_PROCESS) + return pace_sched_setscheduler (0, // this process + sched_params.policy (), + ¶m) == -1 ? -1 : 0; + else if (sched_params.scope () == ACE_SCOPE_THREAD) + { + ACE_thread_t thr_id = ACE_OS::thr_self (); + return pace_pthread_setschedparam (thr_id, + sched_params.policy (), + ¶m); + } +#if defined (sun) + // We need to be able to set LWP priorities on Suns, even without + // ACE_HAS_STHREADS, to obtain preemption. + else if (sched_params.scope () == ACE_SCOPE_LWP) + return ACE_OS::set_scheduling_params (sched_params, id); +#endif /* sun */ + else // sched_params.scope () == ACE_SCOPE_LWP, which isn't POSIX + { + errno = EINVAL; + return -1; + } +# elif defined (CHORUS) + ACE_UNUSED_ARG (id); + int result; + struct sched_param param; + ACE_thread_t thr_id = ACE_OS::thr_self (); + + param.sched_priority = sched_params.priority (); + + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id, + sched_params.policy (), + ¶m), + result), + int, -1); +# elif defined (ACE_HAS_STHREADS) + return ACE_OS::set_scheduling_params (sched_params, id); +# elif defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_SETSCHED) + ACE_UNUSED_ARG (id); + if (sched_params.quantum () != ACE_Time_Value::zero) + { + // quantums not supported + errno = EINVAL; + return -1; + } + + // Thanks to Thilo Kielmann for + // providing this code for 1003.1c PThreads. Please note that this + // has only been tested for POSIX 1003.1c threads, and may cause + // problems with other PThreads flavors! + + struct sched_param param; + param.sched_priority = sched_params.priority (); + + if (sched_params.scope () == ACE_SCOPE_PROCESS) + { + int result = ::sched_setscheduler (0, // this process + sched_params.policy (), + ¶m) == -1 ? -1 : 0; +# if defined (DIGITAL_UNIX) + return result == 0 + ? // Use priocntl (2) to set the process in the RT class, + // if using an RT policy. + ACE_OS::set_scheduling_params (sched_params) + : result; +# else /* ! DIGITAL_UNIX */ + return result; +# endif /* ! DIGITAL_UNIX */ + } + else if (sched_params.scope () == ACE_SCOPE_THREAD) + { + ACE_thread_t thr_id = ACE_OS::thr_self (); + +# if defined (ACE_HAS_PTHREADS_DRAFT4) + return (::pthread_setscheduler (thr_id, + sched_params.policy (), + sched_params.priority()) == -1 ? -1 : 0); +# else + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id, + sched_params.policy (), + ¶m), + result), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + } +#if defined (sun) + // We need to be able to set LWP priorities on Suns, even without + // ACE_HAS_STHREADS, to obtain preemption. + else if (sched_params.scope () == ACE_SCOPE_LWP) + return ACE_OS::set_scheduling_params (sched_params, id); +#endif /* sun */ + else // sched_params.scope () == ACE_SCOPE_LWP, which isn't POSIX + { + errno = EINVAL; + return -1; + } + +# elif defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) + + // PharLap ETS can act on the current thread - it can set the + // quantum also, unlike Win32. All this only works on the RT + // version. +# if defined (ACE_HAS_PHARLAP_RT) + if (id != ACE_SELF) + ACE_NOTSUP_RETURN (-1); + + if (sched_params.quantum() != ACE_Time_Value::zero) + EtsSetTimeSlice (sched_params.quantum().msec()); + +# else + ACE_UNUSED_ARG (id); + + if (sched_params.scope () != ACE_SCOPE_PROCESS + || sched_params.quantum () != ACE_Time_Value::zero) + { + // Win32 only allows setting priority class (therefore, policy) + // at the process level. I don't know of a way to set the + // quantum. + errno = EINVAL; + return -1; + } + + // Set the priority class of this process to the REALTIME process class + // _if_ the policy is ACE_SCHED_FIFO. Otherwise, set to NORMAL. + if (!::SetPriorityClass (::GetCurrentProcess (), + sched_params.policy () == ACE_SCHED_FIFO + ? REALTIME_PRIORITY_CLASS + : NORMAL_PRIORITY_CLASS)) + { + ACE_OS::set_errno_to_last_error (); + return -1; + } +# endif /* ACE_HAS_PHARLAP_RT */ + + // Set the thread priority on the current thread. + return ACE_OS::thr_setprio (sched_params.priority ()); + +# elif defined (VXWORKS) || defined (ACE_PSOS) + ACE_UNUSED_ARG (id); + + // There is only one class of priorities on VxWorks, and no time + // quanta. So, just set the current thread's priority. + + if (sched_params.policy () != ACE_SCHED_FIFO + || sched_params.scope () != ACE_SCOPE_PROCESS + || sched_params.quantum () != ACE_Time_Value::zero) + { + errno = EINVAL; + return -1; + } + + // Set the thread priority on the current thread. + return ACE_OS::thr_setprio (sched_params.priority ()); +#else + ACE_UNUSED_ARG (sched_params); + ACE_UNUSED_ARG (id); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE && !ACE_WIN32 */ +} + +// = Static initialization. + +// This is necessary to deal with POSIX pthreads insanity. This +// guarantees that we've got a "zero'd" thread id even when +// ACE_thread_t, ACE_hthread_t, and ACE_thread_key_t are implemented +// as structures... Under no circumstances should these be given +// initial values. +// Note: these three objects require static construction. +ACE_thread_t ACE_OS::NULL_thread; +ACE_hthread_t ACE_OS::NULL_hthread; +#if defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) + ACE_thread_key_t ACE_OS::NULL_key = ACE_static_cast (ACE_thread_key_t, -1); +#else /* ! ACE_HAS_TSS_EMULATION */ + ACE_thread_key_t ACE_OS::NULL_key; +#endif /* ! ACE_HAS_TSS_EMULATION */ + +#if defined (CHORUS) +KnCap ACE_OS::actorcaps_[ACE_CHORUS_MAX_ACTORS]; +// This is used to map an actor's id into a KnCap for killing and +// waiting actors. +#endif /* CHORUS */ + +#if defined (ACE_WIN32) + +// = Static initialization. + +// Keeps track of whether we've initialized the WinSock DLL. +int ACE_OS::socket_initialized_; + +#endif /* WIN32 */ + +#if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) + +// Moved class ACE_TSS_Ref declaration to OS.h so it can be visible to +// the single file of template instantiations. + +ACE_TSS_Ref::ACE_TSS_Ref (ACE_thread_t id) + : tid_(id) +{ + ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref"); +} + +ACE_TSS_Ref::ACE_TSS_Ref (void) +{ + ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref"); +} + +// Check for equality. +int +ACE_TSS_Ref::operator== (const ACE_TSS_Ref &info) const +{ + ACE_OS_TRACE ("ACE_TSS_Ref::operator=="); + + return this->tid_ == info.tid_; +} + +// Check for inequality. +ACE_SPECIAL_INLINE +int +ACE_TSS_Ref::operator != (const ACE_TSS_Ref &tss_ref) const +{ + ACE_OS_TRACE ("ACE_TSS_Ref::operator !="); + + return !(*this == tss_ref); +} + +// moved class ACE_TSS_Info declaration +// to OS.h so it can be visible to the +// single file of template instantiations + +ACE_TSS_Info::ACE_TSS_Info (ACE_thread_key_t key, + void (*dest)(void *), + void *tss_inst) + : key_ (key), + destructor_ (dest), + tss_obj_ (tss_inst), + thread_count_ (-1) +{ + ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info"); +} + +ACE_TSS_Info::ACE_TSS_Info (void) + : key_ (ACE_OS::NULL_key), + destructor_ (0), + tss_obj_ (0), + thread_count_ (-1) +{ + ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info"); +} + +# if defined (ACE_HAS_NONSCALAR_THREAD_KEY_T) +static inline int operator== (const ACE_thread_key_t &lhs, + const ACE_thread_key_t &rhs) +{ + return ! ACE_OS::memcmp (&lhs, &rhs, sizeof (ACE_thread_key_t)); +} + +static inline int operator!= (const ACE_thread_key_t &lhs, + const ACE_thread_key_t &rhs) +{ + return ! (lhs == rhs); +} +# endif /* ACE_HAS_NONSCALAR_THREAD_KEY_T */ + +// Check for equality. +int +ACE_TSS_Info::operator== (const ACE_TSS_Info &info) const +{ + ACE_OS_TRACE ("ACE_TSS_Info::operator=="); + + return this->key_ == info.key_; +} + +// Check for inequality. +int +ACE_TSS_Info::operator != (const ACE_TSS_Info &info) const +{ + ACE_OS_TRACE ("ACE_TSS_Info::operator !="); + + return !(*this == info); +} + +void +ACE_TSS_Info::dump (void) +{ + // ACE_OS_TRACE ("ACE_TSS_Info::dump"); + +#if 0 + ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("key_ = %u\n"), this->key_)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("destructor_ = %u\n"), this->destructor_)); + ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("tss_obj_ = %u\n"), this->tss_obj_)); + ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); +#endif /* 0 */ +} + +// Moved class ACE_TSS_Keys declaration to OS.h so it can be visible +// to the single file of template instantiations. + +ACE_TSS_Keys::ACE_TSS_Keys (void) +{ + for (u_int i = 0; i < ACE_WORDS; ++i) + { + key_bit_words_[i] = 0; + } +} + +ACE_SPECIAL_INLINE +void +ACE_TSS_Keys::find (const u_int key, u_int &word, u_int &bit) +{ + word = key / ACE_BITS_PER_WORD; + bit = key % ACE_BITS_PER_WORD; +} + +int +ACE_TSS_Keys::test_and_set (const ACE_thread_key_t key) +{ + ACE_KEY_INDEX (key_index, key); + u_int word, bit; + find (key_index, word, bit); + + if (ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit)) + { + return 1; + } + else + { + ACE_SET_BITS (key_bit_words_[word], 1 << bit); + return 0; + } +} + +int +ACE_TSS_Keys::test_and_clear (const ACE_thread_key_t key) +{ + ACE_KEY_INDEX (key_index, key); + u_int word, bit; + find (key_index, word, bit); + + if (ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit)) + { + ACE_CLR_BITS (key_bit_words_[word], 1 << bit); + return 0; + } + else + { + return 1; + } +} + +int +ACE_TSS_Keys::is_set (const ACE_thread_key_t key) const +{ + ACE_KEY_INDEX (key_index, key); + u_int word, bit; + find (key_index, word, bit); + + return ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit); +} + + +class ACE_TSS_Cleanup + // = TITLE + // Singleton that knows how to clean up all the thread-specific + // resources for Win32. + // + // = DESCRIPTION + // All this nonsense is required since Win32 doesn't + // automatically cleanup thread-specific storage on thread exit, + // unlike real operating systems... ;-) +{ +public: + static ACE_TSS_Cleanup *instance (void); + + ~ACE_TSS_Cleanup (void); + + void exit (void *status); + // Cleanup the thread-specific objects. Does _NOT_ exit the thread. + + int insert (ACE_thread_key_t key, void (*destructor)(void *), void *inst); + // Insert a tuple into the table. + + int remove (ACE_thread_key_t key); + // Remove a tuple from the table. + + int detach (void *inst); + // Detaches a tss_instance from its key. + + void key_used (ACE_thread_key_t key); + // Mark a key as being used by this thread. + + int free_all_keys_left (void); + // Free all keys left in the table before destruction. + + static int lockable () { return instance_ != 0; } + // Indication of whether the ACE_TSS_CLEANUP_LOCK is usable, and + // therefore whether we are in static constructor/destructor phase + // or not. + +protected: + void dump (void); + + ACE_TSS_Cleanup (void); + // Ensure singleton. + +private: + // Array of objects. + typedef ACE_TSS_Info ACE_TSS_TABLE[ACE_DEFAULT_THREAD_KEYS]; + typedef ACE_TSS_Info *ACE_TSS_TABLE_ITERATOR; + + ACE_TSS_TABLE table_; + // Table of 's. + + ACE_thread_key_t in_use_; + // Key for the thread-specific array of whether each TSS key is in use. + + ACE_TSS_Keys *tss_keys (); + // Accessor for this threads ACE_TSS_Keys instance. + +#if defined (ACE_HAS_TSS_EMULATION) + ACE_thread_key_t in_use_key_; + // Key that is used by in_use_. We save this key so that we know + // not to call its destructor in free_all_keys_left (). +#endif /* ACE_HAS_TSS_EMULATION */ + + // = Static data. + static ACE_TSS_Cleanup *instance_; + // Pointer to the singleton instance. +}; + +// = Static object initialization. + +// Pointer to the singleton instance. +ACE_TSS_Cleanup *ACE_TSS_Cleanup::instance_ = 0; + +ACE_TSS_Cleanup::~ACE_TSS_Cleanup (void) +{ + // Zero out the instance pointer to support lockable () accessor. + ACE_TSS_Cleanup::instance_ = 0; +} + +void +ACE_TSS_Cleanup::exit (void * /* status */) +{ + ACE_OS_TRACE ("ACE_TSS_Cleanup::exit"); + + ACE_TSS_TABLE_ITERATOR key_info = table_; + ACE_TSS_Info info_arr[ACE_DEFAULT_THREAD_KEYS]; + int info_ix = 0; + + // While holding the lock, we only collect the ACE_TSS_Info objects + // in an array without invoking the according destructors. + { + ACE_TSS_CLEANUP_GUARD + + // Iterate through all the thread-specific items and free them all + // up. + + for (unsigned int i = 0; + i < ACE_DEFAULT_THREAD_KEYS; + ++key_info, ++i) + { + if (key_info->key_ == ACE_OS::NULL_key || + ! key_info->key_in_use ()) continue; + + // If the key's ACE_TSS_Info in-use bit for this thread was set, + // unset it and decrement the key's thread_count_. + if (! tss_keys ()->test_and_clear (key_info->key_)) + { + --key_info->thread_count_; + } + + void *tss_info = 0; + + if (key_info->destructor_ + && ACE_OS::thr_getspecific (key_info->key_, &tss_info) == 0 + && tss_info) + { + info_arr[info_ix].key_ = key_info->key_; + info_arr[info_ix].destructor_ = key_info->destructor_; + info_arr[info_ix++].tss_obj_ = key_info->tss_obj_; + } + } + } + + // Now we have given up the ACE_TSS_Cleanup::lock_ and we start + // invoking destructors, in the reverse order of creation. + for (int i = info_ix - 1; i >= 0; --i) + { + void *tss_info = 0; + + ACE_OS::thr_getspecific (info_arr[i].key_, &tss_info); + + if (tss_info != 0) + { + // Only call the destructor if the value is non-zero for this + // thread. + (*info_arr[i].destructor_)(tss_info); + } + } + + // Acquire the ACE_TSS_CLEANUP_LOCK, then free TLS keys and remove + // entries from ACE_TSS_Info table. + { + ACE_TSS_CLEANUP_GUARD + +# if 0 + // We shouldn't free the key and remove it from the table here + // because if we do and some thread ends before other threads + // even get started (or their TSS object haven't been created yet,) + // it's entry will be removed from the table and we are in big chaos. + // For TSS object, these have been done in ACE_TSS_Cleanup::detach. + // Two other use cases will be user managed TSS'es and system wide + // TSS, ones are users responsibilities and the others should be + // persistant system wide. + for (int i = 0; i < index; i++) + { +# if defined (ACE_WIN32) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) + // Calling thr_keyfree here ensure the key + // gets removed appropriately. Notice that + // a key should be removed before freeing it. + ACE_OS::thr_keyfree (key_info->key_); +# else + // don't bother to free the key + this->remove (key_info->key_); +# endif /* ACE_WIN32 */ + } +# endif /* 0 */ + } +} + +int +ACE_TSS_Cleanup::free_all_keys_left (void) + // This is called from ACE_OS::cleanup_tss (). When this gets + // called, all threads should have exited except the main thread. + // No key should be freed from this routine. It there's any, + // something might be wrong. +{ + ACE_thread_key_t key_arr[ACE_DEFAULT_THREAD_KEYS]; + ACE_TSS_TABLE_ITERATOR key_info = table_; + unsigned int idx = 0; + unsigned int i; + + for (i = 0; + i < ACE_DEFAULT_THREAD_KEYS; + ++key_info, ++i) +#if defined (ACE_HAS_TSS_EMULATION) + if (key_info->key_ != in_use_key_) +#endif /* ACE_HAS_TSS_EMULATION */ + // Don't call ACE_OS::thr_keyfree () on ACE_TSS_Cleanup's own + // key. See the comments in ACE_OS::thr_key_detach (): the key + // doesn't get detached, so it will be in the table here. + // However, there's no resource associated with it, so we don't + // need to keyfree it. The dynamic memory associated with it + // was already deleted by ACE_TSS_Cleanup::exit (), so we don't + // want to access it again. + key_arr [idx++] = key_info->key_; + + for (i = 0; i < idx; i++) + if (key_arr[i] != ACE_OS::NULL_key) +#if defined (ACE_HAS_TSS_EMULATION) + ACE_OS::thr_keyfree (key_arr[i]); +#elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS) + // Don't call ACE_OS::thr_keyfree here. It will try to use + // which has already been cleaned up here. + ::tsd_delete (key_arr[i]); +#else /* ACE_WIN32 */ + // Don't call ACE_OS::thr_keyfree here. It will try to use + // which has already been cleaned up here. + TlsFree (key_arr[i]); +#endif /* ACE_HAS_TSS_EMULATION */ + + return 0; +} + +extern "C" void +ACE_TSS_Cleanup_keys_destroyer (void *tss_keys) +{ + delete ACE_reinterpret_cast (ACE_TSS_Keys *, tss_keys); +} + +ACE_TSS_Cleanup::ACE_TSS_Cleanup (void) + : in_use_ (ACE_OS::NULL_key) +#if defined (ACE_HAS_TSS_EMULATION) + // ACE_TSS_Emulation::total_keys () provides the value of the next + // key to be created. + , in_use_key_ (ACE_TSS_Emulation::total_keys ()) +#endif /* ACE_HAS_TSS_EMULATION */ +{ + ACE_OS_TRACE ("ACE_TSS_Cleanup::ACE_TSS_Cleanup"); +} + +ACE_TSS_Cleanup * +ACE_TSS_Cleanup::instance (void) +{ + ACE_OS_TRACE ("ACE_TSS_Cleanup::instance"); + + // Create and initialize thread-specific key. + if (ACE_TSS_Cleanup::instance_ == 0) + { + // Insure that we are serialized! + ACE_TSS_CLEANUP_GUARD + + // Now, use the Double-Checked Locking pattern to make sure we + // only create the ACE_TSS_Cleanup instance once. + if (ACE_TSS_Cleanup::instance_ == 0) + ACE_NEW_RETURN (ACE_TSS_Cleanup::instance_, + ACE_TSS_Cleanup, + 0); + } + + return ACE_TSS_Cleanup::instance_; +} + +int +ACE_TSS_Cleanup::insert (ACE_thread_key_t key, + void (*destructor)(void *), + void *inst) +{ + ACE_OS_TRACE ("ACE_TSS_Cleanup::insert"); + ACE_TSS_CLEANUP_GUARD + + ACE_KEY_INDEX (key_index, key); + if (key_index < ACE_DEFAULT_THREAD_KEYS) + { + table_[key_index] = ACE_TSS_Info (key, destructor, inst); + return 0; + } + else + { + return -1; + } +} + +int +ACE_TSS_Cleanup::remove (ACE_thread_key_t key) +{ + ACE_OS_TRACE ("ACE_TSS_Cleanup::remove"); + ACE_TSS_CLEANUP_GUARD + + ACE_KEY_INDEX (key_index, key); + if (key_index < ACE_DEFAULT_THREAD_KEYS) + { + // "Remove" the TSS_Info table entry by zeroing out its key_ and + // destructor_ fields. Also, keep track of the number threads + // using the key. + ACE_TSS_Info &info = this->table_ [key_index]; + + // Don't bother to check if the program is shutting + // down. Doing so will cause a new ACE_TSS object getting + // created again. + if (!ACE_OS_Object_Manager::shutting_down () + && ! tss_keys ()->test_and_clear (info.key_)) + --info.thread_count_; + + info.key_ = ACE_OS::NULL_key; + info.destructor_ = 0; + return 0; + } + else + return -1; +} + +int +ACE_TSS_Cleanup::detach (void *inst) +{ + ACE_TSS_CLEANUP_GUARD + + ACE_TSS_TABLE_ITERATOR key_info = table_; + int success = 0; + int ref_cnt = 0; + + // Mark the key as detached in the TSS_Info table. + // It only works for the first key that "inst" owns. + // I don't know why. + for (unsigned int i = 0; + i < ACE_DEFAULT_THREAD_KEYS; + ++key_info, ++i) + { + if (key_info->tss_obj_ == inst) + { + key_info->tss_obj_ = 0; + ref_cnt = key_info->thread_count_; + success = 1; + break; + } + } + + if (success == 0) + return -1; + else if (ref_cnt == 0) + { + // Mark the key as no longer being used. + key_info->key_in_use (0); +# if defined (ACE_WIN32) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) + ACE_thread_key_t temp_key = key_info->key_; +# endif /* ACE_WIN32 */ + int retv = this->remove (key_info->key_); + +# if defined (ACE_WIN32) + ::TlsFree (temp_key); +# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS) + ::tsd_delete (temp_key); +# endif /* ACE_WIN32 */ + return retv; + } + + return 0; +} + +void +ACE_TSS_Cleanup::key_used (ACE_thread_key_t key) +{ + // If the key's ACE_TSS_Info in-use bit for this thread is not set, + // set it and increment the key's thread_count_. + if (! tss_keys ()->test_and_set (key)) + { + ACE_TSS_CLEANUP_GUARD + + // Retrieve the key's ACE_TSS_Info and increment its thread_count_. + ACE_KEY_INDEX (key_index, key); + ACE_TSS_Info &key_info = this->table_ [key_index]; + if (key_info.thread_count_ == -1) + key_info.key_in_use (1); + else + ++key_info.thread_count_; + } +} + +void +ACE_TSS_Cleanup::dump (void) +{ + // Iterate through all the thread-specific items and dump them all. + + ACE_TSS_TABLE_ITERATOR key_info = table_; + for (unsigned int i = 0; + i < ACE_DEFAULT_THREAD_KEYS; + ++key_info, ++i) + key_info->dump (); +} + +ACE_TSS_Keys * +ACE_TSS_Cleanup::tss_keys () +{ + if (in_use_ == ACE_OS::NULL_key) + { + ACE_TSS_CLEANUP_GUARD + // Double-check; + if (in_use_ == ACE_OS::NULL_key) + { + // Initialize in_use_ with a new key. + if (ACE_OS::thr_keycreate (&in_use_, + &ACE_TSS_Cleanup_keys_destroyer)) + return 0; // Major problems, this should *never* happen! + } + } + + ACE_TSS_Keys *ts_keys = 0; + if (ACE_OS::thr_getspecific (in_use_, + ACE_reinterpret_cast (void **, &ts_keys)) == -1) + return 0; // This should not happen! + + if (ts_keys == 0) + { + ACE_NEW_RETURN (ts_keys, + ACE_TSS_Keys, + 0); + // Store the dynamically allocated pointer in thread-specific + // storage. + if (ACE_OS::thr_setspecific (in_use_, + ACE_reinterpret_cast (void *, + ts_keys)) == -1) + { + delete ts_keys; + return 0; // Major problems, this should *never* happen! + } + } + + return ts_keys; +} + +# if defined (ACE_HAS_TSS_EMULATION) +u_int ACE_TSS_Emulation::total_keys_ = 0; + +ACE_TSS_Keys ACE_TSS_Emulation::tss_keys_used_; + +ACE_TSS_Emulation::ACE_TSS_DESTRUCTOR +ACE_TSS_Emulation::tss_destructor_[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX] + = { 0 }; + +# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + +int ACE_TSS_Emulation::key_created_ = 0; + +ACE_OS_thread_key_t ACE_TSS_Emulation::native_tss_key_; + +/* static */ +# if defined (ACE_HAS_THR_C_FUNC) +extern "C" +void +ACE_TSS_Emulation_cleanup (void *ptr) +{ + ACE_UNUSED_ARG (ptr); + // Really this must be used for ACE_TSS_Emulation code to make the TSS + // cleanup +} +#else +void +ACE_TSS_Emulation_cleanup (void *ptr) +{ + ACE_UNUSED_ARG (ptr); + // Really this must be used for ACE_TSS_Emulation code to make the TSS + // cleanup +} +# endif /* ACE_HAS_THR_C_FUNC */ + +void ** +ACE_TSS_Emulation::tss_base (void* ts_storage[], u_int *ts_created) +{ + // TSS Singleton implementation. + + // Create the one native TSS key, if necessary. + if (key_created_ == 0) + { + // Double-checked lock . . . + ACE_TSS_BASE_GUARD + + if (key_created_ == 0) + { + ACE_NO_HEAP_CHECK; + if (ACE_OS::thr_keycreate (&native_tss_key_, + &ACE_TSS_Emulation_cleanup) != 0) + { + return 0; // Major problems, this should *never* happen! + } + key_created_ = 1; + } + } + + void **old_ts_storage = 0; + + // Get the tss_storage from thread-OS specific storage. + if (ACE_OS::thr_getspecific (native_tss_key_, + (void **) &old_ts_storage) == -1) + return 0; // This should not happen! + + // Check to see if this is the first time in for this thread. + // This block can also be entered after a fork () in the child process, + // at least on Pthreads Draft 4 platforms. + if (old_ts_storage == 0) + { + if (ts_created) + *ts_created = 1u; + + // Use the ts_storage passed as argument, if non-zero. It is + // possible that this has been implemented in the stack. At the + // moment, this is unknown. The cleanup must not do nothing. + // If ts_storage is zero, allocate (and eventually leak) the + // storage array. + if (ts_storage == 0) + { + ACE_NO_HEAP_CHECK; + + ACE_NEW_RETURN (ts_storage, + void*[ACE_TSS_THREAD_KEYS_MAX], + 0); + + // Zero the entire TSS array. Do it manually instead of + // using memset, for optimum speed. Though, memset may be + // faster :-) + void **tss_base_p = ts_storage; + + for (u_int i = 0; + i < ACE_TSS_THREAD_KEYS_MAX; + ++i) + *tss_base_p++ = 0; + } + + // Store the pointer in thread-specific storage. It gets + // deleted via the ACE_TSS_Emulation_cleanup function when the + // thread terminates. + if (ACE_OS::thr_setspecific (native_tss_key_, + (void *) ts_storage) != 0) + return 0; // Major problems, this should *never* happen! + } + else + if (ts_created) + ts_created = 0; + + return ts_storage ? ts_storage : old_ts_storage; +} +# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ + +u_int +ACE_TSS_Emulation::total_keys () +{ + ACE_OS_Recursive_Thread_Mutex_Guard ( + *ACE_static_cast (ACE_recursive_thread_mutex_t *, + ACE_OS_Object_Manager::preallocated_object[ + ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK])); + + return total_keys_; +} + +int +ACE_TSS_Emulation::next_key (ACE_thread_key_t &key) +{ + ACE_OS_Recursive_Thread_Mutex_Guard ( + *ACE_static_cast (ACE_recursive_thread_mutex_t *, + ACE_OS_Object_Manager::preallocated_object[ + ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK])); + + if (total_keys_ < ACE_TSS_THREAD_KEYS_MAX) + { + u_int counter = 0; + // Loop through all possible keys and check whether a key is free + for ( ;counter < ACE_TSS_THREAD_KEYS_MAX; counter++) + { + ACE_thread_key_t localkey; +# if defined (ACE_HAS_NONSCALAR_THREAD_KEY_T) + ACE_OS::memset (&localkey, 0, sizeof (ACE_thread_key_t)); + ACE_OS::memcpy (&localkey, &counter_, sizeof (u_int)); +# else + localkey = counter; +# endif /* ACE_HAS_NONSCALAR_THREAD_KEY_T */ + // If the key is not set as used, we can give out this key, if not + // we have to search further + if (tss_keys_used_.is_set(localkey) == 0) + { + tss_keys_used_.test_and_set(localkey); + key = localkey; + break; + } + } + + ++total_keys_; + return 0; + } + else + { + key = ACE_OS::NULL_key; + return -1; + } +} + +int +ACE_TSS_Emulation::release_key (ACE_thread_key_t key) +{ + ACE_OS_Recursive_Thread_Mutex_Guard ( + *ACE_static_cast (ACE_recursive_thread_mutex_t *, + ACE_OS_Object_Manager::preallocated_object[ + ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK])); + + if (tss_keys_used_.test_and_clear (key) == 0) + { + --total_keys_; + return 0; + } + return 1; +} + +void * +ACE_TSS_Emulation::tss_open (void *ts_storage[ACE_TSS_THREAD_KEYS_MAX]) +{ +# if defined (ACE_PSOS) + u_long tss_base; + + // Use the supplied array for this thread's TSS. + tss_base = (u_long) ts_storage; + t_setreg (0, PSOS_TASK_REG_TSS, tss_base); + + // Zero the entire TSS array. + void **tss_base_p = ts_storage; + for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p) + { + *tss_base_p = 0; + } + + return (void *) tss_base; +# else /* ! ACE_PSOS */ +# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + // On VxWorks, in particular, don't check to see if the field + // is 0. It isn't always, specifically, when a program is run + // directly by the shell (without spawning a new task) after + // another program has been run. + + u_int ts_created = 0; + tss_base (ts_storage, &ts_created); + if (ts_created) + { +# else /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */ + tss_base () = ts_storage; +# endif + + // Zero the entire TSS array. Do it manually instead of using + // memset, for optimum speed. Though, memset may be faster :-) + void **tss_base_p = tss_base (); + for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p) + { + *tss_base_p = 0; + } + + return tss_base (); +# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + } + else + { + return 0; + } +# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ +# endif /* ! ACE_PSOS */ +} + +void +ACE_TSS_Emulation::tss_close () +{ +#if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + // Free native_tss_key_ here. +#endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ +} + +# endif /* ACE_HAS_TSS_EMULATION */ + +#endif /* WIN32 || ACE_HAS_TSS_EMULATION */ + +void +ACE_OS::cleanup_tss (const u_int main_thread) +{ +#if defined (ACE_HAS_TSS_EMULATION) || defined (ACE_WIN32) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) + // Call TSS destructors for current thread. + ACE_TSS_Cleanup::instance ()->exit (0); +#endif /* ACE_HAS_TSS_EMULATION || ACE_WIN32 || ACE_PSOS_HAS_TSS */ + + if (main_thread) + { +#if !defined (ACE_HAS_TSS_EMULATION) && !defined (ACE_HAS_MINIMAL_ACE_OS) + // Just close the ACE_Log_Msg for the current (which should be + // main) thread. We don't have TSS emulation; if there's native + // TSS, it should call its destructors when the main thread + // exits. + ACE_Base_Thread_Adapter::close_log_msg (); +#endif /* ! ACE_HAS_TSS_EMULATION && ! ACE_HAS_MINIMAL_ACE_OS */ + +#if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) +#if ! defined (ACE_HAS_TSS_EMULATION) + // Don't do this with TSS_Emulation, because the the + // ACE_TSS_Cleanup::instance () has already exited (). We can't + // safely access the TSS values that were created by the main + // thread. + + // Remove all TSS_Info table entries. + ACE_TSS_Cleanup::instance ()->free_all_keys_left (); +#endif /* ! ACE_HAS_TSS_EMULATION */ + + // Finally, free up the ACE_TSS_Cleanup instance. This method gets + // called by the ACE_Object_Manager. + delete ACE_TSS_Cleanup::instance (); +#endif /* WIN32 || ACE_HAS_TSS_EMULATION || ACE_PSOS_HAS_TSS */ + +#if defined (ACE_HAS_TSS_EMULATION) + ACE_TSS_Emulation::tss_close (); +#endif /* ACE_HAS_TSS_EMULATION */ + } +} + +#if !defined(ACE_WIN32) && defined (__IBMCPP__) && (__IBMCPP__ >= 400) +#define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \ + (*THR_ID = ::_beginthreadex ((void(_Optlink*)(void*))ENTRY_POINT, STACK, STACKSIZE, ARGS), *THR_ID) +#elif defined(ACE_WIN32) && defined (__IBMCPP__) && (__IBMCPP__ >= 400) + +struct __IBMCPP__thread_params { + __IBMCPP__thread_params(ACE_THR_C_FUNC e, LPVOID a) + :entry_point(e),args(a) {} + ACE_THR_C_FUNC entry_point; + LPVOID args; +}; + +#pragma handler(initThread) +extern "C" DWORD __stdcall __IBMCPP__initThread(void *arg) +{ + // Must reset 387 since using CreateThread + _fpreset(); + + // Dispatch user function... + auto_ptr<__IBMCPP__thread_params> parms((__IBMCPP__thread_params *)arg); + (*parms->entry_point)(parms->args); + _endthread(); + return 0; +} + +HANDLE WINAPI __IBMCPP__beginthreadex(void *stack, + DWORD stacksize, + ACE_THR_C_FUNC entry_point, + LPVOID args, + DWORD flags, + LPDWORD thr_id) +{ + return CreateThread(NULL, + stacksize, + (LPTHREAD_START_ROUTINE)__IBMCPP__initThread, + new __IBMCPP__thread_params(entry_point, args), + flags, + thr_id); +} + +#define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \ + __IBMCPP__beginthreadex(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) + +#elif defined (ACE_HAS_WINCE) && defined (UNDER_CE) && (UNDER_CE >= 211) +#define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \ + CreateThread (NULL, STACKSIZE, (unsigned long (__stdcall *) (void *)) ENTRY_POINT, ARGS, (FLAGS) & CREATE_SUSPENDED, (unsigned long *) THR_ID) +#elif defined(ACE_HAS_WTHREADS) + // Green Hills compiler gets confused when __stdcall is imbedded in + // parameter list, so we define the type ACE_WIN32THRFUNC_T and use it + // instead. + typedef unsigned (__stdcall *ACE_WIN32THRFUNC_T)(void*); +#define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \ + ::_beginthreadex (STACK, STACKSIZE, (ACE_WIN32THRFUNC_T) ENTRY_POINT, ARGS, FLAGS, (unsigned int *) THR_ID) +#endif /* defined (__IBMCPP__) && (__IBMCPP__ >= 400) */ + +#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) +int ACE_SEH_Default_Exception_Selector (void *) +{ +#if 0 + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("(%t) Win32 structured exception exiting thread\n"))); +#endif /* 0 */ + return (DWORD) ACE_SEH_DEFAULT_EXCEPTION_HANDLING_ACTION; +} + +int ACE_SEH_Default_Exception_Handler (void *) +{ + return 0; +} +#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ + +extern "C" void +ace_cleanup_destroyer (ACE_Cleanup *object, void *param) +{ + object->cleanup (param); +} + +int +ACE_OS::thr_create (ACE_THR_FUNC func, + void *args, + long flags, + ACE_thread_t *thr_id, + ACE_hthread_t *thr_handle, + long priority, + void *stack, + size_t stacksize, + ACE_Base_Thread_Adapter *thread_adapter) +{ + ACE_OS_TRACE ("ACE_OS::thr_create"); + + if (ACE_BIT_DISABLED (flags, THR_DETACHED) && + ACE_BIT_DISABLED (flags, THR_JOINABLE)) + ACE_SET_BITS (flags, THR_JOINABLE); + +# if defined (ACE_NO_THREAD_ADAPTER) +# define ACE_THREAD_FUNCTION func +# define ACE_THREAD_ARGUMENT args +# else /* ! defined (ACE_NO_THREAD_ADAPTER) */ +# if defined (ACE_PSOS) +# define ACE_THREAD_FUNCTION (PSOS_TASK_ENTRY_POINT) thread_args->entry_point () +# else +# define ACE_THREAD_FUNCTION thread_args->entry_point () +# endif /* defined (ACE_PSOS) */ +# define ACE_THREAD_ARGUMENT thread_args +# endif /* ! defined (ACE_NO_THREAD_ADAPTER) */ + +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_Base_Thread_Adapter *thread_args; + if (thread_adapter == 0) + ACE_NEW_RETURN (thread_args, + ACE_OS_Thread_Adapter (func, args, + (ACE_THR_C_FUNC) ace_thread_adapter), + -1); + else + thread_args = thread_adapter; + +# if defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE) + if (stacksize < ACE_NEEDS_HUGE_THREAD_STACKSIZE) + stacksize = ACE_NEEDS_HUGE_THREAD_STACKSIZE; +# endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */ + + ACE_thread_t tmp_thr; + + if (thr_id == 0) + thr_id = &tmp_thr; + + ACE_hthread_t tmp_handle; + if (thr_handle == 0) + thr_handle = &tmp_handle; + + int result = 0; + pace_pthread_attr_t attr; + if (::pace_pthread_attr_init (&attr) != 0) + return -1; + + if (stacksize != 0) + { + size_t size = stacksize; +# if defined (PACE_PTHREAD_STACK_MIN) + if (size < ACE_static_cast (pace_size_t, PACE_PTHREAD_STACK_MIN)) + size = PACE_PTHREAD_STACK_MIN; +# endif /* PACE_PTHREAD_STACK_MIN */ + + if (ACE_ADAPT_RETVAL(::pace_pthread_attr_setstacksize (&attr, size), result) == -1) + { + ::pace_pthread_attr_destroy (&attr); + return -1; + } + } + + // *** Set Stack Address + if (stack != 0) + { + if (::pace_pthread_attr_setstackaddr (&attr, stack) != 0) + { + ::pace_pthread_attr_destroy (&attr); + return -1; + } + } + + // *** Deal with various attributes + if (flags != 0) + { + // *** Set Detach state + if (ACE_BIT_ENABLED (flags, THR_DETACHED) + || ACE_BIT_ENABLED (flags, THR_JOINABLE)) + { + int dstate = PACE_PTHREAD_CREATE_JOINABLE; + + if (ACE_BIT_ENABLED (flags, THR_DETACHED)) + dstate = PACE_PTHREAD_CREATE_DETACHED; + if (ACE_ADAPT_RETVAL(::pace_pthread_attr_setdetachstate (&attr, dstate), + result) != 0) + { + ::pace_pthread_attr_destroy (&attr); + return -1; + } + } + + // *** Set Policy + // If we wish to set the priority explicitly, we have to enable + // explicit scheduling, and a policy, too. + if (priority != ACE_DEFAULT_THREAD_PRIORITY) + { + ACE_SET_BITS (flags, THR_EXPLICIT_SCHED); + if (ACE_BIT_DISABLED (flags, THR_SCHED_FIFO) + && ACE_BIT_DISABLED (flags, THR_SCHED_RR) + && ACE_BIT_DISABLED (flags, THR_SCHED_DEFAULT)) + ACE_SET_BITS (flags, THR_SCHED_DEFAULT); + } + + if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO) + || ACE_BIT_ENABLED (flags, THR_SCHED_RR) + || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT)) + { + int spolicy; + +# if defined (ACE_HAS_ONLY_SCHED_OTHER) + // SunOS, thru version 5.6, only supports SCHED_OTHER. + spolicy = SCHED_OTHER; +# else + // Make sure to enable explicit scheduling, in case we didn't + // enable it above (for non-default priority). + ACE_SET_BITS (flags, THR_EXPLICIT_SCHED); + + if (ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT)) + spolicy = SCHED_OTHER; + else if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)) + spolicy = SCHED_FIFO; +# if defined (SCHED_IO) + else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO)) + spolicy = SCHED_IO; +# else + else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO)) + { + errno = ENOSYS; + return -1; + } +# endif /* SCHED_IO */ + else + spolicy = SCHED_RR; + + ACE_ADAPT_RETVAL(::pace_pthread_attr_setschedpolicy (&attr, spolicy), + result); + if (result != 0) + { + ::pace_pthread_attr_destroy (&attr); + return -1; + } + } + + // *** Set Priority (use reasonable default priorities) +# if defined(ACE_HAS_PTHREADS_STD) + // If we wish to explicitly set a scheduling policy, we also + // have to specify a priority. We choose a "middle" priority as + // default. Maybe this is also necessary on other POSIX'ish + // implementations? + if ((ACE_BIT_ENABLED (flags, THR_SCHED_FIFO) + || ACE_BIT_ENABLED (flags, THR_SCHED_RR) + || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT)) + && priority == ACE_DEFAULT_THREAD_PRIORITY) + { + if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)) + priority = ACE_THR_PRI_FIFO_DEF; + else if (ACE_BIT_ENABLED (flags, THR_SCHED_RR)) + priority = ACE_THR_PRI_RR_DEF; + else // THR_SCHED_DEFAULT + priority = ACE_THR_PRI_OTHER_DEF; + } +# endif /* ACE_HAS_PTHREADS_STD */ + if (priority != ACE_DEFAULT_THREAD_PRIORITY) + { + pace_sched_param sparam; + ACE_OS::memset ((void *) &sparam, 0, sizeof sparam); + sparam.sched_priority = priority; +# if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER) + // SunOS, through 5.6, POSIX only allows priorities > 0 to + // ::pthread_attr_setschedparam. If a priority of 0 was + // requested, set the thread priority after creating it, below. + if (priority > 0) +# endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */ + { + ACE_ADAPT_RETVAL(::pace_pthread_attr_setschedparam (&attr, &sparam), + result); + if (result != 0) + { + ::pace_pthread_attr_destroy (&attr); + return -1; + } + } + } + + if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED) + || ACE_BIT_ENABLED (flags, THR_EXPLICIT_SCHED)) + { + int sched = PTHREAD_EXPLICIT_SCHED; + if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED)) + sched = PTHREAD_INHERIT_SCHED; + if (::pace_pthread_attr_setinheritsched (&attr, sched) != 0) + { + ::pace_pthread_attr_destroy (&attr); + return -1; + } + } + + // *** Set Scope +# if !defined (ACE_LACKS_THREAD_PROCESS_SCOPING) + if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM) + || ACE_BIT_ENABLED (flags, THR_SCOPE_PROCESS)) + { +# if defined (ACE_CONFIG_LINUX_H) + // LinuxThreads do not have support for PTHREAD_SCOPE_PROCESS. + int scope = PTHREAD_SCOPE_SYSTEM; +# else /* ACE_CONFIG_LINUX_H */ + int scope = PTHREAD_SCOPE_PROCESS; +# endif /* ACE_CONFIG_LINUX_H */ + if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM)) + scope = PTHREAD_SCOPE_SYSTEM; + + if (::pace_pthread_attr_setscope (&attr, scope) != 0) + { + ::pace_pthread_attr_destroy (&attr); + return -1; + } + } +# endif /* !ACE_LACKS_THREAD_PROCESS_SCOPING */ + + if (ACE_BIT_ENABLED (flags, THR_NEW_LWP)) + { + // Increment the number of LWPs by one to emulate the + // SunOS semantics. + int lwps = ACE_OS::thr_getconcurrency (); + if (lwps == -1) + { + if (errno == ENOTSUP) + // Suppress the ENOTSUP because it's harmless. + errno = 0; + else + // This should never happen on SunOS: + // ::thr_getconcurrency () should always succeed. + return -1; + } + else if (ACE_OS::thr_setconcurrency (lwps + 1) == -1) + { + if (errno == ENOTSUP) + { + // Unlikely: ::thr_getconcurrency () is supported + // but ::thr_setconcurrency () is not? + } + else + return -1; + } + } + } + + ACE_OSCALL (ACE_ADAPT_RETVAL (::pace_pthread_create (thr_id, + &attr, + PACE_THR_ENTRY_CAST (void * (*)(void *)) thread_args->entry_point (), + thread_args), + result), + int, -1, result); + ::pace_pthread_attr_destroy (&attr); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + + // This is a SunOS or POSIX implementation of pthreads, + // where we assume that ACE_thread_t and ACE_hthread_t are the same. + // If this *isn't* correct on some platform, please let us know. + if (result != -1) + *thr_handle = *thr_id; + +# if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER) + // SunOS prior to 5.7: + + // If the priority is 0, then we might have to set it now + // because we couldn't set it with + // ::pthread_attr_setschedparam, as noted above. This doesn't + // provide strictly correct behavior, because the thread was + // created (above) with the priority of its parent. (That + // applies regardless of the inherit_sched attribute: if it + // was PTHREAD_INHERIT_SCHED, then it certainly inherited its + // parent's priority. If it was PTHREAD_EXPLICIT_SCHED, then + // "attr" was initialized by the SunOS ::pthread_attr_init + // () to contain NULL for the priority, which indicated to + // SunOS ::pthread_create () to inherit the parent + // priority.) + if (priority == 0) + { + // Check the priority of this thread, which is the parent + // of the newly created thread. If it is 0, then the + // newly created thread will have inherited the priority + // of 0, so there's no need to explicitly set it. + struct sched_param sparam; + int policy = 0; + ACE_OSCALL (ACE_ADAPT_RETVAL (::pace_pthread_getschedparam (thr_self (), + &policy, + &sparam), + result), int, + -1, result); + + // The only policy supported by by SunOS, thru version 5.6, + // is SCHED_OTHER, so that's hard-coded here. + policy = ACE_SCHED_OTHER; + + if (sparam.sched_priority != 0) + { + ACE_OS::memset ((void *) &sparam, 0, sizeof sparam); + // The memset to 0 sets the priority to 0, so we don't need + // to explicitly set sparam.sched_priority. + + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_setschedparam ( + *thr_id, + policy, + &sparam), + result), + int, -1); + } + } +# endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */ + return result; + +#else /* ACE_HAS_PACE && !ACE_WIN32 */ + + ACE_Base_Thread_Adapter *thread_args; + if (thread_adapter == 0) + +# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) + ACE_NEW_RETURN (thread_args, + ACE_OS_Thread_Adapter (func, args, + (ACE_THR_C_FUNC) ace_thread_adapter, + ACE_OS_Object_Manager::seh_except_selector(), + ACE_OS_Object_Manager::seh_except_handler()), + -1); +# else + ACE_NEW_RETURN (thread_args, + ACE_OS_Thread_Adapter (func, args, + (ACE_THR_C_FUNC) ace_thread_adapter), + -1); + +# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ + else + thread_args = thread_adapter; + +# if defined (ACE_HAS_THREADS) + + // *** Set Stack Size +# if defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE) + if (stacksize < ACE_NEEDS_HUGE_THREAD_STACKSIZE) + stacksize = ACE_NEEDS_HUGE_THREAD_STACKSIZE; +# endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */ + +# if !defined (VXWORKS) + // On VxWorks, the OS will provide a task name if the user doesn't. + // So, we don't need to create a tmp_thr. If the caller of this + // member function is the Thread_Manager, than thr_id will be non-zero + // anyways. + ACE_thread_t tmp_thr; + + if (thr_id == 0) + thr_id = &tmp_thr; +# endif /* ! VXWORKS */ + + ACE_hthread_t tmp_handle; + if (thr_handle == 0) + thr_handle = &tmp_handle; + +# if defined (ACE_HAS_PTHREADS) + + int result; + pthread_attr_t attr; +# if defined (ACE_HAS_PTHREADS_DRAFT4) + if (::pthread_attr_create (&attr) != 0) +# else /* ACE_HAS_PTHREADS_DRAFT4 */ + if (::pthread_attr_init (&attr) != 0) +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + return -1; + +# if defined (CHORUS) + // If it is a super actor, we can't set stacksize. But for the time + // being we are all non-super actors. Should be fixed to take care + // of super actors!!! + if (stacksize == 0) + stacksize = ACE_CHORUS_DEFAULT_MIN_STACK_SIZE; + else if (stacksize < ACE_CHORUS_DEFAULT_MIN_STACK_SIZE) + stacksize = ACE_CHORUS_DEFAULT_MIN_STACK_SIZE; +# endif /*CHORUS */ + + if (stacksize != 0) + { + size_t size = stacksize; + +# if defined (PTHREAD_STACK_MIN) + if (size < ACE_static_cast (size_t, PTHREAD_STACK_MIN)) + size = PTHREAD_STACK_MIN; +# endif /* PTHREAD_STACK_MIN */ + +# if !defined (ACE_LACKS_THREAD_STACK_SIZE) // JCEJ 12/17/96 +# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) + if (::pthread_attr_setstacksize (&attr, size) != 0) +# else + if (ACE_ADAPT_RETVAL(pthread_attr_setstacksize (&attr, size), result) == -1) +# endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */ + { +# if defined (ACE_HAS_PTHREADS_DRAFT4) + ::pthread_attr_delete (&attr); +# else /* ACE_HAS_PTHREADS_DRAFT4 */ + ::pthread_attr_destroy (&attr); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + return -1; + } +# else + ACE_UNUSED_ARG (size); +# endif /* !ACE_LACKS_THREAD_STACK_SIZE */ + } + + // *** Set Stack Address +# if !defined (ACE_LACKS_THREAD_STACK_ADDR) + if (stack != 0) + { + if (::pthread_attr_setstackaddr (&attr, stack) != 0) + { +# if defined (ACE_HAS_PTHREADS_DRAFT4) + ::pthread_attr_delete (&attr); +# else /* ACE_HAS_PTHREADS_DRAFT4 */ + ::pthread_attr_destroy (&attr); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + return -1; + } + } +# else + ACE_UNUSED_ARG (stack); +# endif /* !ACE_LACKS_THREAD_STACK_ADDR */ + + // *** Deal with various attributes + if (flags != 0) + { + // *** Set Detach state +# if !defined (ACE_LACKS_SETDETACH) + if (ACE_BIT_ENABLED (flags, THR_DETACHED) + || ACE_BIT_ENABLED (flags, THR_JOINABLE)) + { + int dstate = PTHREAD_CREATE_JOINABLE; + + if (ACE_BIT_ENABLED (flags, THR_DETACHED)) + dstate = PTHREAD_CREATE_DETACHED; + +# if defined (ACE_HAS_PTHREADS_DRAFT4) + if (::pthread_attr_setdetach_np (&attr, dstate) != 0) +# else /* ACE_HAS_PTHREADS_DRAFT4 */ +# if defined (ACE_HAS_PTHREADS_DRAFT6) + if (::pthread_attr_setdetachstate (&attr, &dstate) != 0) +# else + if (ACE_ADAPT_RETVAL(::pthread_attr_setdetachstate (&attr, dstate), + result) != 0) +# endif /* ACE_HAS_PTHREADS_DRAFT6 */ +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + { +# if defined (ACE_HAS_PTHREADS_DRAFT4) + ::pthread_attr_delete (&attr); +# else /* ACE_HAS_PTHREADS_DRAFT4 */ + ::pthread_attr_destroy (&attr); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + return -1; + } + } + + // Note: if ACE_LACKS_SETDETACH and THR_DETACHED is enabled, we + // call ::pthread_detach () below. If THR_DETACHED is not + // enabled, we call ::pthread_detach () in the Thread_Manager, + // after joining with the thread. +# endif /* ACE_LACKS_SETDETACH */ + + // *** Set Policy +# if !defined (ACE_LACKS_SETSCHED) + // If we wish to set the priority explicitly, we have to enable + // explicit scheduling, and a policy, too. + if (priority != ACE_DEFAULT_THREAD_PRIORITY) + { + ACE_SET_BITS (flags, THR_EXPLICIT_SCHED); + if (ACE_BIT_DISABLED (flags, THR_SCHED_FIFO) + && ACE_BIT_DISABLED (flags, THR_SCHED_RR) + && ACE_BIT_DISABLED (flags, THR_SCHED_DEFAULT)) + ACE_SET_BITS (flags, THR_SCHED_DEFAULT); + } + + if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO) + || ACE_BIT_ENABLED (flags, THR_SCHED_RR) + || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT)) + { + int spolicy; + +# if defined (ACE_HAS_ONLY_SCHED_OTHER) + // SunOS, thru version 5.6, only supports SCHED_OTHER. + spolicy = SCHED_OTHER; +# else + // Make sure to enable explicit scheduling, in case we didn't + // enable it above (for non-default priority). + ACE_SET_BITS (flags, THR_EXPLICIT_SCHED); + + if (ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT)) + spolicy = SCHED_OTHER; + else if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)) + spolicy = SCHED_FIFO; +# if defined (SCHED_IO) + else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO)) + spolicy = SCHED_IO; +# else + else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO)) + { + errno = ENOSYS; + return -1; + } +# endif /* SCHED_IO */ + else + spolicy = SCHED_RR; + +# if defined (ACE_HAS_FSU_PTHREADS) + int ret; + switch (spolicy) + { + case SCHED_FIFO: + case SCHED_RR: + ret = 0; + break; + default: + ret = 22; + break; + } + if (ret != 0) + { + ::pthread_attr_destroy (&attr); + return -1; + } +# endif /* ACE_HAS_FSU_PTHREADS */ + +# endif /* ACE_HAS_ONLY_SCHED_OTHER */ + +# if defined (ACE_HAS_PTHREADS_DRAFT4) + result = ::pthread_attr_setsched (&attr, spolicy); +# elif defined (ACE_HAS_PTHREADS_DRAFT6) + result = ::pthread_attr_setschedpolicy (&attr, spolicy); +# else /* draft 7 or std */ + ACE_ADAPT_RETVAL(::pthread_attr_setschedpolicy (&attr, spolicy), + result); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + if (result != 0) + { +# if defined (ACE_HAS_PTHREADS_DRAFT4) + ::pthread_attr_delete (&attr); +# else /* ACE_HAS_PTHREADS_DRAFT4 */ + ::pthread_attr_destroy (&attr); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + return -1; + } + } + + // *** Set Priority (use reasonable default priorities) +# if defined(ACE_HAS_PTHREADS_STD) + // If we wish to explicitly set a scheduling policy, we also + // have to specify a priority. We choose a "middle" priority as + // default. Maybe this is also necessary on other POSIX'ish + // implementations? + if ((ACE_BIT_ENABLED (flags, THR_SCHED_FIFO) + || ACE_BIT_ENABLED (flags, THR_SCHED_RR) + || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT)) + && priority == ACE_DEFAULT_THREAD_PRIORITY) + { + if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)) + priority = ACE_THR_PRI_FIFO_DEF; + else if (ACE_BIT_ENABLED (flags, THR_SCHED_RR)) + priority = ACE_THR_PRI_RR_DEF; + else // THR_SCHED_DEFAULT + priority = ACE_THR_PRI_OTHER_DEF; + } +# endif /* ACE_HAS_PTHREADS_STD */ + if (priority != ACE_DEFAULT_THREAD_PRIORITY) + { + struct sched_param sparam; + ACE_OS::memset ((void *) &sparam, 0, sizeof sparam); + +# if defined (ACE_HAS_IRIX62_THREADS) + sparam.sched_priority = ACE_MIN (priority, + (long) PTHREAD_MAX_PRIORITY); +# elif defined (PTHREAD_MAX_PRIORITY) && !defined(ACE_HAS_PTHREADS_STD) + /* For MIT pthreads... */ + sparam.prio = ACE_MIN (priority, PTHREAD_MAX_PRIORITY); +# elif defined(ACE_HAS_PTHREADS_STD) && !defined (ACE_HAS_STHREADS) + // The following code forces priority into range. + if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)) + sparam.sched_priority = + ACE_MIN (ACE_THR_PRI_FIFO_MAX, + ACE_MAX (ACE_THR_PRI_FIFO_MIN, priority)); + else if (ACE_BIT_ENABLED(flags, THR_SCHED_RR)) + sparam.sched_priority = + ACE_MIN (ACE_THR_PRI_RR_MAX, + ACE_MAX (ACE_THR_PRI_RR_MIN, priority)); + else // Default policy, whether set or not + sparam.sched_priority = + ACE_MIN (ACE_THR_PRI_OTHER_MAX, + ACE_MAX (ACE_THR_PRI_OTHER_MIN, priority)); +# elif defined (PRIORITY_MAX) + sparam.sched_priority = ACE_MIN (priority, + (long) PRIORITY_MAX); +# else + sparam.sched_priority = priority; +# endif /* ACE_HAS_IRIX62_THREADS */ + +# if defined (ACE_HAS_FSU_PTHREADS) + if (sparam.sched_priority >= PTHREAD_MIN_PRIORITY + && sparam.sched_priority <= PTHREAD_MAX_PRIORITY) + attr.prio = sparam.sched_priority; + else + { + pthread_attr_destroy (&attr); + errno = EINVAL; + return -1; + } +# else + { +# if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER) + // SunOS, through 5.6, POSIX only allows priorities > 0 to + // ::pthread_attr_setschedparam. If a priority of 0 was + // requested, set the thread priority after creating it, below. + if (priority > 0) +# endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */ + { +# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) + result = ::pthread_attr_setprio (&attr, + sparam.sched_priority); +# else /* this is draft 7 or std */ + ACE_ADAPT_RETVAL(::pthread_attr_setschedparam (&attr, &sparam), + result); +# endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */ + if (result != 0) + { +# if defined (ACE_HAS_PTHREADS_DRAFT4) + ::pthread_attr_delete (&attr); +# else /* ACE_HAS_PTHREADS_DRAFT4 */ + ::pthread_attr_destroy (&attr); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + return -1; + } + } + } +# endif /* ACE_HAS_FSU_PTHREADS */ + } + + // *** Set scheduling explicit or inherited + if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED) + || ACE_BIT_ENABLED (flags, THR_EXPLICIT_SCHED)) + { +# if defined (ACE_HAS_PTHREADS_DRAFT4) + int sched = PTHREAD_DEFAULT_SCHED; +# else /* ACE_HAS_PTHREADS_DRAFT4 */ + int sched = PTHREAD_EXPLICIT_SCHED; +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED)) + sched = PTHREAD_INHERIT_SCHED; + if (::pthread_attr_setinheritsched (&attr, sched) != 0) + { +# if defined (ACE_HAS_PTHREADS_DRAFT4) + ::pthread_attr_delete (&attr); +# else /* ACE_HAS_PTHREADS_DRAFT4 */ + ::pthread_attr_destroy (&attr); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + return -1; + } + } +# else /* ACE_LACKS_SETSCHED */ + ACE_UNUSED_ARG (priority); +# endif /* ACE_LACKS_SETSCHED */ + + // *** Set Scope +# if !defined (ACE_LACKS_THREAD_PROCESS_SCOPING) + if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM) + || ACE_BIT_ENABLED (flags, THR_SCOPE_PROCESS)) + { +# if defined (ACE_CONFIG_LINUX_H) || defined (HPUX) + // LinuxThreads do not have support for PTHREAD_SCOPE_PROCESS. + // Neither does HPUX (up to HP-UX 11.00, as far as I know). + int scope = PTHREAD_SCOPE_SYSTEM; +# else /* ACE_CONFIG_LINUX_H */ + int scope = PTHREAD_SCOPE_PROCESS; +# endif /* ACE_CONFIG_LINUX_H */ + if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM)) + scope = PTHREAD_SCOPE_SYSTEM; + + if (::pthread_attr_setscope (&attr, scope) != 0) + { +# if defined (ACE_HAS_PTHREADS_DRAFT4) + ::pthread_attr_delete (&attr); +# else /* ACE_HAS_PTHREADS_DRAFT4 */ + ::pthread_attr_destroy (&attr); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + return -1; + } + } +# endif /* !ACE_LACKS_THREAD_PROCESS_SCOPING */ + + if (ACE_BIT_ENABLED (flags, THR_NEW_LWP)) + { + // Increment the number of LWPs by one to emulate the + // SunOS semantics. + int lwps = ACE_OS::thr_getconcurrency (); + if (lwps == -1) + { + if (errno == ENOTSUP) + // Suppress the ENOTSUP because it's harmless. + errno = 0; + else + // This should never happen on SunOS: + // ::thr_getconcurrency () should always succeed. + return -1; + } + else if (ACE_OS::thr_setconcurrency (lwps + 1) == -1) + { + if (errno == ENOTSUP) + { + // Unlikely: ::thr_getconcurrency () is supported but + // ::thr_setconcurrency () is not? + } + else + return -1; + } + } + } + +# if defined (ACE_HAS_PTHREADS_DRAFT4) + ACE_OSCALL (::pthread_create (thr_id, attr, + thread_args->entry_point (), + thread_args), + int, -1, result); + +# if defined (ACE_LACKS_SETDETACH) + if (ACE_BIT_ENABLED (flags, THR_DETACHED)) + { +# if defined (HPUX_10) + // HP-UX DCE threads' pthread_detach will smash thr_id if it's + // just given as an argument. This will cause + // ACE_Thread_Manager (if it's doing this create) to lose track + // of the new thread since the ID will be passed back equal to + // 0. So give pthread_detach a junker to scribble on. + ACE_thread_t junker; + cma_handle_assign(thr_id, &junker); + ::pthread_detach (&junker); +# else + ::pthread_detach (thr_id); +# endif /* HPUX_10 */ + } +# endif /* ACE_LACKS_SETDETACH */ + + ::pthread_attr_delete (&attr); + +# elif defined (ACE_HAS_PTHREADS_DRAFT6) + ACE_OSCALL (::pthread_create (thr_id, &attr, + thread_args->entry_point (), + thread_args), + int, -1, result); + ::pthread_attr_destroy (&attr); + +# else /* this is draft 7 or std */ + ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (thr_id, + &attr, + thread_args->entry_point (), + thread_args), + result), + int, -1, result); + ::pthread_attr_destroy (&attr); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + + // This is a SunOS or POSIX implementation of pthreads, where we + // assume that ACE_thread_t and ACE_hthread_t are the same. If this + // *isn't* correct on some platform, please let us know. + if (result != -1) + *thr_handle = *thr_id; + +# if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER) + // SunOS prior to 5.7: + + // If the priority is 0, then we might have to set it now because we + // couldn't set it with ::pthread_attr_setschedparam, as noted + // above. This doesn't provide strictly correct behavior, because + // the thread was created (above) with the priority of its parent. + // (That applies regardless of the inherit_sched attribute: if it + // was PTHREAD_INHERIT_SCHED, then it certainly inherited its + // parent's priority. If it was PTHREAD_EXPLICIT_SCHED, then "attr" + // was initialized by the SunOS ::pthread_attr_init () to contain + // NULL for the priority, which indicated to SunOS ::pthread_create + // () to inherit the parent priority.) + if (priority == 0) + { + // Check the priority of this thread, which is the parent + // of the newly created thread. If it is 0, then the + // newly created thread will have inherited the priority + // of 0, so there's no need to explicitly set it. + struct sched_param sparam; + int policy = 0; + ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_getschedparam (thr_self (), + &policy, + &sparam), + result), int, + -1, result); + + // The only policy supported by by SunOS, thru version 5.6, + // is SCHED_OTHER, so that's hard-coded here. + policy = ACE_SCHED_OTHER; + + if (sparam.sched_priority != 0) + { + ACE_OS::memset ((void *) &sparam, 0, sizeof sparam); + // The memset to 0 sets the priority to 0, so we don't need + // to explicitly set sparam.sched_priority. + + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (*thr_id, + policy, + &sparam), + result), + int, -1); + } + } + +# if defined (ACE_NEEDS_LWP_PRIO_SET) +# if 0 + // It would be useful if we could make this work. But, it requires + // a mechanism for determining the ID of an LWP to which another + // thread is bound. Is there a way to do that? Instead, just rely + // on the code in ACE_Thread_Adapter::invoke () to set the LWP + // priority. + + // If the thread is bound, then set the priority on its LWP. + if (ACE_BIT_ENABLED (flags, THR_BOUND)) + { + ACE_Sched_Params sched_params (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO) || + ACE_BIT_ENABLED (flags, THR_SCHED_RR) ? + ACE_SCHED_FIFO : + ACE_SCHED_OTHER, + priority); + result = ACE_OS::lwp_setparams (sched_params, + /* ? How do we find the ID of the LWP + to which *thr_id is bound? */); + } +# endif /* 0 */ +# endif /* ACE_NEEDS_LWP_PRIO_SET */ + +# endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */ + return result; +# elif defined (ACE_HAS_STHREADS) + int result; + int start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED); + + if (priority != ACE_DEFAULT_THREAD_PRIORITY) + // If we need to set the priority, then we need to start the + // thread in a suspended mode. + ACE_SET_BITS (flags, THR_SUSPENDED); + + ACE_OSCALL (ACE_ADAPT_RETVAL (::thr_create (stack, stacksize, + thread_args->entry_point (), + thread_args, + flags, thr_id), result), + int, -1, result); + + if (result != -1) + { + // With SunOS threads, ACE_thread_t and ACE_hthread_t are the same. + *thr_handle = *thr_id; + + if (priority != ACE_DEFAULT_THREAD_PRIORITY) + { + // Set the priority of the new thread and then let it + // continue, but only if the user didn't start it suspended + // in the first place! + if ((result = ACE_OS::thr_setprio (*thr_id, priority)) != 0) + { + errno = result; + return -1; + } + + if (start_suspended == 0) + { + if ((result = ACE_OS::thr_continue (*thr_id)) != 0) + { + errno = result; + return -1; + } + } + } + } + return result; +# elif defined (ACE_HAS_WTHREADS) + ACE_UNUSED_ARG (stack); +# if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0) + if (ACE_BIT_ENABLED (flags, THR_USE_AFX)) + { + CWinThread *cwin_thread = + ::AfxBeginThread ((AFX_THREADPROC) thread_args->entry_point (), + thread_args, + priority, + 0, + flags | THR_SUSPENDED); + // Have to duplicate the handle because + // CWinThread::~CWinThread() closes the original handle. +# if !defined (ACE_HAS_WINCE) + (void) ::DuplicateHandle (::GetCurrentProcess (), + cwin_thread->m_hThread, + ::GetCurrentProcess (), + thr_handle, + 0, + TRUE, + DUPLICATE_SAME_ACCESS); +# endif /* ! ACE_HAS_WINCE */ + *thr_id = cwin_thread->m_nThreadID; + + if (ACE_BIT_ENABLED (flags, THR_SUSPENDED) == 0) + cwin_thread->ResumeThread (); + // cwin_thread will be deleted in AfxThreadExit() + // Warning: If AfxThreadExit() is called from within the + // thread, ACE_TSS_Cleanup->exit() never gets called ! + } + else +# endif /* ACE_HAS_MFC */ + { + int start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED); + + if (priority != ACE_DEFAULT_THREAD_PRIORITY) + // If we need to set the priority, then we need to start the + // thread in a suspended mode. + ACE_SET_BITS (flags, THR_SUSPENDED); + + *thr_handle = (void *) ACE_BEGINTHREADEX (0, + stacksize, + thread_args->entry_point (), + thread_args, + flags, + thr_id); + + if (priority != ACE_DEFAULT_THREAD_PRIORITY && *thr_handle != 0) + { + // Set the priority of the new thread and then let it + // continue, but only if the user didn't start it suspended + // in the first place! + ACE_OS::thr_setprio (*thr_handle, priority); + + if (start_suspended == 0) + ACE_OS::thr_continue (*thr_handle); + } + } +# if 0 + *thr_handle = ::CreateThread + (0, + stacksize, + LPTHREAD_START_ROUTINE (thread_args->entry_point ()), + thread_args, + flags, + thr_id); +# endif /* 0 */ + + // Close down the handle if no one wants to use it. + if (thr_handle == &tmp_handle) + ::CloseHandle (tmp_handle); + + if (*thr_handle != 0) + return 0; + else + ACE_FAIL_RETURN (-1); + /* NOTREACHED */ + +# elif defined (ACE_PSOS) + + // stack is created in the task's memory region 0 + ACE_UNUSED_ARG (stack); + + // task creation and start flags are fixed + ACE_UNUSED_ARG (flags); + + // lowest priority is reserved for the IDLE pSOS+ system daemon, + // highest are reserved for high priority pSOS+ system daemons + if (priority < PSOS_TASK_MIN_PRIORITY) + { + priority = PSOS_TASK_MIN_PRIORITY; + } + else if (priority > PSOS_TASK_MAX_PRIORITY) + { + priority = PSOS_TASK_MAX_PRIORITY; + } + + // set the stacksize to a default value if no size is specified + if (stacksize == 0) + stacksize = ACE_PSOS_DEFAULT_STACK_SIZE; + + ACE_hthread_t tid; + *thr_handle = 0; + + // create the thread + if (t_create ((char *) thr_id, // task name + priority, // (possibly adjusted) task priority + stacksize, // passed stack size is used for supervisor stack + 0, // no user stack: tasks run strictly in supervisor mode + T_LOCAL, // local to the pSOS+ node (does not support pSOS+m) + &tid) // receives task id + != 0) + { + return -1; + } + + // pSOS tasks are passed an array of 4 u_longs + u_long targs[4]; + targs[0] = (u_long) ACE_THREAD_ARGUMENT; + targs[1] = 0; + targs[2] = 0; + targs[3] = 0; + + // start the thread + if (t_start (tid, + T_PREEMPT | // Task can be preempted + // T_NOTSLICE | // Task is not timesliced with other tasks at same priority + T_TSLICE | // Task is timesliced with other tasks at same priority + T_NOASR | // Task level signals disabled + T_SUPV | // Task runs strictly in supervisor mode + T_ISR, // Hardware interrupts are enabled + ACE_THREAD_FUNCTION, // Task entry point + targs) // Task argument(s) + != 0) + { + return -1; + } + + // store the task id in the handle and return success + *thr_handle = tid; + return 0; + +# elif defined (VXWORKS) + // The hard-coded values below are what ::sp () would use. (::sp () + // hardcodes priority to 100, flags to VX_FP_TASK, and stacksize to + // 20,000.) stacksize should be an even integer. If a stack is not + // specified, ::taskSpawn () is used so that we can set the + // priority, flags, and stacksize. If a stack is specified, + // ::taskInit ()/::taskActivate() are used. + + // If called with thr_create() defaults, use same default values as ::sp (): + if (priority == ACE_DEFAULT_THREAD_PRIORITY) priority = 100; + // Assumes that there is a floating point coprocessor. As noted + // above, ::sp () hardcodes this, so we should be safe with it. + if (flags == 0) flags = VX_FP_TASK; + if (stacksize == 0) stacksize = 20000; + + const u_int thr_id_provided = + thr_id && *thr_id && (*thr_id)[0] != ACE_THR_ID_ALLOCATED; + + ACE_hthread_t tid; +# if 0 /* Don't support setting of stack, because it doesn't seem to work. */ + if (stack == 0) + { +# else + ACE_UNUSED_ARG (stack); +# endif /* 0 */ + // The call below to ::taskSpawn () causes VxWorks to assign a + // unique task name of the form: "t" + an integer, because the + // first argument is 0. + tid = ::taskSpawn (thr_id_provided ? *thr_id : 0, + priority, + (int) flags, + (int) stacksize, + thread_args->entry_point (), + (int) thread_args, + 0, 0, 0, 0, 0, 0, 0, 0, 0); +# if 0 /* Don't support setting of stack, because it doesn't seem to work. */ + } + else + { + // If a task name (thr_id) was not supplied, then the task will + // not have a unique name. That's VxWorks' behavior. + + // Carve out a TCB at the beginning of the stack space. The TCB + // occupies 400 bytes with VxWorks 5.3.1/I386. + WIND_TCB *tcb = (WIND_TCB *) stack; + + // The TID is defined to be the address of the TCB. + int status = ::taskInit (tcb, + thr_id_provided ? *thr_id : 0, + priority, + (int) flags, + (char *) stack + sizeof (WIND_TCB), + (int) (stacksize - sizeof (WIND_TCB)), + thread_args->entry_point (), + (int) thread_args, + 0, 0, 0, 0, 0, 0, 0, 0, 0); + + if (status == OK) + { + // The task was successfully initialized, now activate it. + status = ::taskActivate ((ACE_hthread_t) tcb); + } + + tid = status == OK ? (ACE_hthread_t) tcb : ERROR; + } +# endif /* 0 */ + + if (tid == ERROR) + return -1; + else + { + if (! thr_id_provided && thr_id) + { + if (*thr_id && (*thr_id)[0] == ACE_THR_ID_ALLOCATED) + // *thr_id was allocated by the Thread_Manager. ::taskTcb + // (int tid) returns the address of the WIND_TCB (task + // control block). According to the ::taskSpawn() + // documentation, the name of the new task is stored at + // pStackBase, but is that of the current task? If so, it + // might be a bit quicker than this extraction of the tcb + // . . . + ACE_OS::strsncpy (*thr_id + 1, ::taskTcb (tid)->name, 10); + else + // *thr_id was not allocated by the Thread_Manager. + // Pass back the task name in the location pointed to + // by thr_id. + *thr_id = ::taskTcb (tid)->name; + } + // else if the thr_id was provided, there's no need to overwrite + // it with the same value (string). If thr_id is 0, then we can't + // pass the task name back. + + if (thr_handle) + *thr_handle = tid; + + return 0; + } + +# endif /* ACE_HAS_STHREADS */ +# else + ACE_UNUSED_ARG (func); + ACE_UNUSED_ARG (args); + ACE_UNUSED_ARG (flags); + ACE_UNUSED_ARG (thr_id); + ACE_UNUSED_ARG (thr_handle); + ACE_UNUSED_ARG (priority); + ACE_UNUSED_ARG (stack); + ACE_UNUSED_ARG (stacksize); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_THREADS */ +#endif /* ACE_HAS_PACE && !ACE_WIN32 */ +} + +void +ACE_OS::thr_exit (void *status) +{ + ACE_OS_TRACE ("ACE_OS::thr_exit"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ::pace_pthread_exit (status); +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) + ::pthread_exit (status); +# elif defined (ACE_HAS_STHREADS) + ::thr_exit (status); +# elif defined (ACE_HAS_WTHREADS) + // Can't call it here because on NT, the thread is exited + // directly by ACE_Thread_Adapter::invoke (). + // ACE_TSS_Cleanup::instance ()->exit (status); + +# if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0) + int using_afx = -1; + // An ACE_Thread_Descriptor really is an ACE_OS_Thread_Descriptor. + // But without #including ace/Thread_Manager.h, we don't know that. + ACE_OS_Thread_Descriptor *td = + ACE_Base_Thread_Adapter::thr_desc_log_msg (); + if (td) + using_afx = ACE_BIT_ENABLED (td->flags (), THR_USE_AFX); +# endif /* ACE_HAS_MFC && (ACE_HAS_MFC != 0) */ + + // Call TSS destructors. + ACE_OS::cleanup_tss (0 /* not main thread */); + + // Exit the thread. + // Allow CWinThread-destructor to be invoked from AfxEndThread. + // _endthreadex will be called from AfxEndThread so don't exit the + // thread now if we are running an MFC thread. +# if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0) + if (using_afx != -1) + { + if (using_afx) + ::AfxEndThread ((DWORD)status); + else + ACE_ENDTHREADEX (status); + } + else + { + // Not spawned by ACE_Thread_Manager, use the old buggy + // version. You should seriously consider using + // ACE_Thread_Manager to spawn threads. The following code is + // know to cause some problem. + CWinThread *pThread = ::AfxGetThread (); + if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ()) + ACE_ENDTHREADEX (status); + else + ::AfxEndThread ((DWORD)status); + } +# else + ACE_ENDTHREADEX (status); +# endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/ + +# elif defined (VXWORKS) + ACE_hthread_t tid; + ACE_OS::thr_self (tid); + *((int *) status) = ::taskDelete (tid); +# elif defined (ACE_PSOS) + ACE_hthread_t tid; + ACE_OS::thr_self (tid); + +# if defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS) + // Call TSS destructors. + ACE_OS::cleanup_tss (0 /* not main thread */); +# endif /* ACE_PSOS && ACE_PSOS_HAS_TSS */ + + *((u_long *) status) = ::t_delete (tid); +# endif /* ACE_HAS_PTHREADS */ +# else + ACE_UNUSED_ARG (status); +# endif /* ACE_HAS_PACE && !ACE_WIN32 */ +} + +int +ACE_OS::lwp_getparams (ACE_Sched_Params &sched_params) +{ +# if defined (ACE_HAS_STHREADS) || defined (sun) + // Get the class TS and RT class IDs. + ACE_id_t rt_id; + ACE_id_t ts_id; + if (ACE_OS::scheduling_class ("RT", rt_id) == -1 + || ACE_OS::scheduling_class ("TS", ts_id) == -1) + return -1; + + // Get this LWP's scheduling parameters. + pcparms_t pcparms; + // The following is just to avoid Purify warnings about unitialized + // memory reads. + ACE_OS::memset (&pcparms, 0, sizeof pcparms); + pcparms.pc_cid = PC_CLNULL; + + if (ACE_OS::priority_control (P_LWPID, + P_MYID, + PC_GETPARMS, + (char *) &pcparms) == -1) + return -1; + else if (pcparms.pc_cid == rt_id) + { + // RT class. + rtparms_t rtparms; + ACE_OS::memcpy (&rtparms, pcparms.pc_clparms, sizeof rtparms); + + sched_params.policy (ACE_SCHED_FIFO); + sched_params.priority (rtparms.rt_pri); + sched_params.scope (ACE_SCOPE_THREAD); + ACE_Time_Value quantum (rtparms.rt_tqsecs, + rtparms.rt_tqnsecs == RT_TQINF + ? 0 : rtparms.rt_tqnsecs * 1000); + sched_params.quantum (quantum); + return 0; + } + else if (pcparms.pc_cid == ts_id) + { + /* TS class */ + tsparms_t tsparms; + ACE_OS::memcpy (&tsparms, pcparms.pc_clparms, sizeof tsparms); + + sched_params.policy (ACE_SCHED_OTHER); + sched_params.priority (tsparms.ts_upri); + sched_params.scope (ACE_SCOPE_THREAD); + return 0; + } + else + return -1; + +# else /* ! ACE_HAS_STHREADS && ! sun */ + ACE_UNUSED_ARG (sched_params); + ACE_NOTSUP_RETURN (-1); +# endif /* ! ACE_HAS_STHREADS && ! sun */ +} + +int +ACE_OS::lwp_setparams (const ACE_Sched_Params &sched_params) +{ +# if defined (ACE_HAS_STHREADS) || defined (sun) + ACE_Sched_Params lwp_params (sched_params); + lwp_params.scope (ACE_SCOPE_LWP); + return ACE_OS::sched_params (lwp_params); +# else /* ! ACE_HAS_STHREADS && ! sun */ + ACE_UNUSED_ARG (sched_params); + ACE_NOTSUP_RETURN (-1); +# endif /* ! ACE_HAS_STHREADS && ! sun */ +} + +# if defined (ACE_HAS_TSS_EMULATION) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) +int +ACE_OS::thr_setspecific (ACE_OS_thread_key_t key, void *data) +{ + // ACE_OS_TRACE ("ACE_OS::thr_setspecific"); +# if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) +# if defined (ACE_HAS_FSU_PTHREADS) + // Call pthread_init() here to initialize threads package. FSU + // threads need an initialization before the first thread constructor. + // This seems to be the one; however, a segmentation fault may + // indicate that another pthread_init() is necessary, perhaps in + // Synch.cpp or Synch_T.cpp. FSU threads will not reinit if called + // more than once, so another call to pthread_init will not adversely + // affect existing threads. + pthread_init (); +# endif /* ACE_HAS_FSU_PTHREADS */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setspecific (key, data), ace_result_), int, -1); +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setspecific (key, data), ace_result_), int, -1); +# elif defined (ACE_HAS_WTHREADS) + ::TlsSetValue (key, data); + return 0; +# endif /* ACE_HAS_STHREADS */ +# else + ACE_UNUSED_ARG (key); + ACE_UNUSED_ARG (data); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_THREADS */ +} +# endif /* ACE_HAS_TSS_EMULATION && ACE_HAS_THREAD_SPECIFIC_STORAGE */ + +int +ACE_OS::thr_setspecific (ACE_thread_key_t key, void *data) +{ + // ACE_OS_TRACE ("ACE_OS::thr_setspecific"); + // If we are using TSS emulation then we shuld use ACE's implementation + // of it and not make any PACE calls. +#if defined (ACE_HAS_PACE) && !defined (ACE_HAS_TSS_EMULATION) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_setspecific (key, data), + ace_result_), + int, -1); +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_TSS_EMULATION) + ACE_KEY_INDEX (key_index, key); + + if (key_index >= ACE_TSS_Emulation::total_keys ()) + { + errno = EINVAL; + data = 0; + return -1; + } + else + { + ACE_TSS_Emulation::ts_object (key) = data; + ACE_TSS_Cleanup::instance ()->key_used (key); + + return 0; + } +# elif defined (ACE_HAS_PTHREADS) +# if defined (ACE_HAS_FSU_PTHREADS) + // Call pthread_init() here to initialize threads package. FSU + // threads need an initialization before the first thread constructor. + // This seems to be the one; however, a segmentation fault may + // indicate that another pthread_init() is necessary, perhaps in + // Synch.cpp or Synch_T.cpp. FSU threads will not reinit if called + // more than once, so another call to pthread_init will not adversely + // affect existing threads. + pthread_init (); +# endif /* ACE_HAS_FSU_PTHREADS */ + +# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) + ACE_OSCALL_RETURN (::pthread_setspecific (key, data), int, -1); +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setspecific (key, data), + ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */ + +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setspecific (key, data), ace_result_), int, -1); +# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS) + ACE_hthread_t tid; + ACE_OS::thr_self (tid); + if (::tsd_setval (key, tid, data) != 0) + return -1; + ACE_TSS_Cleanup::instance ()->key_used (key); + return 0; +# elif defined (ACE_HAS_WTHREADS) + ::TlsSetValue (key, data); + ACE_TSS_Cleanup::instance ()->key_used (key); + return 0; +# else + ACE_UNUSED_ARG (key); + ACE_UNUSED_ARG (data); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_STHREADS */ +# else + ACE_UNUSED_ARG (key); + ACE_UNUSED_ARG (data); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE && !ACE_HAS_TSS_EMULATION && !ACE_WIN32 */ +} + +int +ACE_OS::thr_keyfree (ACE_thread_key_t key) +{ + ACE_OS_TRACE ("ACE_OS::thr_keyfree"); + // If we are using TSS emulation then we should use ACE's implementation + // of it and not make any PACE calls. +# if defined (ACE_HAS_PACE) && !defined (ACE_HAS_TSS_EMULATION) && !defined (ACE_WIN32) + return ::pace_pthread_key_delete (key); +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_TSS_EMULATION) + // Release the key in the TSS_Emulation administration + ACE_TSS_Emulation::release_key (key); + return ACE_TSS_Cleanup::instance ()->remove (key); +# elif defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) + ACE_UNUSED_ARG (key); + ACE_NOTSUP_RETURN (-1); +# elif defined (ACE_HAS_PTHREADS) + return ::pthread_key_delete (key); +# elif defined (ACE_HAS_THR_KEYDELETE) + return ::thr_keydelete (key); +# elif defined (ACE_HAS_STHREADS) + ACE_UNUSED_ARG (key); + ACE_NOTSUP_RETURN (-1); +# elif defined (ACE_HAS_WTHREADS) + // Extract out the thread-specific table instance and free up + // the key and destructor. + ACE_TSS_Cleanup::instance ()->remove (key); + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::TlsFree (key), ace_result_), int, -1); +# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS) + // Extract out the thread-specific table instance and free up + // the key and destructor. + ACE_TSS_Cleanup::instance ()->remove (key); + return (::tsd_delete (key) == 0) ? 0 : -1; +# else + ACE_UNUSED_ARG (key); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_TSS_EMULATION */ +# else + ACE_UNUSED_ARG (key); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE && !ACE_HAS_TSS_EMULATION && !ACE_WIN32 */ +} + +# if defined (ACE_HAS_TSS_EMULATION) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) +int +ACE_OS::thr_keycreate (ACE_OS_thread_key_t *key, +# if defined (ACE_HAS_THR_C_DEST) + ACE_THR_C_DEST dest, +# else + ACE_THR_DEST dest, +# endif /* ACE_HAS_THR_C_DEST */ + void *inst) +{ + // ACE_OS_TRACE ("ACE_OS::thr_keycreate"); +# if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_key_create (key, dest), + ace_result_), + int, -1); + +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) + ACE_UNUSED_ARG (inst); + + +# if defined (ACE_HAS_PTHREADS_DRAFT4) +# if defined (ACE_HAS_STDARG_THR_DEST) + ACE_OSCALL_RETURN (::pthread_keycreate (key, (void (*)(...)) dest), int, -1); +# else /* ! ACE_HAS_STDARG_THR_DEST */ + ACE_OSCALL_RETURN (::pthread_keycreate (key, dest), int, -1); +# endif /* ! ACE_HAS_STDARG_THR_DEST */ +# elif defined (ACE_HAS_PTHREADS_DRAFT6) + ACE_OSCALL_RETURN (::pthread_key_create (key, dest), int, -1); +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key, dest), + ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ +# elif defined (ACE_HAS_STHREADS) + ACE_UNUSED_ARG (inst); + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_keycreate (key, dest), + ace_result_), + int, -1); +# elif defined (ACE_HAS_WTHREADS) + *key = ::TlsAlloc (); + + if (*key != ACE_SYSCALL_FAILED) + { + // Extract out the thread-specific table instance and stash away + // the key and destructor so that we can free it up later on... + return ACE_TSS_Cleanup::instance ()->insert (*key, dest, inst); + } + else + ACE_FAIL_RETURN (-1); + /* NOTREACHED */ +# endif /* ACE_HAS_STHREADS */ +# else + ACE_UNUSED_ARG (key); + ACE_UNUSED_ARG (dest); + ACE_UNUSED_ARG (inst); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE && !ACE_WIN32 */ +} +# endif /* ACE_HAS_TSS_EMULATION && ACE_HAS_THREAD_SPECIFIC_STORAGE */ + +int +ACE_OS::thr_keycreate (ACE_thread_key_t *key, +# if defined (ACE_HAS_THR_C_DEST) + ACE_THR_C_DEST dest, +# else + ACE_THR_DEST dest, +# endif /* ACE_HAS_THR_C_DEST */ + void *inst) +{ + // ACE_OS_TRACE ("ACE_OS::thr_keycreate"); + // If we are using TSS emulation then we shuld use ACE's implementation + // of it and not make any PACE calls. +#if defined (ACE_HAS_PACE) && !defined (ACE_HAS_TSS_EMULATION) && !defined (ACE_WIN32) + ACE_UNUSED_ARG (inst); +# if defined (ACE_WIN32) + int ace_result_ = 0; +# endif /* ACE_WIN32 */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_key_create (key, dest), + ace_result_), + int, -1); +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_TSS_EMULATION) + if (ACE_TSS_Emulation::next_key (*key) == 0) + { + ACE_TSS_Emulation::tss_destructor (*key, dest); + + // Extract out the thread-specific table instance and stash away + // the key and destructor so that we can free it up later on... + return ACE_TSS_Cleanup::instance ()->insert (*key, dest, inst); + } + else + { + errno = EAGAIN; + return -1; + } +# elif defined (ACE_HAS_PTHREADS) + ACE_UNUSED_ARG (inst); + +# if defined (ACE_HAS_PTHREADS_DRAFT4) +# if defined (ACE_HAS_STDARG_THR_DEST) + ACE_OSCALL_RETURN (::pthread_keycreate (key, (void (*)(...)) dest), int, -1); +# else /* ! ACE_HAS_STDARG_THR_DEST */ + ACE_OSCALL_RETURN (::pthread_keycreate (key, dest), int, -1); +# endif /* ! ACE_HAS_STDARG_THR_DEST */ +# elif defined (ACE_HAS_PTHREADS_DRAFT6) + ACE_OSCALL_RETURN (::pthread_key_create (key, dest), int, -1); +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key, dest), + ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + +# elif defined (ACE_HAS_STHREADS) + ACE_UNUSED_ARG (inst); + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_keycreate (key, dest), + ace_result_), + int, -1); +# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS) + + static u_long unique_name = 0; + void *tsdanchor; + + ++unique_name; + if (::tsd_create (ACE_reinterpret_cast (char *, unique_name), + 0, + TSD_NOALLOC, + (void ****) &tsdanchor, + key) != 0) + { + return -1; + } + + return ACE_TSS_Cleanup::instance ()->insert (*key, dest, inst); +# elif defined (ACE_HAS_WTHREADS) + *key = ::TlsAlloc (); + + if (*key != ACE_SYSCALL_FAILED) + { + // Extract out the thread-specific table instance and stash away + // the key and destructor so that we can free it up later on... + return ACE_TSS_Cleanup::instance ()->insert (*key, dest, inst); + } + else + ACE_FAIL_RETURN (-1); + /* NOTREACHED */ +# else + ACE_UNUSED_ARG (key); + ACE_UNUSED_ARG (dest); + ACE_UNUSED_ARG (inst); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_TSS_EMULATION */ +# else + ACE_UNUSED_ARG (key); + ACE_UNUSED_ARG (dest); + ACE_UNUSED_ARG (inst); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE && !ACE_HAS_TSS_EMULATION && !ACE_WIN32 */ +} + +int +ACE_OS::thr_key_used (ACE_thread_key_t key) +{ +# if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) + ACE_TSS_Cleanup::instance ()->key_used (key); + return 0; +# else + ACE_UNUSED_ARG (key); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION || ACE_PSOS_HAS_TSS */ +} + +int +ACE_OS::thr_key_detach (void *inst) +{ +# if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) + if (ACE_TSS_Cleanup::lockable ()) + return ACE_TSS_Cleanup::instance()->detach (inst); + else + // We're in static constructor/destructor phase. Don't + // try to use the ACE_TSS_Cleanup instance because its lock + // might not have been constructed yet, or might have been + // destroyed already. Just leak the key . . . + return -1; +# else + ACE_UNUSED_ARG (inst); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */ +} + +void +ACE_OS::unique_name (const void *object, + ACE_TCHAR *name, + size_t length) +{ + // The process ID will provide uniqueness between processes on the + // same machine. The "this" pointer of the will provide + // uniqueness between other "live" objects in the same process. The + // uniqueness of this name is therefore only valid for the life of + // . + ACE_TCHAR temp_name[ACE_UNIQUE_NAME_LEN]; + ACE_OS::sprintf (temp_name, + ACE_LIB_TEXT ("%lx%d"), + ACE_reinterpret_cast (long, object), + ACE_static_cast (int, ACE_OS::getpid ())); + ACE_OS::strsncpy (name, + temp_name, + length); +} + +int +ACE_OS::argv_to_string (ACE_TCHAR **argv, + ACE_TCHAR *&buf, + int substitute_env_args) +{ + if (argv == 0 || argv[0] == 0) + return 0; + + int buf_len = 0; + + // Determine the length of the buffer. + + for (int i = 0; argv[i] != 0; i++) + { + ACE_TCHAR *temp = 0; + +#if !defined (ACE_LACKS_ENV) + // Account for environment variables. + if (substitute_env_args + && (argv[i][0] == '$' + && (temp = ACE_OS::getenv (&argv[i][1])) != 0)) + buf_len += ACE_OS::strlen (temp); + else +#endif /* ACE_LACKS_ENV */ + buf_len += ACE_OS::strlen (argv[i]); + + // Add one for the extra space between each string. + buf_len++; + } + + // Step through all argv params and copy each one into buf; separate + // each param with white space. + + ACE_NEW_RETURN (buf, + ACE_TCHAR[buf_len + 1], + 0); + + // Initial null charater to make it a null string. + buf[0] = '\0'; + ACE_TCHAR *end = buf; + int j; + + for (j = 0; argv[j] != 0; j++) + { + ACE_TCHAR *temp = 0; + +# if !defined (ACE_LACKS_ENV) + // Account for environment variables. + if (substitute_env_args + && (argv[j][0] == '$' + && (temp = ACE_OS::getenv (&argv[j][1])) != 0)) + end = ACE_OS::strecpy (end, temp); + else +#endif /* ACE_LACKS_ENV */ + end = ACE_OS::strecpy (end, argv[j]); + + // Replace the null char that strecpy put there with white + // space. + end[-1] = ' '; + } + + // Null terminate the string. + *end = '\0'; + // The number of arguments. + return j; +} + +int +ACE_OS::string_to_argv (ACE_TCHAR *buf, + size_t &argc, + ACE_TCHAR **&argv, + int substitute_env_args) +{ + // Reset the number of arguments + argc = 0; + + if (buf == 0) + return -1; + + ACE_TCHAR *cp = buf; + + // First pass: count arguments. + + // '#' is the start-comment token.. + while (*cp != '\0' && *cp != '#') + { + // Skip whitespace.. + while (ACE_OS::ace_isspace (*cp)) + cp++; + + // Increment count and move to next whitespace.. + if (*cp != '\0') + argc++; + + while (*cp != '\0' && !ACE_OS::ace_isspace (*cp)) + { + // Grok quotes.... + if (*cp == '\'' || *cp == '"') + { + ACE_TCHAR quote = *cp; + + // Scan past the string.. + for (cp++; *cp != '\0' && *cp != quote; cp++) + continue; + + // '\0' implies unmatched quote.. + if (*cp == '\0') + { + argc--; + break; + } + else + cp++; + } + else + cp++; + } + } + + // Second pass: copy arguments. + ACE_TCHAR arg[ACE_DEFAULT_ARGV_BUFSIZ]; + ACE_TCHAR *argp = arg; + + // Make sure that the buffer we're copying into is always large + // enough. + if (cp - buf >= ACE_DEFAULT_ARGV_BUFSIZ) + ACE_NEW_RETURN (argp, + ACE_TCHAR[cp - buf + 1], + -1); + + // Make a new argv vector of argc + 1 elements. + ACE_NEW_RETURN (argv, + ACE_TCHAR *[argc + 1], + -1); + + ACE_TCHAR *ptr = buf; + + for (size_t i = 0; i < argc; i++) + { + // Skip whitespace.. + while (ACE_OS::ace_isspace (*ptr)) + ptr++; + + // Copy next argument and move to next whitespace.. + cp = argp; + while (*ptr != '\0' && !ACE_OS::ace_isspace (*ptr)) + if (*ptr == '\'' || *ptr == '"') + { + ACE_TCHAR quote = *ptr++; + + while (*ptr != '\0' && *ptr != quote) + *cp++ = *ptr++; + + if (*ptr == quote) + ptr++; + } + else + *cp++ = *ptr++; + + *cp = '\0'; + +#if !defined (ACE_LACKS_ENV) + // Check for environment variable substitution here. + if (substitute_env_args) { + argv[i] = ACE_OS::strenvdup(argp); + + if (argv[i] == 0) + { + if (argp != arg) + delete [] argp; + errno = ENOMEM; + return -1; + } + } + else +#endif /* ACE_LACKS_ENV */ + { + argv[i] = ACE_OS::strdup(argp); + + if (argv[i] == 0) + { + if (argp != arg) + delete [] argp; + errno = ENOMEM; + return -1; + } + } + } + + if (argp != arg) + delete [] argp; + + argv[argc] = 0; + return 0; +} + +// Create a contiguous command-line argument buffer with each arg +// separated by spaces. + +pid_t +ACE_OS::fork_exec (ACE_TCHAR *argv[]) +{ +# if defined (ACE_WIN32) + ACE_TCHAR *buf; + + if (ACE_OS::argv_to_string (argv, buf) != -1) + { + PROCESS_INFORMATION process_info; +# if !defined (ACE_HAS_WINCE) + ACE_TEXT_STARTUPINFO startup_info; + ACE_OS::memset ((void *) &startup_info, + 0, + sizeof startup_info); + startup_info.cb = sizeof startup_info; + + if (ACE_TEXT_CreateProcess (0, + buf, + 0, // No process attributes. + 0, // No thread attributes. + TRUE, // Allow handle inheritance. + 0, // Don't create a new console window. + 0, // No environment. + 0, // No current directory. + &startup_info, + &process_info)) +# else + if (ACE_TEXT_CreateProcess (0, + buf, + 0, // No process attributes. + 0, // No thread attributes. + FALSE, // Can's inherit handles on CE + 0, // Don't create a new console window. + 0, // No environment. + 0, // No current directory. + 0, // Can't use startup info on CE + &process_info)) +# endif /* ! ACE_HAS_WINCE */ + { + // Free resources allocated in kernel. + ACE_OS::close (process_info.hThread); + ACE_OS::close (process_info.hProcess); + // Return new process id. + delete [] buf; + return process_info.dwProcessId; + } + } + + // CreateProcess failed. + return -1; +# elif defined (CHORUS) + return ACE_OS::execv (argv[0], argv); +# else + pid_t result = ACE_OS::fork (); + + switch (result) + { + case -1: + // Error. + return -1; + case 0: + // Child process. + if (ACE_OS::execv (argv[0], argv) == -1) + { + // The OS layer should not print stuff out + // ACE_ERROR ((LM_ERROR, + // "%p Exec failed\n")); + + // If the execv fails, this child needs to exit. + ACE_OS::exit (errno); + } + default: + // Server process. The fork succeeded. + return result; + } +# endif /* ACE_WIN32 */ +} + +ssize_t +ACE_OS::read_n (ACE_HANDLE handle, + void *buf, + size_t len, + size_t *bt) +{ + size_t temp; + size_t &bytes_transferred = bt == 0 ? temp : *bt; + ssize_t n; + + for (bytes_transferred = 0; + bytes_transferred < len; + bytes_transferred += n) + { + n = ACE_OS::read (handle, + (char *) buf + bytes_transferred, + len - bytes_transferred); + + if (n == -1 || n == 0) + return n; + } + + return bytes_transferred; +} + +// Write bytes from to (uses the +// system call on UNIX and the call on Win32). + +ssize_t +ACE_OS::write_n (ACE_HANDLE handle, + const void *buf, + size_t len, + size_t *bt) +{ + size_t temp; + size_t &bytes_transferred = bt == 0 ? temp : *bt; + ssize_t n; + + for (bytes_transferred = 0; + bytes_transferred < len; + bytes_transferred += n) + { + n = ACE_OS::write (handle, + (char *) buf + bytes_transferred, + len - bytes_transferred); + + if (n == -1 || n == 0) + return n; + } + + return bytes_transferred; +} + +# if defined (ACE_LACKS_WRITEV) + +// "Fake" writev for operating systems without it. Note that this is +// thread-safe. + +int +ACE_OS::writev_emulation (ACE_HANDLE handle, ACE_WRITEV_TYPE iov[], int n) +{ + ACE_OS_TRACE ("ACE_OS::writev_emulation"); + + size_t length = 0; + int i; + + // Determine the total length of all the buffers in . + for (i = 0; i < n; i++) + if (ACE_static_cast (int, iov[i].iov_len) < 0) + return -1; + else + length += iov[i].iov_len; + + char *buf; + +# if defined (ACE_HAS_ALLOCA) + buf = (char *) alloca (length); +# else + ACE_NEW_RETURN (buf, + char[length], + -1); +# endif /* !defined (ACE_HAS_ALLOCA) */ + + char *ptr = buf; + + for (i = 0; i < n; i++) + { + ACE_OS::memcpy (ptr, iov[i].iov_base, iov[i].iov_len); + ptr += iov[i].iov_len; + } + + ssize_t result = ACE_OS::write (handle, buf, length); +# if !defined (ACE_HAS_ALLOCA) + delete [] buf; +# endif /* !defined (ACE_HAS_ALLOCA) */ + return result; +} +# endif /* ACE_LACKS_WRITEV */ + +# if defined (ACE_LACKS_READV) + +// "Fake" readv for operating systems without it. Note that this is +// thread-safe. + +ssize_t +ACE_OS::readv_emulation (ACE_HANDLE handle, + ACE_READV_TYPE *iov, + int n) +{ + ACE_OS_TRACE ("ACE_OS::readv_emulation"); + + ssize_t length = 0; + int i; + + for (i = 0; i < n; i++) + if (ACE_static_cast (int, iov[i].iov_len) < 0) + return -1; + else + length += iov[i].iov_len; + + char *buf; +# if defined (ACE_HAS_ALLOCA) + buf = (char *) alloca (length); +# else + ACE_NEW_RETURN (buf, + char[length], + -1); +# endif /* !defined (ACE_HAS_ALLOCA) */ + + length = ACE_OS::read (handle, buf, length); + + if (length != -1) + { + char *ptr = buf; + int copyn = length; + + for (i = 0; + i < n && copyn > 0; + i++) + { + ACE_OS::memcpy (iov[i].iov_base, ptr, + // iov_len is int on some platforms, size_t on others + copyn > (int) iov[i].iov_len + ? (size_t) iov[i].iov_len + : (size_t) copyn); + ptr += iov[i].iov_len; + copyn -= iov[i].iov_len; + } + } + +# if !defined (ACE_HAS_ALLOCA) + delete [] buf; +# endif /* !defined (ACE_HAS_ALLOCA) */ + return length; +} +# endif /* ACE_LACKS_READV */ + +# if defined (ACE_NEEDS_FTRUNCATE) +extern "C" int +ftruncate (ACE_HANDLE handle, long len) +{ + struct flock fl; + fl.l_whence = 0; + fl.l_len = 0; + fl.l_start = len; + fl.l_type = F_WRLCK; + + return ACE_OS::fcntl (handle, F_FREESP, ACE_reinterpret_cast (long, &fl)); +} +# endif /* ACE_NEEDS_FTRUNCATE */ + +# if defined (ACE_LACKS_MKTEMP) +ACE_TCHAR * +ACE_OS::mktemp (ACE_TCHAR *s) +{ + ACE_OS_TRACE ("ACE_OS::mktemp"); + if (s == 0) + // check for null template string failed! + return 0; + else + { + ACE_TCHAR *xxxxxx = ACE_OS::strstr (s, ACE_LIB_TEXT ("XXXXXX")); + + if (xxxxxx == 0) + // the template string doesn't contain "XXXXXX"! + return s; + else + { + ACE_TCHAR unique_letter = ACE_LIB_TEXT ('a'); + ACE_stat sb; + + // Find an unused filename for this process. It is assumed + // that the user will open the file immediately after + // getting this filename back (so, yes, there is a race + // condition if multiple threads in a process use the same + // template). This appears to match the behavior of the + // SunOS 5.5 mktemp(). + ACE_OS::sprintf (xxxxxx, + ACE_LIB_TEXT ("%05d%c"), + ACE_OS::getpid (), + unique_letter); + while (ACE_OS::stat (s, &sb) >= 0) + { + if (++unique_letter <= ACE_LIB_TEXT ('z')) + ACE_OS::sprintf (xxxxxx, + ACE_LIB_TEXT ("%05d%c"), + ACE_OS::getpid (), + unique_letter); + else + { + // maximum of 26 unique files per template, per process + ACE_OS::sprintf (xxxxxx, ACE_LIB_TEXT ("%s"), ACE_LIB_TEXT ("")); + return s; + } + } + } + return s; + } +} +# endif /* ACE_LACKS_MKTEMP */ + +int +ACE_OS::socket_init (int version_high, int version_low) +{ +# if defined (ACE_WIN32) + if (ACE_OS::socket_initialized_ == 0) + { + WORD version_requested = MAKEWORD (version_high, version_low); + WSADATA wsa_data; + int error = WSAStartup (version_requested, &wsa_data); + + if (error != 0) +# if defined (ACE_HAS_WINCE) + { + wchar_t fmt[] = ACE_LIB_TEXT ("%s failed, WSAGetLastError returned %d"); + wchar_t buf[80]; // @@ Eliminate magic number. + ACE_OS::sprintf (buf, fmt, ACE_LIB_TEXT ("WSAStartup"), error); + ::MessageBox (NULL, buf, ACE_LIB_TEXT ("WSAStartup failed!"), MB_OK); + } +# else + ACE_OS::fprintf (stderr, + "ACE_OS::socket_init; WSAStartup failed, " + "WSAGetLastError returned %d\n", + error); +# endif /* ACE_HAS_WINCE */ + + ACE_OS::socket_initialized_ = 1; + } +# else + ACE_UNUSED_ARG (version_high); + ACE_UNUSED_ARG (version_low); +# endif /* ACE_WIN32 */ + return 0; +} + +int +ACE_OS::socket_fini (void) +{ +# if defined (ACE_WIN32) + if (ACE_OS::socket_initialized_ != 0) + { + if (WSACleanup () != 0) + { + int error = ::WSAGetLastError (); +# if defined (ACE_HAS_WINCE) + wchar_t fmt[] = ACE_LIB_TEXT ("%s failed, WSAGetLastError returned %d"); + wchar_t buf[80]; // @@ Eliminate magic number. + ACE_OS::sprintf (buf, fmt, ACE_LIB_TEXT ("WSACleanup"), error); + ::MessageBox (NULL, buf , ACE_LIB_TEXT ("WSACleanup failed!"), MB_OK); +# else + ACE_OS::fprintf (stderr, + "ACE_OS::socket_fini; WSACleanup failed, " + "WSAGetLastError returned %d\n", + error); +# endif /* ACE_HAS_WINCE */ + } + ACE_OS::socket_initialized_ = 0; + } +# endif /* ACE_WIN32 */ + return 0; +} + +# if defined (ACE_LACKS_SYS_NERR) +# if defined (__rtems__) +int sys_nerr = EWOULDBLOCK + 1; // definitely a hack. +# else + int sys_nerr = ERRMAX + 1; +# endif /* __rtems__ */ +# endif /* ACE_LACKS_SYS_NERR */ + +# if defined (VXWORKS) +# include /**/ /* for ::sp() */ + +// This global function can be used from the VxWorks shell to pass +// arguments to a C main () function. +// +// usage: -> spa main, "arg1", "arg2" +// +// All arguments must be quoted, even numbers. +int +spa (FUNCPTR entry, ...) +{ + static const unsigned int MAX_ARGS = 10; + static char *argv[MAX_ARGS]; + va_list pvar; + unsigned int argc; + + // Hardcode a program name because the real one isn't available + // through the VxWorks shell. + argv[0] = "ace_main"; + + // Peel off arguments to spa () and put into argv. va_arg () isn't + // necessarily supposed to return 0 when done, though since the + // VxWorks shell uses a fixed number (10) of arguments, it might 0 + // the unused ones. This function could be used to increase that + // limit, but then it couldn't depend on the trailing 0. So, the + // number of arguments would have to be passed. + va_start (pvar, entry); + + for (argc = 1; argc <= MAX_ARGS; ++argc) + { + argv[argc] = va_arg (pvar, char *); + + if (argv[argc] == 0) + break; + } + + if (argc > MAX_ARGS && argv[argc-1] != 0) + { + // try to read another arg, and warn user if the limit was exceeded + if (va_arg (pvar, char *) != 0) + ACE_OS::fprintf (stderr, "spa(): number of arguments limited to %d\n", + MAX_ARGS); + } + else + { + // fill unused argv slots with 0 to get rid of leftovers + // from previous invocations + for (unsigned int i = argc; i <= MAX_ARGS; ++i) + argv[i] = 0; + } + + // The hard-coded options are what ::sp () uses, except for the + // larger stack size (instead of ::sp ()'s 20000). + const int ret = ::taskSpawn (argv[0], // task name + 100, // task priority + VX_FP_TASK, // task options + ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size + entry, // entry point + argc, // first argument to main () + (int) argv, // second argument to main () + 0, 0, 0, 0, 0, 0, 0, 0); + va_end (pvar); + + // ::taskSpawn () returns the taskID on success: return 0 instead if + // successful + return ret > 0 ? 0 : ret; +} + + + +// A helper function for the extended spa functions +static void +add_to_argv (int& argc, char** argv, int max_args, char* string) +{ + char indouble = 0; + size_t previous = 0; + size_t length = ACE_OS_String::strlen (string); + + // We use <= to make sure that we get the last argument + for (size_t i = 0; i <= length; i++) + { + // Is it a double quote that hasn't been escaped? + if (string[i] == '\"' && (i == 0 || string[i - 1] != '\\')) + { + indouble ^= 1; + if (indouble) + { + // We have just entered a double quoted string, so + // save the starting position of the contents. + previous = i + 1; + } + else + { + // We have just left a double quoted string, so + // zero out the ending double quote. + string[i] = '\0'; + } + } + else if (string[i] == '\\') // Escape the next character + { + // The next character is automatically + // skipped because of the strcpy + ACE_OS_String::strcpy (string + i, string + i + 1); + length--; + } + else if (!indouble && + (ACE_OS::ace_isspace (string[i]) || string[i] == '\0')) + { + string[i] = '\0'; + if (argc < max_args) + { + argv[argc] = string + previous; + argc++; + } + else + { + ACE_OS::fprintf (stderr, "spae(): number of arguments " + "limited to %d\n", max_args); + } + + // Skip over whitespace in between arguments + for(++i; i < length && ACE_OS::ace_isspace (string[i]); ++i) + { + } + + // Save the starting point for the next time around + previous = i; + + // Make sure we don't skip over a character due + // to the above loop to skip over whitespace + i--; + } + } +} + +// This global function can be used from the VxWorks shell to pass +// arguments to a C main () function. +// +// usage: -> spae main, "arg1 arg2 \"arg3 with spaces\"" +// +// All arguments must be within double quotes, even numbers. +int +spae (FUNCPTR entry, ...) +{ + static const int WINDSH_ARGS = 10; + static const int MAX_ARGS = 128; + static char* argv[MAX_ARGS] = { "ace_main", 0 }; + va_list pvar; + int argc = 1; + + // Peel off arguments to spa () and put into argv. va_arg () isn't + // necessarily supposed to return 0 when done, though since the + // VxWorks shell uses a fixed number (10) of arguments, it might 0 + // the unused ones. + va_start (pvar, entry); + + int i = 0; + for (char* str = va_arg (pvar, char*); + str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i) + { + add_to_argv(argc, argv, MAX_ARGS, str); + } + + // fill unused argv slots with 0 to get rid of leftovers + // from previous invocations + for (i = argc; i < MAX_ARGS; ++i) + argv[i] = 0; + + // The hard-coded options are what ::sp () uses, except for the + // larger stack size (instead of ::sp ()'s 20000). + const int ret = ::taskSpawn (argv[0], // task name + 100, // task priority + VX_FP_TASK, // task options + ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size + entry, // entry point + argc, // first argument to main () + (int) argv, // second argument to main () + 0, 0, 0, 0, 0, 0, 0, 0); + va_end (pvar); + + // ::taskSpawn () returns the taskID on success: return 0 instead if + // successful + return ret > 0 ? 0 : ret; +} + + +// This global function can be used from the VxWorks shell to pass +// arguments to a C main () function. The function will be run +// within the shells task. +// +// usage: -> spaef main, "arg1 arg2 \"arg3 with spaces\"" +// +// All arguments must be within double quotes, even numbers. +// Unlike the spae function, this fuction executes the supplied +// routine in the foreground, rather than spawning it in a separate +// task. +int +spaef (FUNCPTR entry, ...) +{ + static const int WINDSH_ARGS = 10; + static const int MAX_ARGS = 128; + static char* argv[MAX_ARGS] = { "ace_main", 0 }; + va_list pvar; + int argc = 1; + + // Peel off arguments to spa () and put into argv. va_arg () isn't + // necessarily supposed to return 0 when done, though since the + // VxWorks shell uses a fixed number (10) of arguments, it might 0 + // the unused ones. + va_start (pvar, entry); + + int i = 0; + for (char* str = va_arg (pvar, char*); + str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i) + { + add_to_argv(argc, argv, MAX_ARGS, str); + } + + // fill unused argv slots with 0 to get rid of leftovers + // from previous invocations + for (i = argc; i < MAX_ARGS; ++i) + argv[i] = 0; + + int ret = entry (argc, argv); + + va_end (pvar); + + // Return the return value of the invoked ace_main routine. + return ret; +} +# endif /* VXWORKS */ + +# if !defined (ACE_HAS_SIGINFO_T) +# if !defined (ACE_HAS_PACE) || !defined (ACE_WIN32) +siginfo_t::siginfo_t (ACE_HANDLE handle) + : si_handle_ (handle), + si_handles_ (&handle) +{ +} + +siginfo_t::siginfo_t (ACE_HANDLE *handles) + : si_handle_ (handles[0]), + si_handles_ (handles) +{ +} +# endif /* ! ACE_HAS_PACE || ! ACE_WIN32 */ +# endif /* ACE_HAS_SIGINFO_T */ + +pid_t +ACE_OS::fork (const ACE_TCHAR *program_name) +{ + ACE_OS_TRACE ("ACE_OS::fork"); +# if defined (ACE_LACKS_FORK) + ACE_UNUSED_ARG (program_name); + ACE_NOTSUP_RETURN (pid_t (-1)); +# else + pid_t pid = +# if defined (ACE_HAS_STHREADS) + ::fork1 (); +#else + ::fork (); +#endif /* ACE_HAS_STHREADS */ + +#if !defined (ACE_HAS_MINIMAL_ACE_OS) + if (pid == 0) + ACE_Base_Thread_Adapter::sync_log_msg (program_name); +#endif /* ! ACE_HAS_MINIMAL_ACE_OS */ + + return pid; +# endif /* ACE_WIN32 */ +} + +void +ACE_Cleanup::cleanup (void *) +{ + delete this; +} + + +ACE_Cleanup::~ACE_Cleanup (void) +{ +} + +// This is necessary to work around nasty problems with MVS C++. + +extern "C" void +ace_mutex_lock_cleanup_adapter (void *args) +{ + ACE_OS::mutex_lock_cleanup (args); +} + +ACE_Thread_ID::ACE_Thread_ID (ACE_thread_t thread_id, + ACE_hthread_t thread_handle) + : thread_id_ (thread_id), + thread_handle_ (thread_handle) +{ +} + +ACE_Thread_ID::ACE_Thread_ID (const ACE_Thread_ID &id) + : thread_id_ (id.thread_id_), + thread_handle_ (id.thread_handle_) +{ +} + +ACE_thread_t +ACE_Thread_ID::id (void) +{ + return this->thread_id_; +} + +void +ACE_Thread_ID::id (ACE_thread_t thread_id) +{ + this->thread_id_ = thread_id; +} + +ACE_hthread_t +ACE_Thread_ID::handle (void) +{ + return this->thread_handle_; +} + +void +ACE_Thread_ID::handle (ACE_hthread_t thread_handle) +{ + this->thread_handle_ = thread_handle; +} + +int +ACE_Thread_ID::operator== (const ACE_Thread_ID &rhs) const +{ + return ACE_OS::thr_cmp (this->thread_handle_, rhs.thread_handle_) == 0 + && ACE_OS::thr_equal (this->thread_id_, rhs.thread_id_) == 0; +} + +int +ACE_Thread_ID::operator!= (const ACE_Thread_ID &rhs) const +{ + return !(*this == rhs); +} + +// All other platforms have this inlined in OS.i +#if defined (ACE_PSOS) +char * +ACE_OS::inet_ntoa (const struct in_addr addr) +{ + ACE_OS_TRACE ("ACE_OS::inet_ntoa"); + + static char addrstr[INET_ADDRSTRLEN + 1] = { 0 }; + ACE_UINT32 ipaddr = ntohl (addr.s_addr); + //printf("Socket address %X, IP address %X.\n",addr.s_addr,ipaddr); + sprintf(addrstr, "%d.%d.%d.%d", + ((ipaddr & 0xff000000) >> 24) & 0x000000ff, + (ipaddr & 0x00ff0000) >> 16, + (ipaddr & 0x0000ff00) >> 8, + (ipaddr & 0x000000ff)); + return addrstr; +} +#endif /* defined (ACE_PSOS) */ + +int +ACE_OS::inet_aton (const char *host_name, struct in_addr *addr) +{ +#if defined (ACE_LACKS_INET_ATON) + ACE_UINT32 ip_addr = ACE_OS::inet_addr (host_name); + + if (ip_addr == INADDR_NONE + // Broadcast addresses are weird... + && ACE_OS::strcmp (host_name, "255.255.255.255") != 0) + return 0; + else if (addr == 0) + return 0; + else + { + addr->s_addr = ip_addr; // Network byte ordered + return 1; + } +#else + // inet_aton() returns 0 upon failure, not -1 since -1 is a valid + // address (255.255.255.255). + ACE_OSCALL_RETURN (::inet_aton (host_name, addr), int, 0); +#endif /* ACE_LACKS_INET_ATON */ +} + +struct tm * +ACE_OS::localtime_r (const time_t *t, struct tm *res) +{ + ACE_OS_TRACE ("ACE_OS::localtime_r"); +#if defined (ACE_HAS_REENTRANT_FUNCTIONS) +# if defined (DIGITAL_UNIX) + ACE_OSCALL_RETURN (::_Plocaltime_r (t, res), struct tm *, 0); +# elif defined (HPUX_10) + return (::localtime_r (t, res) == 0 ? res : (struct tm *)0); +# else + ACE_OSCALL_RETURN (::localtime_r (t, res), struct tm *, 0); +# endif /* DIGITAL_UNIX */ +#elif !defined (ACE_HAS_WINCE) && !defined(ACE_PSOS) || defined (ACE_PSOS_HAS_TIME) + ACE_OS_GUARD + + ACE_UNUSED_ARG (res); + struct tm * res_ptr; + ACE_OSCALL (::localtime (t), struct tm *, 0, res_ptr); + if (res_ptr == 0) + return 0; + else + { + *res = *res_ptr; + return res; + } +#else + // @@ Same as ACE_OS::localtime (), you need to implement it + // yourself. + ACE_UNUSED_ARG (t); + ACE_UNUSED_ARG (res); + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_REENTRANT_FUNCTIONS */ +} + +ssize_t +ACE_OS::pread (ACE_HANDLE handle, + void *buf, + size_t nbytes, + off_t offset) +{ +# if defined (ACE_HAS_P_READ_WRITE) +# if defined (ACE_WIN32) + + ACE_OS_GUARD + + // Remember the original file pointer position + DWORD original_position = ::SetFilePointer (handle, + 0, + NULL, + FILE_CURRENT); + + if (original_position == 0xFFFFFFFF) + return -1; + + // Go to the correct position + DWORD altered_position = ::SetFilePointer (handle, + offset, + NULL, + FILE_BEGIN); + if (altered_position == 0xFFFFFFFF) + return -1; + + DWORD bytes_read; + +# if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0) + + OVERLAPPED overlapped; + overlapped.Internal = 0; + overlapped.InternalHigh = 0; + overlapped.Offset = offset; + overlapped.OffsetHigh = 0; + overlapped.hEvent = 0; + + BOOL result = ::ReadFile (handle, + buf, + nbytes, + &bytes_read, + &overlapped); + + if (result == FALSE) + { + if (::GetLastError () != ERROR_IO_PENDING) + return -1; + + else + { + result = ::GetOverlappedResult (handle, + &overlapped, + &bytes_read, + TRUE); + if (result == FALSE) + return -1; + } + } + +# else /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ + + BOOL result = ::ReadFile (handle, + buf, + nbytes, + &bytes_read, + NULL); + if (result == FALSE) + return -1; + +# endif /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ + + // Reset the original file pointer position + if (::SetFilePointer (handle, + original_position, + NULL, + FILE_BEGIN) == 0xFFFFFFFF) + return -1; + + return (ssize_t) bytes_read; + +# else /* ACE_WIN32 */ + + return ::pread (handle, buf, nbytes, offset); + +# endif /* ACE_WIN32 */ + +# else /* ACE_HAS_P_READ_WRITE */ + + ACE_OS_GUARD + + // Remember the original file pointer position + off_t original_position = ACE_OS::lseek (handle, + 0, + SEEK_CUR); + + if (original_position == -1) + return -1; + + // Go to the correct position + off_t altered_position = ACE_OS::lseek (handle, + offset, + SEEK_SET); + + if (altered_position == -1) + return -1; + + ssize_t bytes_read = ACE_OS::read (handle, + buf, + nbytes); + + if (bytes_read == -1) + return -1; + + if (ACE_OS::lseek (handle, + original_position, + SEEK_SET) == -1) + return -1; + + return bytes_read; + +# endif /* ACE_HAD_P_READ_WRITE */ +} + +ssize_t +ACE_OS::pwrite (ACE_HANDLE handle, + const void *buf, + size_t nbytes, + off_t offset) +{ +# if defined (ACE_HAS_P_READ_WRITE) +# if defined (ACE_WIN32) + + ACE_OS_GUARD + + // Remember the original file pointer position + DWORD original_position = ::SetFilePointer (handle, + 0, + NULL, + FILE_CURRENT); + + if (original_position == 0xFFFFFFFF) + return -1; + + // Go to the correct position + DWORD altered_position = ::SetFilePointer (handle, + offset, + NULL, + FILE_BEGIN); + if (altered_position == 0xFFFFFFFF) + return -1; + + DWORD bytes_written; + +# if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0) + + OVERLAPPED overlapped; + overlapped.Internal = 0; + overlapped.InternalHigh = 0; + overlapped.Offset = offset; + overlapped.OffsetHigh = 0; + overlapped.hEvent = 0; + + BOOL result = ::WriteFile (handle, + buf, + nbytes, + &bytes_written, + &overlapped); + + if (result == FALSE) + { + if (::GetLastError () != ERROR_IO_PENDING) + return -1; + + else + { + result = ::GetOverlappedResult (handle, + &overlapped, + &bytes_written, + TRUE); + if (result == FALSE) + return -1; + } + } + +# else /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ + + BOOL result = ::WriteFile (handle, + buf, + nbytes, + &bytes_written, + NULL); + if (result == FALSE) + return -1; + +# endif /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ + + // Reset the original file pointer position + if (::SetFilePointer (handle, + original_position, + NULL, + FILE_BEGIN) == 0xFFFFFFFF) + return -1; + + return (ssize_t) bytes_written; + +# else /* ACE_WIN32 */ + + return ::pwrite (handle, buf, nbytes, offset); +# endif /* ACE_WIN32 */ +# else /* ACE_HAS_P_READ_WRITE */ + + ACE_OS_GUARD + + // Remember the original file pointer position + off_t original_position = ACE_OS::lseek (handle, + 0, + SEEK_CUR); + if (original_position == -1) + return -1; + + // Go to the correct position + off_t altered_position = ACE_OS::lseek (handle, + offset, + SEEK_SET); + if (altered_position == -1) + return -1; + + ssize_t bytes_written = ACE_OS::write (handle, + buf, + nbytes); + if (bytes_written == -1) + return -1; + + if (ACE_OS::lseek (handle, + original_position, + SEEK_SET) == -1) + return -1; + + return bytes_written; +# endif /* ACE_HAD_P_READ_WRITE */ +} + +ACE_HANDLE +ACE_OS::open (const char *filename, + int mode, + int perms, + LPSECURITY_ATTRIBUTES sa) +{ + ACE_OS_TRACE ("ACE_OS::open"); + +#if defined (ACE_WIN32) + DWORD access = GENERIC_READ; + if (ACE_BIT_ENABLED (mode, O_WRONLY)) + access = GENERIC_WRITE; + else if (ACE_BIT_ENABLED (mode, O_RDWR)) + access = GENERIC_READ | GENERIC_WRITE; + + DWORD creation = OPEN_EXISTING; + + if ((mode & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL)) + creation = CREATE_NEW; + else if ((mode & (_O_CREAT | _O_TRUNC)) == (_O_CREAT | _O_TRUNC)) + creation = CREATE_ALWAYS; + else if (ACE_BIT_ENABLED (mode, _O_CREAT)) + creation = OPEN_ALWAYS; + else if (ACE_BIT_ENABLED (mode, _O_TRUNC)) + creation = TRUNCATE_EXISTING; + + DWORD flags = 0; + + if (ACE_BIT_ENABLED (mode, _O_TEMPORARY)) + flags |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY; + + if (ACE_BIT_ENABLED (mode, FILE_FLAG_WRITE_THROUGH)) + flags |= FILE_FLAG_WRITE_THROUGH; + if (ACE_BIT_ENABLED (mode, FILE_FLAG_OVERLAPPED)) + flags |= FILE_FLAG_OVERLAPPED; + if (ACE_BIT_ENABLED (mode, FILE_FLAG_NO_BUFFERING)) + flags |= FILE_FLAG_NO_BUFFERING; + if (ACE_BIT_ENABLED (mode, FILE_FLAG_RANDOM_ACCESS)) + flags |= FILE_FLAG_RANDOM_ACCESS; + if (ACE_BIT_ENABLED (mode, FILE_FLAG_SEQUENTIAL_SCAN)) + flags |= FILE_FLAG_SEQUENTIAL_SCAN; + if (ACE_BIT_ENABLED (mode, FILE_FLAG_DELETE_ON_CLOSE)) + flags |= FILE_FLAG_DELETE_ON_CLOSE; + if (ACE_BIT_ENABLED (mode, FILE_FLAG_BACKUP_SEMANTICS)) + flags |= FILE_FLAG_BACKUP_SEMANTICS; + if (ACE_BIT_ENABLED (mode, FILE_FLAG_POSIX_SEMANTICS)) + flags |= FILE_FLAG_POSIX_SEMANTICS; + + ACE_MT (ACE_thread_mutex_t *ace_os_monitor_lock = 0;) + + if (ACE_BIT_ENABLED (mode, _O_APPEND)) + { + ACE_MT + ( + ace_os_monitor_lock = (ACE_thread_mutex_t *) + ACE_OS_Object_Manager::preallocated_object[ + ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]; + ACE_OS::thread_mutex_lock (ace_os_monitor_lock); + ) + } + + DWORD shared_mode = perms; + +#if defined (ACE_HAS_WINCE) + ACE_HANDLE h = ::CreateFileW (ACE_Ascii_To_Wide (filename).wchar_rep (), access, + shared_mode, + ACE_OS::default_win32_security_attributes (sa), + creation, + flags, + 0); +#else /* ACE_HAS_WINCE */ + ACE_HANDLE h = ::CreateFileA (filename, access, + shared_mode, + ACE_OS::default_win32_security_attributes (sa), + creation, + flags, + 0); +#endif /* ACE_HAS_WINCE */ + + if (ACE_BIT_ENABLED (mode, _O_APPEND)) + { + if (h != ACE_INVALID_HANDLE) + { + ::SetFilePointer (h, 0, 0, FILE_END); + } + + ACE_MT (ACE_OS::thread_mutex_unlock (ace_os_monitor_lock);) + } + + if (h == ACE_INVALID_HANDLE) + ACE_FAIL_RETURN (h); + else + return h; +#elif defined (ACE_PSOS) + ACE_UNUSED_ARG (perms); + ACE_UNUSED_ARG (sa); +# if defined (ACE_PSOS_LACKS_PHILE) + ACE_UNUSED_ARG (filename); + return 0; +# else + unsigned long result, handle; + result = ::open_f (&handle, ACE_const_cast(char *, filename), 0); + if (result != 0) + { + // We need to clean this up...not 100% correct! + // To correct we should handle all the cases of TRUNC and CREAT + if ((result == 0x200B) && (ACE_BIT_ENABLED (mode, O_CREAT))) + { + result = ::create_f(ACE_const_cast(char *, filename),1,0); + if (result != 0) + { + errno = result; + return ACE_static_cast (ACE_HANDLE, -1); + } + else //File created...try to open it again + { + result = ::open_f (&handle, ACE_const_cast(char *, filename), 0); + if (result != 0) + { + errno = result; + return ACE_static_cast (ACE_HANDLE, -1); + } + + } + } + else + { + errno = result; + return ACE_static_cast (ACE_HANDLE, -1); + } + } + return ACE_static_cast (ACE_HANDLE, handle); +# endif /* defined (ACE_PSOS_LACKS_PHILE) */ +#else + ACE_UNUSED_ARG (sa); + ACE_OSCALL_RETURN (::open (filename, mode, perms), ACE_HANDLE, -1); +#endif /* ACE_WIN32 */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_HANDLE +ACE_OS::open (const wchar_t *filename, + int mode, + int perms, + LPSECURITY_ATTRIBUTES sa) +{ +#if defined (ACE_WIN32) + // @@ (brunsch) Yuck, maybe there is a way to combine the code + // here with the char version + + DWORD access = GENERIC_READ; + if (ACE_BIT_ENABLED (mode, O_WRONLY)) + access = GENERIC_WRITE; + else if (ACE_BIT_ENABLED (mode, O_RDWR)) + access = GENERIC_READ | GENERIC_WRITE; + + DWORD creation = OPEN_EXISTING; + + if ((mode & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL)) + creation = CREATE_NEW; + else if ((mode & (_O_CREAT | _O_TRUNC)) == (_O_CREAT | _O_TRUNC)) + creation = CREATE_ALWAYS; + else if (ACE_BIT_ENABLED (mode, _O_CREAT)) + creation = OPEN_ALWAYS; + else if (ACE_BIT_ENABLED (mode, _O_TRUNC)) + creation = TRUNCATE_EXISTING; + + DWORD flags = 0; + + if (ACE_BIT_ENABLED (mode, _O_TEMPORARY)) + flags |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY; + + if (ACE_BIT_ENABLED (mode, FILE_FLAG_WRITE_THROUGH)) + flags |= FILE_FLAG_WRITE_THROUGH; + if (ACE_BIT_ENABLED (mode, FILE_FLAG_OVERLAPPED)) + flags |= FILE_FLAG_OVERLAPPED; + if (ACE_BIT_ENABLED (mode, FILE_FLAG_NO_BUFFERING)) + flags |= FILE_FLAG_NO_BUFFERING; + if (ACE_BIT_ENABLED (mode, FILE_FLAG_RANDOM_ACCESS)) + flags |= FILE_FLAG_RANDOM_ACCESS; + if (ACE_BIT_ENABLED (mode, FILE_FLAG_SEQUENTIAL_SCAN)) + flags |= FILE_FLAG_SEQUENTIAL_SCAN; + if (ACE_BIT_ENABLED (mode, FILE_FLAG_DELETE_ON_CLOSE)) + flags |= FILE_FLAG_DELETE_ON_CLOSE; + if (ACE_BIT_ENABLED (mode, FILE_FLAG_BACKUP_SEMANTICS)) + flags |= FILE_FLAG_BACKUP_SEMANTICS; + if (ACE_BIT_ENABLED (mode, FILE_FLAG_POSIX_SEMANTICS)) + flags |= FILE_FLAG_POSIX_SEMANTICS; + + ACE_MT (ACE_thread_mutex_t *ace_os_monitor_lock = 0;) + + if (ACE_BIT_ENABLED (mode, _O_APPEND)) + { + ACE_MT + ( + ace_os_monitor_lock = (ACE_thread_mutex_t *) + ACE_OS_Object_Manager::preallocated_object[ + ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]; + ACE_OS::thread_mutex_lock (ace_os_monitor_lock); + ) + } + + DWORD shared_mode = perms; + + ACE_HANDLE h = ::CreateFileW (filename, + access, + shared_mode, + ACE_OS::default_win32_security_attributes (sa), + creation, + flags, + 0); + + if (ACE_BIT_ENABLED (mode, _O_APPEND)) + { + if (h != ACE_INVALID_HANDLE) + { + ::SetFilePointer (h, 0, 0, FILE_END); + } + + ACE_MT (ACE_OS::thread_mutex_unlock (ace_os_monitor_lock);) + } + + if (h == ACE_INVALID_HANDLE) + ACE_FAIL_RETURN (h); + else + return h; +#else /* ACE_WIN32 */ + // Just emulate with ascii version + return ACE_OS::open (ACE_Wide_To_Ascii (filename).char_rep (), + mode, + perms, + sa); +#endif /* ACE_WIN32 */ +} +#endif /* ACE_HAS_WCHAR */ + +# if defined (ACE_LACKS_DIFFTIME) +double +ACE_OS::difftime (time_t t1, time_t t0) +{ + /* return t1 - t0 in seconds */ + struct tm tms[2], *ptms[2], temp; + double seconds; + double days; + int swap = 0; + + /* extract the tm structure from time_t */ + ptms[1] = gmtime_r (&t1, &tms[1]); + if (ptms[1] == 0) return 0.0; + + ptms[0] = gmtime_r (&t0, &tms[0]); + if (ptms[0] == 0) return 0.0; + + /* make sure t1 is > t0 */ + if (tms[1].tm_year < tms[0].tm_year) + swap = 1; + else if (tms[1].tm_year == tms[0].tm_year) + { + if (tms[1].tm_yday < tms[0].tm_yday) + swap = 1; + else if (tms[1].tm_yday == tms[0].tm_yday) + { + if (tms[1].tm_hour < tms[0].tm_hour) + swap = 1; + else if (tms[1].tm_hour == tms[0].tm_hour) + { + if (tms[1].tm_min < tms[0].tm_min) + swap = 1; + else if (tms[1].tm_min == tms[0].tm_min) + { + if (tms[1].tm_sec < tms[0].tm_sec) + swap = 1; + } + } + } + } + + if (swap) + temp = tms[0], tms[0] = tms[1], tms[1] = temp; + + seconds = 0.0; + if (tms[1].tm_year > tms[0].tm_year) + { + // Accumulate the time until t[0] catches up to t[1]'s year. + seconds = 60 - tms[0].tm_sec; + tms[0].tm_sec = 0; + tms[0].tm_min += 1; + seconds += 60 * (60 - tms[0].tm_min); + tms[0].tm_min = 0; + tms[0].tm_hour += 1; + seconds += 60*60 * (24 - tms[0].tm_hour); + tms[0].tm_hour = 0; + tms[0].tm_yday += 1; + +# define ISLEAPYEAR(y) ((y)&3u?0:(y)%25u?1:(y)/25u&12?0:1) + + if (ISLEAPYEAR(tms[0].tm_year)) + seconds += 60*60*24 * (366 - tms[0].tm_yday); + else + seconds += 60*60*24 * (365 - tms[0].tm_yday); + + tms[0].tm_yday = 0; + tms[0].tm_year += 1; + + while (tms[1].tm_year > tms[0].tm_year) + { + if (ISLEAPYEAR(tms[0].tm_year)) + seconds += 60*60*24 * 366; + else + seconds += 60*60*24 * 365; + + tms[0].tm_year += 1; + } + +# undef ISLEAPYEAR + + } + else + { + // Normalize + if (tms[1].tm_sec < tms[0].tm_sec) + { + if (tms[1].tm_min == 0) + { + if (tms[1].tm_hour == 0) + { + tms[1].tm_yday -= 1; + tms[1].tm_hour += 24; + } + tms[1].tm_hour -= 1; + tms[1].tm_min += 60; + } + tms[1].tm_min -= 1; + tms[1].tm_sec += 60; + } + tms[1].tm_sec -= tms[0].tm_sec; + + if (tms[1].tm_min < tms[0].tm_min) + { + if (tms[1].tm_hour == 0) + { + tms[1].tm_yday -= 1; + tms[1].tm_hour += 24; + } + tms[1].tm_hour -= 1; + tms[1].tm_min += 60; + } + tms[1].tm_min -= tms[0].tm_min; + + if (tms[1].tm_hour < tms[0].tm_hour) + { + tms[1].tm_yday -= 1; + tms[1].tm_hour += 24; + } + tms[1].tm_hour -= tms[0].tm_hour; + + tms[1].tm_yday -= tms[0].tm_yday; + } + + // accumulate the seconds + seconds += tms[1].tm_sec; + seconds += 60 * tms[1].tm_min; + seconds += 60*60 * tms[1].tm_hour; + seconds += 60*60*24 * tms[1].tm_yday; + + return seconds; +} +# endif /* ACE_LACKS_DIFFTIME */ + +# if defined (ACE_HAS_WINCE) +ACE_TCHAR * +ACE_OS::ctime_r (const time_t *clock, ACE_TCHAR *buf, int buflen) +{ + // buflen must be at least 26 wchar_t long. + if (buflen < 26) // Again, 26 is a magic number. + return 0; + // This is really stupid, converting FILETIME to timeval back and + // forth. It assumes FILETIME and DWORDLONG are the same structure + // internally. + ULARGE_INTEGER _100ns; + _100ns.QuadPart = (DWORDLONG) *clock * 10000 * 1000 + + ACE_Time_Value::FILETIME_to_timval_skew; + FILETIME file_time; + file_time.dwLowDateTime = _100ns.LowPart; + file_time.dwHighDateTime = _100ns.HighPart; + + FILETIME localtime; + SYSTEMTIME systime; + FileTimeToLocalFileTime (&file_time, &localtime); + FileTimeToSystemTime (&localtime, &systime); + ACE_OS::sprintf (buf, ACE_OS_CTIME_R_FMTSTR, + ACE_OS::day_of_week_name[systime.wDayOfWeek], + ACE_OS::month_name[systime.wMonth - 1], + systime.wDay, + systime.wHour, + systime.wMinute, + systime.wSecond, + systime.wYear); + return buf; +} +# endif /* ACE_HAS_WINCE */ + +# if !defined (ACE_HAS_WINCE) +time_t +ACE_OS::mktime (struct tm *t) +{ + ACE_OS_TRACE ("ACE_OS::mktime"); +# if defined (ACE_PSOS) && ! defined (ACE_PSOS_HAS_TIME) + ACE_UNUSED_ARG (t); + ACE_NOTSUP_RETURN (-1); +# else +# if defined (ACE_HAS_THREADS) && !defined (ACE_HAS_MT_SAFE_MKTIME) + ACE_OS_GUARD +# endif /* ACE_HAS_THREADS && ! ACE_HAS_MT_SAFE_MKTIME */ + + ACE_OSCALL_RETURN (::mktime (t), time_t, (time_t) -1); +# endif /* ACE_PSOS && ! ACE_PSOS_HAS_TIME */ +} +# endif /* !ACE_HAS_WINCE */ + +# if !defined (ACE_HAS_THREADS) || defined (ACE_LACKS_RWLOCK_T) +int +ACE_OS::rwlock_init (ACE_rwlock_t *rw, + int type, + const ACE_TCHAR *name, + void *arg) +{ + // ACE_OS_TRACE ("ACE_OS::rwlock_init"); +# if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_RWLOCK_T) + // NT, POSIX, and VxWorks don't support this natively. + ACE_UNUSED_ARG (name); + int result = -1; + + // Since we cannot use the user specified name for all three + // objects, we will create three completely new names. + ACE_TCHAR name1[ACE_UNIQUE_NAME_LEN]; + ACE_TCHAR name2[ACE_UNIQUE_NAME_LEN]; + ACE_TCHAR name3[ACE_UNIQUE_NAME_LEN]; + ACE_TCHAR name4[ACE_UNIQUE_NAME_LEN]; + + ACE_OS::unique_name ((const void *) &rw->lock_, + name1, + ACE_UNIQUE_NAME_LEN); + ACE_OS::unique_name ((const void *) &rw->waiting_readers_, + name2, + ACE_UNIQUE_NAME_LEN); + ACE_OS::unique_name ((const void *) &rw->waiting_writers_, + name3, + ACE_UNIQUE_NAME_LEN); + ACE_OS::unique_name ((const void *) &rw->waiting_important_writer_, + name4, + ACE_UNIQUE_NAME_LEN); + + ACE_condattr_t attributes; + if (ACE_OS::condattr_init (attributes, type) == 0) + { + if (ACE_OS::mutex_init (&rw->lock_, type, name1, + (ACE_mutexattr_t *) arg) == 0 + && ACE_OS::cond_init (&rw->waiting_readers_, + attributes, name2, arg) == 0 + && ACE_OS::cond_init (&rw->waiting_writers_, + attributes, name3, arg) == 0 + && ACE_OS::cond_init (&rw->waiting_important_writer_, + attributes, name4, arg) == 0) + { + // Success! + rw->ref_count_ = 0; + rw->num_waiting_writers_ = 0; + rw->num_waiting_readers_ = 0; + rw->important_writer_ = 0; + result = 0; + } + ACE_OS::condattr_destroy (attributes); + } + + if (result == -1) + { + // Save/restore errno. + ACE_Errno_Guard error (errno); + ACE_OS::mutex_destroy (&rw->lock_); + ACE_OS::cond_destroy (&rw->waiting_readers_); + ACE_OS::cond_destroy (&rw->waiting_writers_); + ACE_OS::cond_destroy (&rw->waiting_important_writer_); + } + return result; +# else + ACE_UNUSED_ARG (rw); + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (arg); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_THREADS */ +} +# endif /* ! ACE_HAS_THREADS || ACE_LACKS_RWLOCK_T */ + +// If we're using PACE then we don't want this method (since PACE +// takes care of it) unless we're on Windows. Win32 mutexes, semaphores, +// and condition variables are not yet supported in PACE. +#if defined (ACE_LACKS_COND_T) && ! defined (ACE_PSOS_DIAB_MIPS) && ! (defined (ACE_HAS_PACE) && ! defined (ACE_WIN32)) +// NOTE: The ACE_OS::cond_* functions for some non-Unix platforms are +// defined here either because they're too big to be inlined, or +// to avoid use before definition if they were inline. + +int +ACE_OS::cond_destroy (ACE_cond_t *cv) +{ + ACE_OS_TRACE ("ACE_OS::cond_destroy"); +# if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_WTHREADS) + ACE_OS::event_destroy (&cv->waiters_done_); +# elif defined (VXWORKS) || defined (ACE_PSOS) + ACE_OS::sema_destroy (&cv->waiters_done_); +# endif /* VXWORKS */ + ACE_OS::thread_mutex_destroy (&cv->waiters_lock_); + return ACE_OS::sema_destroy (&cv->sema_); +# else + ACE_UNUSED_ARG (cv); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_THREADS */ +} + +// @@ The following functions could be inlined if i could figure where +// to put it among the #ifdefs! +int +ACE_OS::condattr_init (ACE_condattr_t &attributes, + int type) +{ + attributes.type = type; + return 0; +} + +int +ACE_OS::condattr_destroy (ACE_condattr_t &) +{ + return 0; +} + +int +ACE_OS::cond_init (ACE_cond_t *cv, + ACE_condattr_t &attributes, + const char *name, void *arg) +{ + return ACE_OS::cond_init (cv, attributes.type, name, arg); +} + +#if defined (ACE_HAS_WCHAR) +int +ACE_OS::cond_init (ACE_cond_t *cv, + ACE_condattr_t &attributes, + const wchar_t *name, void *arg) +{ + return ACE_OS::cond_init (cv, attributes.type, name, arg); +} +#endif /* ACE_HAS_WCHAR */ + +int +ACE_OS::cond_init (ACE_cond_t *cv, short type, const char *name, void *arg) +{ + ACE_OS_TRACE ("ACE_OS::cond_init"); +# if defined (ACE_HAS_THREADS) + cv->waiters_ = 0; + cv->was_broadcast_ = 0; + + int result = 0; + if (ACE_OS::sema_init (&cv->sema_, 0, type, name, arg) == -1) + result = -1; + else if (ACE_OS::thread_mutex_init (&cv->waiters_lock_) == -1) + result = -1; +# if defined (VXWORKS) || defined (ACE_PSOS) + else if (ACE_OS::sema_init (&cv->waiters_done_, 0, type) == -1) +# else + else if (ACE_OS::event_init (&cv->waiters_done_) == -1) +# endif /* VXWORKS */ + result = -1; + return result; +# else + ACE_UNUSED_ARG (cv); + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (arg); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_THREADS */ +} + +#if defined (ACE_HAS_WCHAR) +int +ACE_OS::cond_init (ACE_cond_t *cv, short type, const wchar_t *name, void *arg) +{ + ACE_OS_TRACE ("ACE_OS::cond_init"); +# if defined (ACE_HAS_THREADS) + cv->waiters_ = 0; + cv->was_broadcast_ = 0; + + int result = 0; + if (ACE_OS::sema_init (&cv->sema_, 0, type, name, arg) == -1) + result = -1; + else if (ACE_OS::thread_mutex_init (&cv->waiters_lock_) == -1) + result = -1; +# if defined (VXWORKS) || defined (ACE_PSOS) + else if (ACE_OS::sema_init (&cv->waiters_done_, 0, type) == -1) +# else + else if (ACE_OS::event_init (&cv->waiters_done_) == -1) +# endif /* VXWORKS */ + result = -1; + return result; +# else + ACE_UNUSED_ARG (cv); + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (arg); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_THREADS */ +} +#endif /* ACE_HAS_WCHAR */ + +int +ACE_OS::cond_signal (ACE_cond_t *cv) +{ + ACE_OS_TRACE ("ACE_OS::cond_signal"); +# if defined (ACE_HAS_THREADS) + // If there aren't any waiters, then this is a no-op. Note that + // this function *must* be called with the held + // since other wise there is a race condition that can lead to the + // lost wakeup bug... This is needed to ensure that the + // value is not in an inconsistent internal state while being + // updated by another thread. + ACE_OS::thread_mutex_lock (&cv->waiters_lock_); + int have_waiters = cv->waiters_ > 0; + ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); + + if (have_waiters != 0) + return ACE_OS::sema_post (&cv->sema_); + else + return 0; // No-op +# else + ACE_UNUSED_ARG (cv); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_THREADS */ +} + +int +ACE_OS::cond_broadcast (ACE_cond_t *cv) +{ + ACE_OS_TRACE ("ACE_OS::cond_broadcast"); +# if defined (ACE_HAS_THREADS) + // The must be locked before this call is made. + + // This is needed to ensure that and are + // consistent relative to each other. + ACE_OS::thread_mutex_lock (&cv->waiters_lock_); + int have_waiters = 0; + + if (cv->waiters_ > 0) + { + // We are broadcasting, even if there is just one waiter... + // Record the fact that we are broadcasting. This helps the + // cond_wait() method know how to optimize itself. Be sure to + // set this with the held. + cv->was_broadcast_ = 1; + have_waiters = 1; + } + ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); + int result = 0; + if (have_waiters) + { + // Wake up all the waiters. + if (ACE_OS::sema_post (&cv->sema_, cv->waiters_) == -1) + result = -1; + // Wait for all the awakened threads to acquire their part of + // the counting semaphore. +# if defined (VXWORKS) || defined (ACE_PSOS) + else if (ACE_OS::sema_wait (&cv->waiters_done_) == -1) +# else + else if (ACE_OS::event_wait (&cv->waiters_done_) == -1) +# endif /* VXWORKS */ + result = -1; + // This is okay, even without the held because + // no other waiter threads can wake up to access it. + cv->was_broadcast_ = 0; + } + return result; +# else + ACE_UNUSED_ARG (cv); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_THREADS */ +} + +int +ACE_OS::cond_wait (ACE_cond_t *cv, + ACE_mutex_t *external_mutex) +{ + ACE_OS_TRACE ("ACE_OS::cond_wait"); +# if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + return (::pace_pthread_cond_wait(cv, external_mutex); +# elif defined (ACE_HAS_THREADS) + // Prevent race conditions on the count. + ACE_OS::thread_mutex_lock (&cv->waiters_lock_); + cv->waiters_++; + ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); + + int result = 0; + +# if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT) + if (external_mutex->type_ == USYNC_PROCESS) + // This call will automatically release the mutex and wait on the semaphore. +# if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (external_mutex->proc_mutex_, + cv->sema_.sema_, INFINITE, FALSE), + result), + int, -1, result); +# else + ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (external_mutex->proc_mutex_, + cv->sema_, INFINITE, FALSE), + result), + int, -1, result); +# endif /* ACE_HAS_PACE && !ACE_WIN32 */ + else +# endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */ + { + // We keep the lock held just long enough to increment the count of + // waiters by one. Note that we can't keep it held across the call + // to ACE_OS::sema_wait() since that will deadlock other calls to + // ACE_OS::cond_signal(). + if (ACE_OS::mutex_unlock (external_mutex) != 0) + return -1; + + // Wait to be awakened by a ACE_OS::cond_signal() or + // ACE_OS::cond_broadcast(). + result = ACE_OS::sema_wait (&cv->sema_); + } + + // Reacquire lock to avoid race conditions on the count. + ACE_OS::thread_mutex_lock (&cv->waiters_lock_); + + // We're ready to return, so there's one less waiter. + cv->waiters_--; + + int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0; + + // Release the lock so that other collaborating threads can make + // progress. + ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); + + if (result == -1) + // Bad things happened, so let's just return below. + /* NOOP */; +# if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT) + else if (external_mutex->type_ == USYNC_PROCESS) + { + if (last_waiter) + + // This call atomically signals the event and + // waits until it can acquire the mutex. This is important to + // prevent unfairness. + ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_, + external_mutex->proc_mutex_, + INFINITE, FALSE), + result), + int, -1, result); + else + // We must always regain the , even when + // errors occur because that's the guarantee that we give to + // our callers. + ACE_OS::mutex_lock (external_mutex); + + return result; + /* NOTREACHED */ + } +# endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */ + // If we're the last waiter thread during this particular broadcast + // then let all the other threads proceed. + else if (last_waiter) +# if defined (VXWORKS) || defined (ACE_PSOS) + ACE_OS::sema_post (&cv->waiters_done_); +# else + ACE_OS::event_signal (&cv->waiters_done_); +# endif /* VXWORKS */ + + // We must always regain the , even when errors + // occur because that's the guarantee that we give to our callers. + ACE_OS::mutex_lock (external_mutex); + + return result; +# else + ACE_UNUSED_ARG (cv); + ACE_UNUSED_ARG (external_mutex); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_THREADS */ +} + +int +ACE_OS::cond_timedwait (ACE_cond_t *cv, + ACE_mutex_t *external_mutex, + ACE_Time_Value *timeout) +{ + ACE_OS_TRACE ("ACE_OS::cond_timedwait"); +# if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + return (::pace_pthread_cond_timedwait(cv, external_mutex, timeout); +# elif defined (ACE_HAS_THREADS) + // Handle the easy case first. + if (timeout == 0) + return ACE_OS::cond_wait (cv, external_mutex); +# if defined (ACE_HAS_WTHREADS) || defined (VXWORKS) || defined (ACE_PSOS) + + // Prevent race conditions on the count. + ACE_OS::thread_mutex_lock (&cv->waiters_lock_); + cv->waiters_++; + ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); + + int result = 0; + ACE_Errno_Guard error (errno, 0); + int msec_timeout; + + if (timeout->sec () == 0 && timeout->usec () == 0) + msec_timeout = 0; // Do a "poll." + else + { + // Note that we must convert between absolute time (which is + // passed as a parameter) and relative time (which is what + // WaitForSingleObjects() expects). + ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ()); + + // Watchout for situations where a context switch has caused the + // current time to be > the timeout. + if (relative_time < ACE_Time_Value::zero) + msec_timeout = 0; + else + msec_timeout = relative_time.msec (); + } + +# if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT) + if (external_mutex->type_ == USYNC_PROCESS) + // This call will automatically release the mutex and wait on the + // semaphore. +# if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + result = ::SignalObjectAndWait (external_mutex->proc_mutex_, + cv->sema_.sema_, + msec_timeout, + FALSE); +# else + result = ::SignalObjectAndWait (external_mutex->proc_mutex_, + cv->sema_, + msec_timeout, + FALSE); +# endif /* ACE_HAS_PACE && !ACE_WIN32 */ + else +# endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */ + { + // We keep the lock held just long enough to increment the count + // of waiters by one. Note that we can't keep it held across + // the call to WaitForSingleObject since that will deadlock + // other calls to ACE_OS::cond_signal(). + if (ACE_OS::mutex_unlock (external_mutex) != 0) + return -1; + + // Wait to be awakened by a ACE_OS::signal() or + // ACE_OS::broadcast(). +# if defined (ACE_WIN32) +# if !defined (ACE_USES_WINCE_SEMA_SIMULATION) + result = ::WaitForSingleObject (cv->sema_, msec_timeout); +# else /* ACE_USES_WINCE_SEMA_SIMULATION */ + // Can't use Win32 API on our simulated semaphores. + result = ACE_OS::sema_wait (&cv->sema_, + ACE_Time_Value (0, msec_timeout * 1000)); +# endif /* ACE_USES_WINCE_SEMA_SIMULATION */ +# elif defined (ACE_PSOS) + // Inline the call to ACE_OS::sema_wait () because it takes an + // ACE_Time_Value argument. Avoid the cost of that conversion . . . + u_long ticks = (KC_TICKS2SEC * msec_timeout) / ACE_ONE_SECOND_IN_MSECS; + //Tick set to 0 tells pSOS to wait forever is SM_WAIT is set. + if(ticks == 0) + result = ::sm_p (cv->sema_.sema_, SM_NOWAIT, ticks); //no timeout + else + result = ::sm_p (cv->sema_.sema_, SM_WAIT, ticks); +# elif defined (VXWORKS) + // Inline the call to ACE_OS::sema_wait () because it takes an + // ACE_Time_Value argument. Avoid the cost of that conversion . . . + int ticks_per_sec = ::sysClkRateGet (); + int ticks = msec_timeout * ticks_per_sec / ACE_ONE_SECOND_IN_MSECS; + result = ::semTake (cv->sema_.sema_, ticks); +# endif /* ACE_WIN32 || VXWORKS */ + } + + // Reacquire lock to avoid race conditions. + ACE_OS::thread_mutex_lock (&cv->waiters_lock_); + cv->waiters_--; + + int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0; + + ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); + +# if defined (ACE_WIN32) + if (result != WAIT_OBJECT_0) + { + switch (result) + { + case WAIT_TIMEOUT: + error = ETIME; + break; + default: + error = ::GetLastError (); + break; + } + result = -1; + } +# elif defined (ACE_PSOS) + if (result != 0) + { + switch (result) + { + case ERR_TIMEOUT: // Timeout occured with SM_WAIT + case ERR_NOMSG: // Didn't acquire semaphore w/ SM_NOWAIT (ticks=0) + error = ETIME; + break; + default: + error = errno; + break; + } + result = -1; + } +# elif defined (VXWORKS) + if (result == ERROR) + { + switch (errno) + { + case S_objLib_OBJ_TIMEOUT: + error = ETIME; + break; + case S_objLib_OBJ_UNAVAILABLE: + if (msec_timeout == 0) + error = ETIME; + break; + default: + error = errno; + break; + } + result = -1; + } +# endif /* ACE_WIN32 || VXWORKS */ +# if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT) + if (external_mutex->type_ == USYNC_PROCESS) + { + if (last_waiter) + // This call atomically signals the event and + // waits until it can acquire the mutex. This is important to + // prevent unfairness. + ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_, + external_mutex->proc_mutex_, + INFINITE, FALSE), + result), + int, -1, result); + else + // We must always regain the , even when + // errors occur because that's the guarantee that we give to + // our callers. + ACE_OS::mutex_lock (external_mutex); + + return result; + /* NOTREACHED */ + } +# endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */ + // Note that this *must* be an "if" statement rather than an "else + // if" statement since the caller may have timed out and hence the + // result would have been -1 above. + if (last_waiter) + // Release the signaler/broadcaster if we're the last waiter. +# if defined (ACE_WIN32) + ACE_OS::event_signal (&cv->waiters_done_); +# else + ACE_OS::sema_post (&cv->waiters_done_); +# endif /* ACE_WIN32 */ + + // We must always regain the , even when errors + // occur because that's the guarantee that we give to our callers. + ACE_OS::mutex_lock (external_mutex); + + return result; +# endif /* ACE_HAS_WTHREADS || ACE_HAS_VXWORKS || ACE_PSOS */ +# else + ACE_UNUSED_ARG (cv); + ACE_UNUSED_ARG (external_mutex); + ACE_UNUSED_ARG (timeout); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_THREADS */ +} + +# if defined (ACE_HAS_WTHREADS) +int +ACE_OS::cond_timedwait (ACE_cond_t *cv, + ACE_thread_mutex_t *external_mutex, + ACE_Time_Value *timeout) +{ + ACE_OS_TRACE ("ACE_OS::cond_timedwait"); +# if defined (ACE_HAS_THREADS) + // Handle the easy case first. + if (timeout == 0) + return ACE_OS::cond_wait (cv, external_mutex); + + // Prevent race conditions on the count. + ACE_OS::thread_mutex_lock (&cv->waiters_lock_); + cv->waiters_++; + ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); + + int result = 0; + int error = 0; + int msec_timeout; + + if (timeout->sec () == 0 && timeout->usec () == 0) + msec_timeout = 0; // Do a "poll." + else + { + // Note that we must convert between absolute time (which is + // passed as a parameter) and relative time (which is what + // WaitForSingleObjects() expects). + ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ()); + + // Watchout for situations where a context switch has caused the + // current time to be > the timeout. + if (relative_time < ACE_Time_Value::zero) + msec_timeout = 0; + else + msec_timeout = relative_time.msec (); + } + + // We keep the lock held just long enough to increment the count of + // waiters by one. Note that we can't keep it held across the call + // to WaitForSingleObject since that will deadlock other calls to + // ACE_OS::cond_signal(). + if (ACE_OS::thread_mutex_unlock (external_mutex) != 0) + return -1; + + // Wait to be awakened by a ACE_OS::signal() or ACE_OS::broadcast(). +# if defined (ACE_USES_WINCE_SEMA_SIMULATION) + // Can't use Win32 API on simulated semaphores. + result = ACE_OS::sema_wait (&cv->sema_, + ACE_Time_Value (0, msec_timeout * 1000)); + + if (result == -1 && errno == ETIME) + result = WAIT_TIMEOUT; +# else + result = ::WaitForSingleObject (cv->sema_, msec_timeout); +# endif /* ACE_USES_WINCE_SEMA_SIMULATION */ + + // Reacquire lock to avoid race conditions. + ACE_OS::thread_mutex_lock (&cv->waiters_lock_); + + cv->waiters_--; + + int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0; + + ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); + + if (result != WAIT_OBJECT_0) + { + switch (result) + { + case WAIT_TIMEOUT: + error = ETIME; + break; + default: + error = ::GetLastError (); + break; + } + result = -1; + } + + if (last_waiter) + // Release the signaler/broadcaster if we're the last waiter. + ACE_OS::event_signal (&cv->waiters_done_); + + // We must always regain the , even when errors + // occur because that's the guarantee that we give to our callers. + ACE_OS::thread_mutex_lock (external_mutex); + errno = error; + return result; +# else + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_THREADS */ +} + +int +ACE_OS::cond_wait (ACE_cond_t *cv, + ACE_thread_mutex_t *external_mutex) +{ + ACE_OS_TRACE ("ACE_OS::cond_wait"); +# if defined (ACE_HAS_THREADS) + ACE_OS::thread_mutex_lock (&cv->waiters_lock_); + cv->waiters_++; + ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); + + int result = 0; + int error = 0; + + // We keep the lock held just long enough to increment the count of + // waiters by one. Note that we can't keep it held across the call + // to ACE_OS::sema_wait() since that will deadlock other calls to + // ACE_OS::cond_signal(). + if (ACE_OS::thread_mutex_unlock (external_mutex) != 0) + return -1; + + // Wait to be awakened by a ACE_OS::cond_signal() or + // ACE_OS::cond_broadcast(). +# if !defined (ACE_USES_WINCE_SEMA_SIMULATION) + result = ::WaitForSingleObject (cv->sema_, INFINITE); +# else + // Can't use Win32 API on simulated semaphores. + result = ACE_OS::sema_wait (&cv->sema_); + + if (result != WAIT_OBJECT_0 && errno == ETIME) + result = WAIT_TIMEOUT; + +# endif /* ACE_USES_WINCE_SEMA_SIMULATION */ + + // Reacquire lock to avoid race conditions. + ACE_OS::thread_mutex_lock (&cv->waiters_lock_); + + cv->waiters_--; + + int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0; + + ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); + + if (result != WAIT_OBJECT_0) + { + switch (result) + { + case WAIT_TIMEOUT: + error = ETIME; + break; + default: + error = ::GetLastError (); + break; + } + } + else if (last_waiter) + // Release the signaler/broadcaster if we're the last waiter. + ACE_OS::event_signal (&cv->waiters_done_); + + // We must always regain the , even when errors + // occur because that's the guarantee that we give to our callers. + ACE_OS::thread_mutex_lock (external_mutex); + + // Reset errno in case mutex_lock() also fails... + errno = error; + return result; +# else + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_THREADS */ +} +# endif /* ACE_HAS_WTHREADS */ +#endif /* ACE_LACKS_COND_T */ + +void +ACE_OS::exit (int status) +{ + ACE_OS_TRACE ("ACE_OS::exit"); + +#if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) && !defined (ACE_HAS_WINCE) && !defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER) + // Shut down the ACE_Object_Manager, if it had registered its exit_hook. + // With ACE_HAS_NONSTATIC_OBJECT_MANAGER, the ACE_Object_Manager is + // instantiated on the main's stack. ::exit () doesn't destroy it. + if (exit_hook_) + (*exit_hook_) (); +#endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER && !ACE_HAS_WINCE && !ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER */ + +#if !defined (ACE_HAS_WINCE) +# if defined (ACE_WIN32) + ::ExitProcess ((UINT) status); +# elif defined (ACE_PSOSIM) + ::u_exit (status); +# else + ::exit (status); +# endif /* ACE_WIN32 */ +#else + // @@ This is not exactly the same as ExitProcess. But this is the + // closest one I can get. + ::TerminateProcess (::GetCurrentProcess (), status); +#endif /* ACE_HAS_WINCE */ +} + +# if defined (ACE_PSOS) + +// bit masks and shifts for prying info out of the pSOS time encoding +const u_long ACE_PSOS_Time_t::year_mask = 0x0000FFFFul; +const u_long ACE_PSOS_Time_t::month_mask = 0x000000FFul; +const u_long ACE_PSOS_Time_t::day_mask = 0x000000FFul; +const u_long ACE_PSOS_Time_t::hour_mask = 0x0000FFFFul; +const u_long ACE_PSOS_Time_t::minute_mask = 0x000000FFul; +const u_long ACE_PSOS_Time_t::second_mask = 0x000000FFul; +const int ACE_PSOS_Time_t::year_shift = 16; +const int ACE_PSOS_Time_t::month_shift = 8; +const int ACE_PSOS_Time_t::hour_shift = 16; +const int ACE_PSOS_Time_t::minute_shift = 8; +const int ACE_PSOS_Time_t::year_origin = 1900; +const int ACE_PSOS_Time_t::month_origin = 1; + +// maximum number of clock ticks supported +const u_long ACE_PSOS_Time_t::max_ticks = ~0UL; + +ACE_PSOS_Time_t::ACE_PSOS_Time_t (void) + : date_ (0), + time_ (0), + ticks_ (0) +{ +} + +// default ctor: date, time, and ticks all zeroed + +ACE_PSOS_Time_t::ACE_PSOS_Time_t (const timespec_t& t) +{ + struct tm* tm_struct = ACE_OS::gmtime (&(t.tv_sec)); + + // Encode date values from tm struct into pSOS date bit array. + date_ = (ACE_PSOS_Time_t::year_mask & + ACE_static_cast (u_long, + tm_struct->tm_year + ACE_PSOS_Time_t::year_origin)) << + ACE_PSOS_Time_t::year_shift; + date_ |= (ACE_PSOS_Time_t::month_mask & + ACE_static_cast (u_long, + tm_struct->tm_mon + ACE_PSOS_Time_t::month_origin)) << + ACE_PSOS_Time_t::month_shift; + date_ |= ACE_PSOS_Time_t::day_mask & + ACE_static_cast (u_long, tm_struct->tm_mday); + // Encode time values from tm struct into pSOS time bit array. + time_ = (ACE_PSOS_Time_t::hour_mask & + ACE_static_cast (u_long, tm_struct->tm_hour)) << + ACE_PSOS_Time_t::hour_shift; + time_ |= (ACE_PSOS_Time_t::minute_mask & + ACE_static_cast (u_long, tm_struct->tm_min)) << + ACE_PSOS_Time_t::minute_shift; + time_ |= ACE_PSOS_Time_t::second_mask & + ACE_static_cast (u_int, tm_struct->tm_sec); + + // encode nanoseconds as system clock ticks + ticks_ = ACE_static_cast (u_long, + ((ACE_static_cast (double, t.tv_nsec) * + ACE_static_cast (double, KC_TICKS2SEC)) / + ACE_static_cast (double, 1000000000))); + +} + +// ctor from a timespec_t + +ACE_PSOS_Time_t::operator timespec_t (void) +{ + struct tm tm_struct; + + // Decode date and time bit arrays and fill in fields of tm_struct. + + tm_struct.tm_year = + ACE_static_cast (int, (ACE_PSOS_Time_t::year_mask & + (date_ >> ACE_PSOS_Time_t::year_shift))) - + ACE_PSOS_Time_t::year_origin; + tm_struct.tm_mon = + ACE_static_cast (int, (ACE_PSOS_Time_t::month_mask & + (date_ >> ACE_PSOS_Time_t::month_shift))) - + ACE_PSOS_Time_t::month_origin; + tm_struct.tm_mday = + ACE_static_cast (int, (ACE_PSOS_Time_t::day_mask & date_)); + tm_struct.tm_hour = + ACE_static_cast (int, (ACE_PSOS_Time_t::hour_mask & + (time_ >> ACE_PSOS_Time_t::hour_shift))); + tm_struct.tm_min = + ACE_static_cast (int, (ACE_PSOS_Time_t::minute_mask & + (time_ >> ACE_PSOS_Time_t::minute_shift))); + tm_struct.tm_sec = + ACE_static_cast (int, (ACE_PSOS_Time_t::second_mask & time_)); + + // Indicate values we don't know as negative numbers. + tm_struct.tm_wday = -1; + tm_struct.tm_yday = -1; + tm_struct.tm_isdst = -1; + + timespec_t t; + + // Convert calendar time to time struct. + t.tv_sec = ACE_OS::mktime (&tm_struct); + + // Encode nanoseconds as system clock ticks. + t.tv_nsec = ACE_static_cast (long, + ((ACE_static_cast (double, ticks_) * + ACE_static_cast (double, 1000000000)) / + ACE_static_cast (double, KC_TICKS2SEC))); + return t; +} + +// type cast operator (to a timespec_t) + +u_long +ACE_PSOS_Time_t::get_system_time (ACE_PSOS_Time_t& t) +{ + u_long ret_val = 0; + +# if defined (ACE_PSOSIM) // system time is broken in simulator. + timeval tv; + int result = 0; + ACE_OSCALL (::gettimeofday (&tv, 0), int, -1, result); + if (result == -1) + return 1; + + ACE_Time_Value atv (tv); + timespec ts = atv; + ACE_PSOS_Time_t pt (ts); + t.date_ = pt.date_; + t.time_ = pt.time_; + t.ticks_ = pt.ticks_; +# else + ret_val = tm_get (&(t.date_), &(t.time_), &(t.ticks_)); +# endif /* ACE_PSOSIM */ + return ret_val; +} + +// Static member function to get current system time. + +u_long +ACE_PSOS_Time_t::set_system_time (const ACE_PSOS_Time_t& t) +{ + return tm_set (t.date_, t.time_, t.ticks_); +} + +// Static member function to set current system time. + +# if defined (ACE_PSOSIM) + +u_long +ACE_PSOS_Time_t::init_simulator_time (void) +{ + // This is a hack using a direct UNIX system call, because the + // appropriate ACE_OS method ultimately uses the pSOS tm_get + // function, which would fail because the simulator's system time is + // uninitialized (chicken and egg). + timeval t; + int result = 0; + ACE_OSCALL (::gettimeofday (&t, 0), + int, + -1, + result); + + if (result == -1) + return 1; + else + { + ACE_Time_Value tv (t); + timespec ts = tv; + ACE_PSOS_Time_t pt (ts); + u_long ret_val = + ACE_PSOS_Time_t::set_system_time (pt); + return ret_val; + + } +} + +// Static member function to initialize system time, using UNIX calls. + +# endif /* ACE_PSOSIM */ +# endif /* ACE_PSOS && ! ACE_PSOS_DIAB_MIPS */ + +# if defined (__DGUX) && defined (ACE_HAS_THREADS) && defined (_POSIX4A_DRAFT10_SOURCE) +extern "C" int __d6_sigwait (sigset_t *set); + +extern "C" int __d10_sigwait (const sigset_t *set, int *sig) +{ + sigset_t unconst_set = *set; + int caught_sig = __d6_sigwait (&unconst_set); + + if (caught == -1) + return -1; + + *sig = caught_sig; + return 0; +} +# endif /* __DGUX && PTHREADS && _POSIX4A_DRAFT10_SOURCE */ + +# define ACE_OS_PREALLOCATE_OBJECT(TYPE, ID)\ + {\ + TYPE *obj_p = 0;\ + ACE_NEW_RETURN (obj_p, TYPE, -1);\ + preallocated_object[ID] = (void *) obj_p;\ + } +# define ACE_OS_DELETE_PREALLOCATED_OBJECT(TYPE, ID)\ + delete (TYPE *) preallocated_object[ID];\ + preallocated_object[ID] = 0; + +ACE_Object_Manager_Base::ACE_Object_Manager_Base (void) + : object_manager_state_ (OBJ_MAN_UNINITIALIZED) + , dynamically_allocated_ (0) + , next_ (0) +{ +} + +ACE_Object_Manager_Base::~ACE_Object_Manager_Base (void) +{ +#if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) + // Clear the flag so that fini () doesn't delete again. + dynamically_allocated_ = 0; +#endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER */ +} + +int +ACE_Object_Manager_Base::starting_up_i () +{ + return object_manager_state_ < OBJ_MAN_INITIALIZED; +} + +int +ACE_Object_Manager_Base::shutting_down_i () +{ + return object_manager_state_ > OBJ_MAN_INITIALIZED; +} + +extern "C" +void +ACE_OS_Object_Manager_Internal_Exit_Hook (void) +{ + if (ACE_OS_Object_Manager::instance_) + ACE_OS_Object_Manager::instance ()->fini (); +} + +ACE_OS_Object_Manager *ACE_OS_Object_Manager::instance_ = 0; + +void *ACE_OS_Object_Manager::preallocated_object[ + ACE_OS_Object_Manager::ACE_OS_PREALLOCATED_OBJECTS] = { 0 }; + +ACE_OS_Object_Manager::ACE_OS_Object_Manager (void) + // default_mask_ isn't initialized, because it's defined by . + : thread_hook_ (0) + , exit_info_ () +#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) + , seh_except_selector_ (ACE_SEH_Default_Exception_Selector) + , seh_except_handler_ (ACE_SEH_Default_Exception_Handler) +#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ +{ + // If instance_ was not 0, then another ACE_OS_Object_Manager has + // already been instantiated (it is likely to be one initialized by + // way of library/DLL loading). Let this one go through + // construction in case there really is a good reason for it (like, + // ACE is a static/archive library, and this one is the non-static + // instance (with ACE_HAS_NONSTATIC_OBJECT_MANAGER, or the user has + // a good reason for creating a separate one) but the original one + // will be the one retrieved from calls to + // ACE_Object_Manager::instance(). + + // Be sure that no further instances are created via instance (). + if (instance_ == 0) + instance_ = this; + + init (); +} + +ACE_OS_Object_Manager::~ACE_OS_Object_Manager (void) +{ + dynamically_allocated_ = 0; // Don't delete this again in fini() + fini (); +} + +sigset_t * +ACE_OS_Object_Manager::default_mask (void) +{ + return ACE_OS_Object_Manager::instance ()->default_mask_; +} + +ACE_Thread_Hook * +ACE_OS_Object_Manager::thread_hook (void) +{ + return ACE_OS_Object_Manager::instance ()->thread_hook_; +} + +#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) +ACE_SEH_EXCEPT_HANDLER +ACE_OS_Object_Manager::seh_except_selector (void) +{ + return ACE_OS_Object_Manager::instance ()->seh_except_selector_; +} + +ACE_SEH_EXCEPT_HANDLER +ACE_OS_Object_Manager::seh_except_selector (ACE_SEH_EXCEPT_HANDLER n) +{ + ACE_OS_Object_Manager *instance = + ACE_OS_Object_Manager::instance (); + + ACE_SEH_EXCEPT_HANDLER retv = instance->seh_except_selector_; + instance->seh_except_selector_ = n; + return retv; +} + +ACE_SEH_EXCEPT_HANDLER +ACE_OS_Object_Manager::seh_except_handler (void) +{ + return ACE_OS_Object_Manager::instance ()->seh_except_handler_; +} + +ACE_SEH_EXCEPT_HANDLER +ACE_OS_Object_Manager::seh_except_handler (ACE_SEH_EXCEPT_HANDLER n) +{ + ACE_OS_Object_Manager *instance = + ACE_OS_Object_Manager::instance (); + + ACE_SEH_EXCEPT_HANDLER retv = instance->seh_except_handler_; + instance->seh_except_handler_ = n; + return retv; +} +#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ + +ACE_Thread_Hook * +ACE_OS_Object_Manager::thread_hook (ACE_Thread_Hook *new_thread_hook) +{ + ACE_OS_Object_Manager *os_om = ACE_OS_Object_Manager::instance (); + ACE_Thread_Hook *old_hook = os_om->thread_hook_; + os_om->thread_hook_ = new_thread_hook; + return old_hook; +} + +ACE_OS_Object_Manager * +ACE_OS_Object_Manager::instance (void) +{ + // This function should be called during construction of static + // instances, or before any other threads have been created in the + // process. So, it's not thread safe. + + if (instance_ == 0) + { + ACE_OS_Object_Manager *instance_pointer; + + ACE_NEW_RETURN (instance_pointer, + ACE_OS_Object_Manager, + 0); + // I (coryan) removed it, using asserts in the OS layer + // brings down the Log msg stuff + // ACE_ASSERT (instance_pointer == instance_); + + instance_pointer->dynamically_allocated_ = 1; + + } + + return instance_; +} + +int +ACE_OS_Object_Manager::init (void) +{ + if (starting_up_i ()) + { + // First, indicate that this ACE_OS_Object_Manager instance is being + // initialized. + object_manager_state_ = OBJ_MAN_INITIALIZING; + + if (this == instance_) + { +# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) +# if defined (ACE_HAS_WINCE_BROKEN_ERRNO) + ACE_CE_Errno::init (); +# endif /* ACE_HAS_WINCE_BROKEN_ERRNO */ + ACE_OS_PREALLOCATE_OBJECT (ACE_thread_mutex_t, ACE_OS_MONITOR_LOCK) + if (ACE_OS::thread_mutex_init + // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor. + (ACE_reinterpret_cast (ACE_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_OS_MONITOR_LOCK])) != 0) + ACE_OS_Object_Manager::print_error_message ( + __LINE__, ACE_LIB_TEXT ("ACE_OS_MONITOR_LOCK")); + ACE_OS_PREALLOCATE_OBJECT (ACE_recursive_thread_mutex_t, + ACE_TSS_CLEANUP_LOCK) + if (ACE_OS::recursive_mutex_init + // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor. + (ACE_reinterpret_cast (ACE_recursive_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_TSS_CLEANUP_LOCK])) != 0) + ACE_OS_Object_Manager::print_error_message ( + __LINE__, ACE_LIB_TEXT ("ACE_TSS_CLEANUP_LOCK")); + ACE_OS_PREALLOCATE_OBJECT (ACE_thread_mutex_t, + ACE_LOG_MSG_INSTANCE_LOCK) + if (ACE_OS::thread_mutex_init + // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor. + (ACE_reinterpret_cast (ACE_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_LOG_MSG_INSTANCE_LOCK])) != 0) + ACE_OS_Object_Manager::print_error_message ( + __LINE__, ACE_LIB_TEXT ("ACE_LOG_MSG_INSTANCE_LOCK")); +# if defined (ACE_HAS_TSS_EMULATION) + ACE_OS_PREALLOCATE_OBJECT (ACE_recursive_thread_mutex_t, + ACE_TSS_KEY_LOCK) + if (ACE_OS::recursive_mutex_init + // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor. + (ACE_reinterpret_cast (ACE_recursive_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_TSS_KEY_LOCK])) != 0) + ACE_OS_Object_Manager::print_error_message ( + __LINE__, ACE_LIB_TEXT ("ACE_TSS_KEY_LOCK")); +# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + ACE_OS_PREALLOCATE_OBJECT (ACE_recursive_thread_mutex_t, + ACE_TSS_BASE_LOCK) + if (ACE_OS::recursive_mutex_init + // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor. + (ACE_reinterpret_cast (ACE_recursive_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_TSS_BASE_LOCK])) != 0) + ACE_OS_Object_Manager::print_error_message ( + __LINE__, ACE_LIB_TEXT ("ACE_TSS_BASE_LOCK")); +# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ +# endif /* ACE_HAS_TSS_EMULATION */ +# endif /* ACE_MT_SAFE */ + + // Open Winsock (no-op on other platforms). + ACE_OS::socket_init (ACE_WSOCK_VERSION); + + // Register the exit hook, for use by ACE_OS::exit (). + ACE_OS::set_exit_hook (&ACE_OS_Object_Manager_Internal_Exit_Hook); + } + + ACE_NEW_RETURN (default_mask_, sigset_t, -1); + ACE_OS::sigfillset (default_mask_); + + // Finally, indicate that the ACE_OS_Object_Manager instance has + // been initialized. + object_manager_state_ = OBJ_MAN_INITIALIZED; + +# if defined (ACE_WIN32) + ACE_OS::win32_versioninfo_.dwOSVersionInfoSize = + sizeof (OSVERSIONINFO); + ::GetVersionEx (&ACE_OS::win32_versioninfo_); +# endif /* ACE_WIN32 */ + return 0; + } else { + // Had already initialized. + return 1; + } +} + +// Clean up an ACE_OS_Object_Manager. There can be instances of this object +// other than The Instance. This can happen if a user creates one for some +// reason. All objects clean up their per-object information and managed +// objects, but only The Instance cleans up the static preallocated objects. +int +ACE_OS_Object_Manager::fini (void) +{ + if (instance_ == 0 || shutting_down_i ()) + // Too late. Or, maybe too early. Either fini () has already + // been called, or init () was never called. + return object_manager_state_ == OBJ_MAN_SHUT_DOWN ? 1 : -1; + + // No mutex here. Only the main thread should destroy the singleton + // ACE_OS_Object_Manager instance. + + // Indicate that the ACE_OS_Object_Manager instance is being shut + // down. This object manager should be the last one to be shut + // down. + object_manager_state_ = OBJ_MAN_SHUTTING_DOWN; + + // If another Object_Manager has registered for termination, do it. + if (next_) + { + next_->fini (); + next_ = 0; // Protect against recursive calls. + } + + // Call all registered cleanup hooks, in reverse order of + // registration. + exit_info_.call_hooks (); + + // Only clean up preallocated objects when the singleton Instance is being + // destroyed. + if (this == instance_) + { + // Close down Winsock (no-op on other platforms). + ACE_OS::socket_fini (); + +#if ! defined (ACE_HAS_STATIC_PREALLOCATION) + // Cleanup the dynamically preallocated objects. +# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) +# if !defined(ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK) + if (ACE_OS::thread_mutex_destroy + // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor. + (ACE_reinterpret_cast (ACE_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_OS_MONITOR_LOCK])) != 0) + ACE_OS_Object_Manager::print_error_message ( + __LINE__, ACE_LIB_TEXT ("ACE_OS_MONITOR_LOCK")); +# endif /* ! ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK */ + ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_thread_mutex_t, + ACE_OS_MONITOR_LOCK) +# if !defined(ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK) + if (ACE_OS::recursive_mutex_destroy + // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor. + (ACE_reinterpret_cast (ACE_recursive_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_TSS_CLEANUP_LOCK])) != 0) + ACE_OS_Object_Manager::print_error_message ( + __LINE__, ACE_LIB_TEXT ("ACE_TSS_CLEANUP_LOCK")); +# endif /* ! ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK */ + ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_recursive_thread_mutex_t, + ACE_TSS_CLEANUP_LOCK) +# if !defined(ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK) + if (ACE_OS::thread_mutex_destroy + // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor. + (ACE_reinterpret_cast (ACE_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object [ACE_LOG_MSG_INSTANCE_LOCK])) != 0) + ACE_OS_Object_Manager::print_error_message ( + __LINE__, ACE_LIB_TEXT ("ACE_LOG_MSG_INSTANCE_LOCK ")); +# endif /* ! ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK */ + ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_thread_mutex_t, + ACE_LOG_MSG_INSTANCE_LOCK) +# if defined (ACE_HAS_TSS_EMULATION) +# if !defined(ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK) + if (ACE_OS::recursive_mutex_destroy + // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor. + (ACE_reinterpret_cast (ACE_recursive_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_TSS_KEY_LOCK])) != 0) + ACE_OS_Object_Manager::print_error_message ( + __LINE__, ACE_LIB_TEXT ("ACE_TSS_KEY_LOCK")); +# endif /* ! ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK */ + ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_recursive_thread_mutex_t, + ACE_TSS_KEY_LOCK) +# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) +# if !defined(ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK) + if (ACE_OS::recursive_mutex_destroy + // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor. + (ACE_reinterpret_cast (ACE_recursive_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_TSS_BASE_LOCK])) != 0) + ACE_OS_Object_Manager::print_error_message ( + __LINE__, ACE_LIB_TEXT ("ACE_TSS_BASE_LOCK")); +# endif /* ! ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK */ + ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_recursive_thread_mutex_t, + ACE_TSS_BASE_LOCK) +# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ +# endif /* ACE_HAS_TSS_EMULATION */ +# if defined (ACE_HAS_WINCE_BROKEN_ERRNO) + ACE_CE_Errno::fini (); +# endif /* ACE_HAS_WINCE_BROKEN_ERRNO */ +# endif /* ACE_MT_SAFE */ +#endif /* ! ACE_HAS_STATIC_PREALLOCATION */ + } + + delete default_mask_; + default_mask_ = 0; + + // Indicate that this ACE_OS_Object_Manager instance has been shut down. + object_manager_state_ = OBJ_MAN_SHUT_DOWN; + + if (dynamically_allocated_) + { + delete this; + } + + if (this == instance_) + instance_ = 0; + + return 0; +} + +int ace_exit_hook_marker = 0; + +int +ACE_OS_Object_Manager::at_exit (ACE_EXIT_HOOK func) +{ + return exit_info_.at_exit_i (&ace_exit_hook_marker, + ACE_reinterpret_cast (ACE_CLEANUP_FUNC, func), + 0); +} + +void +ACE_OS_Object_Manager::print_error_message (u_int line_number, + const ACE_TCHAR *message) +{ + // To avoid duplication of these const strings in OS.o. +#if !defined (ACE_HAS_WINCE) + fprintf (stderr, "ace/OS.cpp, line %u: %s ", + line_number, + message); + perror ("failed"); +#else + // @@ Need to use the following information. + ACE_UNUSED_ARG (line_number); + ACE_UNUSED_ARG (message); + + ACE_TCHAR *lpMsgBuf = 0; + ::FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + ::GetLastError (), + MAKELANGID (LANG_NEUTRAL, + SUBLANG_DEFAULT), + // Default language + (ACE_TCHAR *) &lpMsgBuf, + 0, + NULL); + ::MessageBox (NULL, + lpMsgBuf, + ACE_LIB_TEXT ("ACE_OS error"), + MB_OK); +#endif +} + +int +ACE_OS_Object_Manager::starting_up (void) +{ + return ACE_OS_Object_Manager::instance_ + ? instance_->starting_up_i () + : 1; +} + +int +ACE_OS_Object_Manager::shutting_down (void) +{ + return ACE_OS_Object_Manager::instance_ + ? instance_->shutting_down_i () + : 1; +} + +#if !defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) +class ACE_OS_Object_Manager_Manager + // = TITLE + // Ensure that the gets initialized at + // program startup, and destroyed at program termination. + // + // = DESCRIPTION + // Without ACE_HAS_NONSTATIC_OBJECT_MANAGER, a static instance of this + // class is created. Therefore, it gets created before main () + // is called. And it gets destroyed after main () returns. +{ +public: + ACE_OS_Object_Manager_Manager (void); + ~ACE_OS_Object_Manager_Manager (void); + +private: + ACE_thread_t saved_main_thread_id_; + // Save the main thread ID, so that destruction can be suppressed. +}; + +ACE_OS_Object_Manager_Manager::ACE_OS_Object_Manager_Manager (void) + : saved_main_thread_id_ (ACE_OS::thr_self ()) +{ + // Ensure that the Object_Manager gets initialized before any + // application threads have been spawned. Because this will be called + // during construction of static objects, that should always be the + // case. + (void) ACE_OS_Object_Manager::instance (); +} + +ACE_OS_Object_Manager_Manager::~ACE_OS_Object_Manager_Manager (void) +{ + if (ACE_OS::thr_equal (ACE_OS::thr_self (), + saved_main_thread_id_)) + { + delete ACE_OS_Object_Manager::instance_; + ACE_OS_Object_Manager::instance_ = 0; + } + // else if this destructor is not called by the main thread, then do + // not delete the ACE_OS_Object_Manager. That causes problems, on + // WIN32 at least. +} + +static ACE_OS_Object_Manager_Manager ACE_OS_Object_Manager_Manager_instance; +#endif /* ! ACE_HAS_NONSTATIC_OBJECT_MANAGER */ + +# if defined (ACE_HAS_WINCE) +ACE_CE_Bridge *ACE_CE_Bridge::default_text_bridge_ = 0; + +ACE_CE_Bridge::ACE_CE_Bridge (void) + : text_output_ (0), + notification_ (0), + idc_ (0) +{ +} + +ACE_CE_Bridge::ACE_CE_Bridge (HWND w, int n, int i) + : text_output_ (w), + notification_ (n), + idc_ (i) +{ +} + +void +ACE_CE_Bridge::set_window (HWND w, int n, int i) +{ + this->text_output_ = w; + this->notification_ = n; + this->idc_ = i; +} + +ACE_CE_Bridge::~ACE_CE_Bridge (void) +{ + // This method needs to be defined because there seems to be a bug + // in CE's compiler. +} + +void +ACE_CE_Bridge::set_self_default (void) +{ + ACE_CE_Bridge::default_text_bridge_ = this; +} + +int +ACE_CE_Bridge::notification (void) +{ + return this->notification_; +} + +int +ACE_CE_Bridge::idc (void) +{ + return this->idc_; +} + +HWND +ACE_CE_Bridge::window (void) +{ + return this->text_output_; +} + +ACE_CE_Bridge * +ACE_CE_Bridge::get_default_winbridge (void) +{ + return ACE_CE_Bridge::default_text_bridge_; +} + +int +ACE_CE_Bridge::write_msg (const ACE_TCHAR *str) +{ + ACE_TCHAR *s = ACE_OS::strdup (str); + return PostMessage (this->text_output_, + WM_COMMAND, + MAKEWORD (this->idc_, + this->notification_), + (long)((void *) s)); +} + +#if 0 +int +ACE_CE_Bridge::write_msg (CString *s) +{ + // Don't ask! + return PostMessage (this->text_output_, + WM_COMMAND, + MAKEWORD (this->idc_, + this->notification_), + (long)((void *) s)); +} +#endif /* 0 */ + +// **** Warning **** +// You should not use the following function under CE at all. This +// function is used to make Svc_Conf_l.cpp compile under WinCE. It +// might not do what it is expected to do under regular environments. +// **** Warning **** + +# if defined (UNDER_CE) && (UNDER_CE < 211) +void +exit (int status) +{ +# if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) && !defined (ACE_HAS_WINCE) && !defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER) + // Shut down the ACE_Object_Manager, if it had registered its exit_hook. + // With ACE_HAS_NONSTATIC_OBJECT_MANAGER, the ACE_Object_Manager is + // instantiated on the main's stack. ::exit () doesn't destroy it. + if (exit_hook_) + (*exit_hook_) (); +# endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER && !ACE_HAS_WINCE && !ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER */ + + ACE_OS::exit (status); +} +# endif /* UNDER_CE && UNDER_CE < 211 */ +# endif /* ACE_HAS_WINCE */ + +// You may be asking yourself, why are we doing this? Well, in winbase.h, +// MS didn't follow their normal Api_FunctionA and Api_FunctionW style, +// so we have to #undef their define to get access to the unicode version. +// And because we don't want to #undef this for the users code, we keep +// this method in the .cpp file. +#if defined (ACE_WIN32) && defined (UNICODE) && !defined (ACE_USES_TCHAR) +#undef GetEnvironmentStrings +#endif /* ACE_WIN32 && UNICODE !ACE_USES_TCHAR */ + +ACE_TCHAR * +ACE_OS::getenvstrings (void) +{ +#if defined (ACE_LACKS_ENV) + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_WIN32) +# if defined (ACE_USES_WCHAR) + return ::GetEnvironmentStringsW (); +# else /* ACE_USES_WCHAR */ + return ::GetEnvironmentStrings (); +# endif /* ACE_USES_WCHAR */ +#else /* ACE_WIN32 */ + ACE_NOTSUP_RETURN (0); +#endif /* ACE_WIN32 */ +} + +#if defined (ACE_HAS_STRPTIME) +char * +ACE_OS::strptime (char *buf, const char *format, struct tm *tm) +{ +#if !defined (ACE_HAS_WINCE) +#if defined (ACE_LACKS_NATIVE_STRPTIME) + int bi = 0; + int fi = 0; + int percent = 0; + + if (!buf || !format) + return 0; + + while (format[fi] != '\0') + { + if (percent) + { + percent = 0; + switch (format[fi]) + { + case '%': // an escaped % + if (buf[bi] == '%') + { + fi++; bi++; + } + else + return buf + bi; + break; + + /* not supported yet: weekday via locale long/short names + case 'a': / * weekday via locale * / + / * FALL THROUGH * / + case 'A': / * long/short names * / + break; + */ + + /* not supported yet: + case 'b': / * month via locale * / + / * FALL THROUGH * / + case 'B': / * long/short names * / + / * FALL THROUGH * / + case 'h': + break; + */ + + /* not supported yet: + case 'c': / * %x %X * / + break; + */ + + /* not supported yet: + case 'C': / * date & time - * / + / * locale long format * / + break; + */ + + case 'd': /* day of month (1-31) */ + /* FALL THROUGH */ + case 'e': + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_mday, &bi, &fi, 1, 31)) + return buf + bi; + + break; + + case 'D': /* %m/%d/%y */ + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_mon, &bi, &fi, 1, 12)) + return buf + bi; + + fi--; + tm->tm_mon--; + + if (buf[bi] != '/') + return buf + bi; + + bi++; + + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_mday, &bi, &fi, 1, 31)) + return buf + bi; + + fi--; + if (buf[bi] != '/') + return buf + bi; + bi++; + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_year, &bi, &fi, 0, 99)) + return buf + bi; + if (tm->tm_year < 69) + tm->tm_year += 100; + break; + + case 'H': /* hour (0-23) */ + /* FALL THROUGH */ + case 'k': + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_hour, &bi, &fi, 0, 23)) + return buf + bi; + break; + + /* not supported yet: + case 'I': / * hour (0-12) * / + / * FALL THROUGH * / + case 'l': + break; + */ + + case 'j': /* day of year (0-366) */ + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_yday, &bi, &fi, 1, 366)) + return buf + bi; + + tm->tm_yday--; + break; + + case 'm': /* an escaped % */ + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_mon, &bi, &fi, 1, 12)) + return buf + bi; + + tm->tm_mon--; + break; + + case 'M': /* minute (0-59) */ + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_min, &bi, &fi, 0, 59)) + return buf + bi; + + break; + + /* not supported yet: + case 'p': / * am or pm for locale * / + break; + */ + + /* not supported yet: + case 'r': / * %I:%M:%S %p * / + break; + */ + + case 'R': /* %H:%M */ + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_hour, &bi, &fi, 0, 23)) + return buf + bi; + + fi--; + if (buf[bi] != ':') + return buf + bi; + bi++; + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_min, &bi, &fi, 0, 59)) + return buf + bi; + + break; + + case 'S': /* seconds (0-61) */ + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_sec, &bi, &fi, 0, 61)) + return buf + bi; + break; + + case 'T': /* %H:%M:%S */ + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_hour, &bi, &fi, 0, 23)) + return buf + bi; + + fi--; + if (buf[bi] != ':') + return buf + bi; + bi++; + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_min, &bi, &fi, 0, 59)) + return buf + bi; + + fi--; + if (buf[bi] != ':') + return buf + bi; + bi++; + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_sec, &bi, &fi, 0, 61)) + return buf + bi; + + break; + + case 'w': /* day of week (0=Sun-6) */ + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_wday, &bi, &fi, 0, 6)) + return buf + bi; + + break; + + /* not supported yet: date, based on locale + case 'x': / * date, based on locale * / + break; + */ + + /* not supported yet: + case 'X': / * time, based on locale * / + break; + */ + + case 'y': /* the year - 1900 (0-99) */ + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_year, &bi, &fi, 0, 99)) + return buf + bi; + + if (tm->tm_year < 69) + tm->tm_year += 100; + break; + + case 'Y': /* the full year (1999) */ + if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_year, &bi, &fi, 0, 0)) + return buf + bi; + + tm->tm_year -= 1900; + break; + + default: /* unrecognised */ + return buf + bi; + } /* switch (format[fi]) */ + + } + else + { /* if (percent) */ + if (format[fi] == '%') + { + percent = 1; + fi++; + } + else + { + if (format[fi] == buf[bi]) + { + fi++; + bi++; + } + else + return buf + bi; + } + } /* if (percent) */ + } /* while (format[fi] */ + + return buf + bi; +#else /* ! ACE_LACKS_NATIVE_STRPTIME */ + return ::strptime (buf, + format, + tm); +#endif /* ! ACE_LACKS_NATIVE_STRPTIME */ +#else /* ! ACE_HAS_WINCE */ + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (format); + ACE_UNUSED_ARG (tm); + + ACE_NOTSUP_RETURN (0); +#endif /* ! ACE_HAS_WINCE */ +} + +# if defined (ACE_LACKS_NATIVE_STRPTIME) +int +ACE_OS::strptime_getnum (char *buf, + int *num, + int *bi, + int *fi, + int min, + int max) +{ + int i = 0, tmp = 0; + + while (isdigit (buf[i])) + { + tmp = (tmp * 10) + (buf[i] - '0'); + if (max && (tmp > max)) + return 0; + i++; + } + + if (tmp < min) + return 0; + else if (i) + { + *num = tmp; + (*fi)++; + *bi += i; + return 1; + } + else + return 0; +} +# endif /* ACE_LACKS_NATIVE_STRPTIME */ +#endif /* ACE_HAS_STRPTIME */ + +ACE_HANDLE +ACE_OS::accept (ACE_HANDLE handle, + struct sockaddr *addr, + int *addrlen, + const ACE_Accept_QoS_Params &qos_params) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + ACE_SOCKCALL_RETURN (::WSAAccept ((ACE_SOCKET) handle, + addr, + (ACE_SOCKET_LEN *) addrlen, + (LPCONDITIONPROC) qos_params.qos_condition_callback (), + qos_params.callback_data ()), + ACE_HANDLE, + ACE_INVALID_HANDLE); +#else + ACE_UNUSED_ARG (qos_params); + return ACE_OS::accept (handle, + addr, + addrlen); +#endif /* ACE_HAS_WINSOCK2 */ +} + +ACE_HANDLE +ACE_OS::join_leaf (ACE_HANDLE socket, + const sockaddr *name, + int namelen, + const ACE_QoS_Params &qos_params) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + + QOS qos; + // Construct the WinSock2 QOS structure. + + qos.SendingFlowspec = *(qos_params.socket_qos ()->sending_flowspec ()); + qos.ReceivingFlowspec = *(qos_params.socket_qos ()->receiving_flowspec ()); + qos.ProviderSpecific = (WSABUF) qos_params.socket_qos ()->provider_specific (); + + ACE_SOCKCALL_RETURN (::WSAJoinLeaf ((ACE_SOCKET) socket, + name, + namelen, + (WSABUF *) qos_params.caller_data (), + (WSABUF *) qos_params.callee_data (), + &qos, + (QOS *) qos_params.group_socket_qos (), + qos_params.flags ()), + ACE_HANDLE, + ACE_INVALID_HANDLE); + +#else + ACE_UNUSED_ARG (socket); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (namelen); + ACE_UNUSED_ARG (qos_params); + ACE_NOTSUP_RETURN (ACE_INVALID_HANDLE); +#endif /* ACE_HAS_WINSOCK2 */ +} + +int +ACE_OS::ioctl (ACE_HANDLE socket, + u_long io_control_code, + void *in_buffer_p, + u_long in_buffer, + void *out_buffer_p, + u_long out_buffer, + u_long *bytes_returned, + ACE_OVERLAPPED *overlapped, + ACE_OVERLAPPED_COMPLETION_FUNC func) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + ACE_SOCKCALL_RETURN (::WSAIoctl ((ACE_SOCKET) socket, + io_control_code, + in_buffer_p, + in_buffer, + out_buffer_p, + out_buffer, + bytes_returned, + (WSAOVERLAPPED *) overlapped, + func), + int, + SOCKET_ERROR); +#else + ACE_UNUSED_ARG (socket); + ACE_UNUSED_ARG (io_control_code); + ACE_UNUSED_ARG (in_buffer_p); + ACE_UNUSED_ARG (in_buffer); + ACE_UNUSED_ARG (out_buffer_p); + ACE_UNUSED_ARG (out_buffer); + ACE_UNUSED_ARG (bytes_returned); + ACE_UNUSED_ARG (overlapped); + ACE_UNUSED_ARG (func); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_WINSOCK2 */ +} + + + +int +ACE_OS::ioctl (ACE_HANDLE socket, + u_long io_control_code, + ACE_QoS &ace_qos, + u_long *bytes_returned, + void *buffer_p, + u_long buffer, + ACE_OVERLAPPED *overlapped, + ACE_OVERLAPPED_COMPLETION_FUNC func) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + + QOS qos; + u_long qos_len = sizeof (QOS); + + if (io_control_code == SIO_SET_QOS) + { + qos.SendingFlowspec = *(ace_qos.sending_flowspec ()); + qos.ReceivingFlowspec = *(ace_qos.receiving_flowspec ()); + qos.ProviderSpecific = (WSABUF) ace_qos.provider_specific (); + + qos_len += ace_qos.provider_specific ().iov_len; + + ACE_SOCKCALL_RETURN (::WSAIoctl ((ACE_SOCKET) socket, + io_control_code, + &qos, + qos_len, + buffer_p, + buffer, + bytes_returned, + (WSAOVERLAPPED *) overlapped, + func), + int, + SOCKET_ERROR); + } + else + { + u_long dwBufferLen = 0; + + // Query for the buffer size. + int result = ::WSAIoctl ((ACE_SOCKET) socket, + io_control_code, + NULL, + 0, + &dwBufferLen, + sizeof (dwBufferLen), + bytes_returned, + NULL, + NULL); + + + if (result == SOCKET_ERROR) + { + u_long dwErr = ::WSAGetLastError (); + + if (dwErr == WSAEWOULDBLOCK) + { + errno = dwErr; + return -1; + } + else + if (dwErr != WSAENOBUFS) + { + errno = dwErr; + return -1; + } + } + + char *qos_buf; + ACE_NEW_RETURN (qos_buf, + char [dwBufferLen], + -1); + + QOS *qos = ACE_reinterpret_cast (QOS*, + qos_buf); + + result = ::WSAIoctl ((ACE_SOCKET) socket, + io_control_code, + NULL, + 0, + qos, + dwBufferLen, + bytes_returned, + NULL, + NULL); + + if (result == SOCKET_ERROR) + return result; + + ACE_Flow_Spec sending_flowspec (qos->SendingFlowspec.TokenRate, + qos->SendingFlowspec.TokenBucketSize, + qos->SendingFlowspec.PeakBandwidth, + qos->SendingFlowspec.Latency, + qos->SendingFlowspec.DelayVariation, +#if defined(ACE_HAS_WINSOCK2_GQOS) + qos->SendingFlowspec.ServiceType, + qos->SendingFlowspec.MaxSduSize, + qos->SendingFlowspec.MinimumPolicedSize, +#else /* ACE_HAS_WINSOCK2_GQOS */ + 0, + 0, + 0, +#endif /* ACE_HAS_WINSOCK2_GQOS */ + 0, + 0); + + ACE_Flow_Spec receiving_flowspec (qos->ReceivingFlowspec.TokenRate, + qos->ReceivingFlowspec.TokenBucketSize, + qos->ReceivingFlowspec.PeakBandwidth, + qos->ReceivingFlowspec.Latency, + qos->ReceivingFlowspec.DelayVariation, +#if defined(ACE_HAS_WINSOCK2_GQOS) + qos->ReceivingFlowspec.ServiceType, + qos->ReceivingFlowspec.MaxSduSize, + qos->ReceivingFlowspec.MinimumPolicedSize, +#else /* ACE_HAS_WINSOCK2_GQOS */ + 0, + 0, + 0, +#endif /* ACE_HAS_WINSOCK2_GQOS */ + 0, + 0); + + ace_qos.sending_flowspec (&sending_flowspec); + ace_qos.receiving_flowspec (&receiving_flowspec); + ace_qos.provider_specific (*((struct iovec *) (&qos->ProviderSpecific))); + + + return result; + } + +#else + ACE_UNUSED_ARG (socket); + ACE_UNUSED_ARG (io_control_code); + ACE_UNUSED_ARG (ace_qos); + ACE_UNUSED_ARG (bytes_returned); + ACE_UNUSED_ARG (buffer_p); + ACE_UNUSED_ARG (buffer); + ACE_UNUSED_ARG (overlapped); + ACE_UNUSED_ARG (func); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_WINSOCK2 */ +} + +int +ACE_OS::connect (ACE_HANDLE handle, + const sockaddr *addr, + int addrlen, + const ACE_QoS_Params &qos_params) +{ + ACE_OS_TRACE ("ACE_OS::connect"); +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + ACE_SOCKCALL_RETURN (::WSAConnect ((ACE_SOCKET) handle, + (const sockaddr *) addr, + (ACE_SOCKET_LEN) addrlen, + (WSABUF *) qos_params.caller_data (), + (WSABUF *) qos_params.callee_data (), + (QOS *) qos_params.socket_qos (), + (QOS *) qos_params.group_socket_qos ()), + int, -1); +#else + ACE_UNUSED_ARG (qos_params); + return ACE_OS::connect (handle, + (sockaddr *) addr, + addrlen); +#endif /* ACE_HAS_WINSOCK2 */ +} diff --git a/ace/OS/OS.h b/ace/OS/OS.h new file mode 100644 index 00000000000..46b2214f4a2 --- /dev/null +++ b/ace/OS/OS.h @@ -0,0 +1,7529 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file OS.h + * + * $Id$ + * + * @author Douglas C. Schmidt + * @author Jesper S. M|ller + * @author and a cast of thousands... + */ +//============================================================================= + +#ifndef ACE_OS_H +#define ACE_OS_H + +#include "ace/pre.h" + +#include "ace/config-all.h" + +#if defined (ACE_HAS_VIRTUAL_TIME) +#include /**/ +#endif /*ACE_HAS_VIRTUAL_TIME*/ + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +// Include the split up ACE_OS classes +#include "OS_Dirent.h" +#include "OS_String.h" +#include "OS_Memory.h" +#include "OS_TLI.h" +#include "OS_Errno.h" + +class ACE_Timeout_Manager; + +#if !defined (_SC_AIO_MAX) +#define _SC_AIO_MAX 1 +#endif /* _SC_AIO_MAX */ + +// Do not change these values wantonly since GPERF depends on them.. +#define ACE_ASCII_SIZE 128 +#define ACE_EBCDIC_SIZE 256 + +#if 'a' < 'A' +#define ACE_HAS_EBCDIC +#define ACE_STANDARD_CHARACTER_SET_SIZE 256 +#else +#define ACE_HAS_ASCII +#define ACE_STANDARD_CHARACTER_SET_SIZE 128 +#endif /* 'a' < 'A' */ + +# if defined (ACE_PSOS_TM) +typedef long long longlong_t; +typedef long id_t; +# endif /* ACE_PSOS_TM */ + +// Deal with MSVC++ insanity for CORBA... +# if defined (ACE_HAS_BROKEN_NAMESPACES) +# define ACE_CORBA_1(NAME) CORBA_##NAME +# define ACE_CORBA_2(TYPE, NAME) CORBA_##TYPE##_##NAME +# define ACE_CORBA_3(TYPE, NAME) CORBA_##TYPE::NAME +# define ACE_NESTED_CLASS(TYPE, NAME) NAME +# else /* ! ACE_HAS_BROKEN_NAMESPACES */ +# define ACE_CORBA_1(NAME) CORBA::NAME +# define ACE_CORBA_2(TYPE, NAME) CORBA::TYPE::NAME +# define ACE_CORBA_3(TYPE, NAME) CORBA::TYPE::NAME +# define ACE_NESTED_CLASS(TYPE, NAME) TYPE::NAME +# endif /* ! ACE_HAS_BROKEN_NAMESPACES */ + +// Here are all ACE-specific default constants, needed throughout ACE +// and its applications. The values can be over written by user +// specific values in config.h files. +#include "ace/Default_Constants.h" + + +# if defined (ACE_HAS_4_4BSD_SENDMSG_RECVMSG) + // Control message size to pass a file descriptor. +# define ACE_BSD_CONTROL_MSG_LEN sizeof (struct cmsghdr) + sizeof (ACE_HANDLE) +# if defined (ACE_LACKS_CMSG_DATA_MACRO) +# if defined (ACE_LACKS_CMSG_DATA_MEMBER) +# define CMSG_DATA(cmsg) ((unsigned char *) ((struct cmsghdr *) (cmsg) + 1)) +# else +# define CMSG_DATA(cmsg) ((cmsg)->cmsg_data) +# endif /* ACE_LACKS_CMSG_DATA_MEMBER */ +# endif /* ACE_LACKS_CMSG_DATA_MACRO */ +# endif /* ACE_HAS_4_4BSD_SENDMSG_RECVMSG */ + + +// Default size of the ACE Reactor. +# if defined (FD_SETSIZE) +int const ACE_FD_SETSIZE = FD_SETSIZE; +# else +# define ACE_FD_SETSIZE FD_SETSIZE +# endif /* ACE_FD_SETSIZE */ + +# if !defined (ACE_DEFAULT_SELECT_REACTOR_SIZE) +# define ACE_DEFAULT_SELECT_REACTOR_SIZE ACE_FD_SETSIZE +# endif /* ACE_DEFAULT_SELECT_REACTOR_SIZE */ + + +// Here are all ACE-specific global declarations needed throughout +// ACE. +#include "Global_Macros.h" + +#if !defined (ACE_WIN32) +#define ACE_MAX_USERID L_cuserid +#endif /*!ACE_WIN32*/ + +// include the ACE min()/max() functions. +# include "ace/Min_Max.h" + + +// These hooks enable ACE to have all dynamic memory management +// automatically handled on a per-object basis. + +# if defined (ACE_LACKS_KEY_T) +# if defined (ACE_WIN32) + // Win32 doesn't use numeric values to name its semaphores, it uses + // strings! +typedef char *key_t; +# else +typedef int key_t; +# endif /* ACE_WIN32 */ +# endif /* ACE_LACKS_KEY_T */ + +/////////////////////////////////////////// +// // +// NOTE: Please do not add any #includes // +// before this point. On VxWorks, // +// vxWorks.h must be #included // +// first! // +// // +/////////////////////////////////////////// + +#if defined (ACE_HAS_PACE) +# include /**/ "pace/dirent.h" +# include /**/ "pace/fcntl.h" +# include /**/ "pace/sys/mman.h" +# include /**/ "pace/pthread.h" +# include /**/ "pace/pwd.h" +# include /**/ "pace/stdio.h" +# include /**/ "pace/stdlib.h" +# include /**/ "pace/sched.h" +# include /**/ "pace/semaphore.h" +# include /**/ "pace/signal.h" +# include /**/ "pace/sys/stat.h" +# include /**/ "pace/stdio.h" +# include /**/ "pace/time.h" +# include /**/ "pace/unistd.h" +# include /**/ "pace/sys/utsname.h" +# include /**/ "pace/sys/wait.h" +#endif /* ACE_HAS_PACE */ + +# if defined (ACE_PSOS) + +# if defined (ACE_LACKS_ASSERT_MACRO) +# define assert(expr) +# endif + +# if defined (ACE_PSOSIM) + +# include /**/ "ace/sys_conf.h" /* system configuration file */ +# include /**/ /* pSOS+ system calls */ +# include /**/ /* pNA+ TCP/IP Network Manager calls */ + + /* In the *simulator* environment, use unsigned int for size_t */ +# define size_t unsigned int + + + /* include pRPC+ Remote Procedure Call Library calls */ + /* are not supported by pSOSim */ + /* */ + /* include pHILE+ file system calls are not supported */ + /* by pSOSim *so*, for the time being, we make */ + /* use of UNIX file system headers and then */ + /* when we have time, we wrap UNIX file system */ + /* calls w/ pHILE+ wrappers, and modify ACE to */ + /* use the wrappers under pSOSim */ + + /* put includes for necessary UNIX file system calls here */ +# include /**/ +# include /**/ +# include /**/ +# include /**/ + +# define TCP_ +# if ! defined (BUFSIZ) +# define BUFSIZ 1024 +# endif /* ! defined (BUFSIZ) */ + + +# else + +# if defined (ACE_PSOS_CANT_USE_SYS_TYPES) + // these are missing from the pSOS types.h file, and the compiler + // supplied types.h file collides with the pSOS version. +# if !defined (ACE_SHOULD_NOT_DEFINE_SYS_TYPES) + typedef unsigned char u_char; + typedef unsigned short u_short; +# endif /* ACE_SHOULD_NOT_DEFINE_SYS_TYPES */ + typedef unsigned int u_int; +# if !defined (ACE_SHOULD_NOT_DEFINE_SYS_TYPES) + typedef unsigned long u_long; +# endif /* ACE_SHOULD_NOT_DEFINE_SYS_TYPES */ + + // These are defined in types.h included by (among others) pna.h +# if 0 + typedef unsigned char uchar_t; + typedef unsigned short ushort_t; + typedef unsigned int uint_t; + typedef unsigned long ulong_t; +# endif /* 0 */ + typedef char * caddr_t; + +# if defined (ACE_PSOS_DIAB_PPC) + // pid_t is defined in sys/types.h +# if 0 + typedef unsigned long pid_t; +# endif /* 0 */ +# define ACE_INVALID_PID ((pid_t) ~0) +# else /* !defined (ACE_PSOS_DIAB_PPC) */ + typedef long pid_t; +# define ACE_INVALID_PID ((pid_t) -1) +# endif /* defined (ACE_PSOS_DIAB_PPC) */ + +// typedef unsigned char wchar_t; +# endif /* ACE_PSOS_CANT_USE_SYS_TYPES */ + +# include /**/ "ace/sys_conf.h" /* system configuration file */ +# include /**/ /* includes all pSOS headers */ +// #include /**/ /* pSOS system calls */ +# include /**/ /* pNA+ TCP/IP Network Manager calls */ +# include /**/ /* pHILE+ file system calls */ +// #include /**/ /* pREPC+ file system calls */ +# if defined (ACE_PSOS_DIAB_MIPS) +# if defined (ACE_PSOS_USES_DIAB_SYS_CALLS) +# include /**/ /* Diab Data supplied file system calls */ +# else +# include /**/ +# endif /* ACE_PSOS_USES_DIAB_SYS_CALLS */ +# include /**/ /* Diab Data supplied header file */ +# endif /* ACE_PSOS_DIAB_MIPS */ + +// This collides with phile.h +// #include /**/ /* Diab Data supplied header file */ + +// Some versions have missing preprocessor definitions +# if !defined (AF_UNIX) +# define AF_UNIX 0x1 +# endif /* AF_UNIX */ +# define PF_UNIX AF_UNIX +# define PF_INET AF_INET +# if !defined (AF_MAX) +# define AF_MAX AF_INET +# endif /* AF_MAX */ +# if !defined (IFF_LOOPBACK) +# define IFF_LOOPBACK IFF_EXTLOOPBACK +# endif /* IFF_LOOPBACK */ + + typedef long fd_mask; +# define IPPORT_RESERVED 1024 +# define IPPORT_USERRESERVED 5000 + +# if !defined (howmany) +# define howmany(x, y) (((x)+((y)-1))/(y)) +# endif /* howmany */ + + extern "C" + { + typedef void (* ACE_SignalHandler) (void); + typedef void (* ACE_SignalHandlerV) (void); + } + +# if !defined(SIG_DFL) +# define SIG_DFL (ACE_SignalHandler) 0 +# endif /* philabs */ + +# endif /* defined (ACE_PSOSIM) */ + +// Some versions of pSOS do not define error numbers, but newer +// versions do. So, include errno.h and then see which ones are not +// yet defined. +# include /**/ + +# if !defined (EPERM) +# define EPERM 1 /* Not super-user */ +# endif /* EPERM */ +# if !defined (ENOENT) +# define ENOENT 2 /* No such file or directory */ +# endif /* ENOENT */ +# if !defined (ESRCH) +# define ESRCH 3 /* No such process */ +# endif /* ESRCH */ +# if ! defined (EINTR) +# define EINTR 4 /* interrupted system call */ +# endif /* EINTR */ +# if !defined (EBADF) +# define EBADF 9 /* Bad file number */ +# endif /* EBADF */ +# if !defined (EAGAIN) +# define EAGAIN 11 /* Resource temporarily unavailable */ +# endif /* EAGAIN */ +# if !defined (EWOULDBLOCK) +# define EWOULDBLOCK EAGAIN /* Blocking resource request would block */ +# endif /* EWOULDBLOCK */ +# if !defined (ENOMEM) +# define ENOMEM 12 /* Not enough core */ +# endif /* ENOMEM */ +# if !defined (EACCESS) +# define EACCES 13 /* Permission denied */ +# endif /* EACCESS */ +# if !defined (EFAULT) +# define EFAULT 14 /* Bad access */ +# endif /* EFAULT */ +# if !defined (EEXIST) +# define EEXIST 17 /* File exists */ +# endif /* EEXIST */ +# if !defined (ENOSPC) +# define ENOSPC 28 /* No space left on device */ +# endif /* ENOSPC */ +# if !defined (EPIPE) +# define EPIPE 32 /* Broken pipe */ +# endif /* EPIPE */ +# if !defined (ETIME) +# define ETIME 62 /* timer expired */ +# endif /* ETIME */ +# if !defined (ENAMETOOLONG) +# define ENAMETOOLONG 78 /* path name is too long */ +# endif /* ENAMETOOLONG */ +# if !defined (ENOSYS) +# define ENOSYS 89 /* Unsupported file system operation */ +# endif /* ENOSYS */ +# if !defined (EADDRINUSE) +# define EADDRINUSE 125 /* Address already in use */ +# endif /* EADDRINUSE */ +# if !defined (ENETUNREACH) +# define ENETUNREACH 128 /* Network is unreachable */ +# endif /* ENETUNREACH */ +# if !defined (EISCONN) +# define EISCONN 133 /* Socket is already connected */ +# endif /* EISCONN */ +# if !defined (ESHUTDOWN) +# define ESHUTDOWN 143 /* Can't send after socket shutdown */ +# endif /* ESHUTDOWN */ +# if !defined (ECONNREFUSED) +# define ECONNREFUSED 146 /* Connection refused */ +# endif /* ECONNREFUSED */ +# if !defined (EINPROGRESS) +# define EINPROGRESS 150 /* operation now in progress */ +# endif /* EINPROGRESS */ +# if !defined (ERRMAX) +# define ERRMAX 151 /* Last error number */ +# endif /* ERRMAX */ + +# if ! defined (NSIG) +# define NSIG 32 +# endif /* NSIG */ + +# if ! defined (TCP_NODELAY) +# define TCP_NODELAY 1 +# endif /* TCP_NODELAY */ + +// For general purpose portability + +# define ACE_BITS_PER_ULONG (8 * sizeof (u_long)) + +typedef u_long ACE_idtype_t; +typedef u_long ACE_id_t; +# define ACE_SELF (0) +typedef u_long ACE_pri_t; + +// pHILE+ calls the DIR struct XDIR instead +# if !defined (ACE_PSOS_DIAB_PPC) +typedef XDIR ACE_DIR; +# endif /* !defined (ACE_PSOS_DIAB_PPC) */ + +// Use pSOS semaphores, wrapped . . . +typedef struct +{ + u_long sema_; + // Semaphore handle. This is allocated by pSOS. + + char name_[4]; + // Name of the semaphore: really a 32 bit number to pSOS +} ACE_sema_t; + +// Used for dynamic linking. +# if !defined (ACE_DEFAULT_SVC_CONF) +# define ACE_DEFAULT_SVC_CONF "./svc.conf" +# endif /* ACE_DEFAULT_SVC_CONF */ + +# if !defined (ACE_DEFAULT_SEM_KEY) +# define ACE_DEFAULT_SEM_KEY 1234 +# endif /* ACE_DEFAULT_SEM_KEY */ + +# define ACE_STDIN 0 +# define ACE_STDOUT 1 +# define ACE_STDERR 2 + +# define ACE_DIRECTORY_SEPARATOR_STR_A "/" +# define ACE_DIRECTORY_SEPARATOR_CHAR_A '/' +# define ACE_PLATFORM_A "pSOS" +# define ACE_PLATFORM_EXE_SUFFIX_A "" + +# define ACE_DLL_SUFFIX ACE_LIB_TEXT (".so") +# define ACE_DLL_PREFIX ACE_LIB_TEXT ("lib") +# define ACE_LD_SEARCH_PATH ACE_LIB_TEXT ("LD_LIBRARY_PATH") +# define ACE_LD_SEARCH_PATH_SEPARATOR_STR ACE_LIB_TEXT (":") +# define ACE_LOGGER_KEY ACE_LIB_TEXT ("/tmp/server_daemon") + +# define ACE_MAX_DEFAULT_PORT 65535 + +# if ! defined(MAXPATHLEN) +# define MAXPATHLEN 1024 +# endif /* MAXPATHLEN */ + +# if ! defined(MAXNAMLEN) +# define MAXNAMLEN 255 +# endif /* MAXNAMLEN */ + +# if defined (ACE_LACKS_MMAP) +# define PROT_READ 0 +# define PROT_WRITE 0 +# define PROT_EXEC 0 +# define PROT_NONE 0 +# define PROT_RDWR 0 +# define MAP_PRIVATE 0 +# define MAP_SHARED 0 +# define MAP_FIXED 0 +# endif /* ACE_LACKS_MMAP */ + + +typedef int ACE_exitcode; + +typedef ACE_HANDLE ACE_SHLIB_HANDLE; +# define ACE_SHLIB_INVALID_HANDLE ACE_INVALID_HANDLE +# define ACE_DEFAULT_SHLIB_MODE 0 + +# define ACE_INVALID_SEM_KEY -1 + +struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + int h_addrtype; /* host address type */ + int h_length; /* address length */ + char **h_addr_list; /* (first, only) address from name server */ +# define h_addr h_addr_list[0] /* the first address */ +}; + +struct servent { + char *s_name; /* official service name */ + char **s_aliases; /* alias list */ + int s_port; /* port # */ + char *s_proto; /* protocol to use */ +}; + +# define ACE_SEH_TRY if (1) +# define ACE_SEH_EXCEPT(X) while (0) +# define ACE_SEH_FINALLY if (1) + +# if !defined (LPSECURITY_ATTRIBUTES) +# define LPSECURITY_ATTRIBUTES int +# endif /* !defined LPSECURITY_ATTRIBUTES */ +# if !defined (GENERIC_READ) +# define GENERIC_READ 0 +# endif /* !defined GENERIC_READ */ +# if !defined (FILE_SHARE_READ) +# define FILE_SHARE_READ 0 +# endif /* !defined FILE_SHARE_READ */ +# if !defined (OPEN_EXISTING) +# define OPEN_EXISTING 0 +# endif /* !defined OPEN_EXISTING */ +# if !defined (FILE_ATTRIBUTE_NORMAL) +# define FILE_ATTRIBUTE_NORMAL 0 +# endif /* !defined FILE_ATTRIBUTE_NORMAL */ +# if !defined (MAXIMUM_WAIT_OBJECTS) +# define MAXIMUM_WAIT_OBJECTS 0 +# endif /* !defined MAXIMUM_WAIT_OBJECTS */ +# if !defined (FILE_FLAG_OVERLAPPED) +# define FILE_FLAG_OVERLAPPED 0 +# endif /* !defined FILE_FLAG_OVERLAPPED */ +# if !defined (FILE_FLAG_SEQUENTIAL_SCAN) +# define FILE_FLAG_SEQUENTIAL_SCAN 0 +# endif /* !defined FILE_FLAG_SEQUENTIAL_SCAN */ + +struct ACE_OVERLAPPED +{ + u_long Internal; + u_long InternalHigh; + u_long Offset; + u_long OffsetHigh; + ACE_HANDLE hEvent; +}; + +# if !defined (USER_INCLUDE_SYS_TIME_TM) +# if defined (ACE_PSOS_DIAB_PPC) +typedef struct timespec timespec_t; +# else /* ! defined (ACE_PSOS_DIAB_PPC) */ +typedef struct timespec +{ + time_t tv_sec; // Seconds + long tv_nsec; // Nanoseconds +} timespec_t; +# endif /* defined (ACE_PSOS_DIAB_PPC) */ +# endif /* !defined (USER_INCLUDE_SYS_TIME_TM) */ + +#if defined (ACE_PSOS_HAS_TIME) + +// Use pSOS time, wrapped . . . +class ACE_OS_Export ACE_PSOS_Time_t +{ +public: + /// default ctor: date, time, and ticks all zeroed. + ACE_PSOS_Time_t (void); + + /// ctor from a timespec_t + ACE_PSOS_Time_t (const timespec_t& t); + + /// type cast operator (to a timespec_t) + operator timespec_t (); + + /// static member function to get current system time + static u_long get_system_time (ACE_PSOS_Time_t& t); + + /// static member function to set current system time + static u_long set_system_time (const ACE_PSOS_Time_t& t); + +# if defined (ACE_PSOSIM) + /// static member function to initialize system time, using UNIX calls + static u_long init_simulator_time (void); +# endif /* ACE_PSOSIM */ + + /// max number of ticks supported in a single system call + static const u_long max_ticks; +private: + // = Constants for prying info out of the pSOS time encoding. + static const u_long year_mask; + static const u_long month_mask; + static const u_long day_mask; + static const u_long hour_mask; + static const u_long minute_mask; + static const u_long second_mask; + static const int year_shift; + static const int month_shift; + static const int hour_shift; + static const int minute_shift; + static const int year_origin; + static const int month_origin; + + // error codes + static const u_long err_notime; // system time not set + static const u_long err_illdate; // date out of range + static const u_long err_illtime; // time out of range + static const u_long err_illticks; // ticks out of range + + /// date : year in bits 31-16, month in bits 15-8, day in bits 7-0 + u_long date_; + + /// time : hour in bits 31-16, minutes in bits 15-8, seconds in bits 7-0 + u_long time_; + + /// ticks: number of system clock ticks (KC_TICKS2SEC-1 max) + u_long ticks_; +} ; +#endif /* ACE_PSOS_HAS_TIME */ + +# endif /* defined (ACE_PSOS) */ + +# if defined (ACE_HAS_CHARPTR_SPRINTF) +# define ACE_SPRINTF_ADAPTER(X) ::strlen (X) +# else +# define ACE_SPRINTF_ADAPTER(X) X +# endif /* ACE_HAS_CHARPTR_SPRINTF */ + +// Default address for shared memory mapped files and SYSV shared memory +// (defaults to 64 M). +# if !defined (ACE_DEFAULT_BASE_ADDR) +# define ACE_DEFAULT_BASE_ADDR ((char *) (64 * 1024 * 1024)) +# endif /* ACE_DEFAULT_BASE_ADDR */ + + +// This fudge factor can be overriden for timers that need it, such as on +// Solaris, by defining the ACE_TIMER_SKEW symbol in the appropriate config +// header. +#if !defined (ACE_TIMER_SKEW) +# define ACE_TIMER_SKEW 0 +#endif /* ACE_TIMER_SKEW */ + +// This needs to go here *first* to avoid problems with AIX. +# if defined (ACE_HAS_PTHREADS) +extern "C" { +# define ACE_DONT_INCLUDE_ACE_SIGNAL_H +# include /**/ +# undef ACE_DONT_INCLUDE_ACE_SIGNAL_H +# include /**/ +# if defined (DIGITAL_UNIX) +# define pthread_self __pthread_self +extern "C" pthread_t pthread_self (void); +# endif /* DIGITAL_UNIX */ +} +# if defined (HPUX_10) +// HP-UX 10 needs to see cma_sigwait, and since _CMA_NOWRAPPERS_ is defined, +// this header does not get included from pthreads.h. +# include /**/ +# endif /* HPUX_10 */ +# endif /* ACE_HAS_PTHREADS */ + +// There are a lot of threads-related macro definitions in the config files. +// They came in at different times and from different places and platform +// requirements as threads evolved. They are probably not all needed - some +// overlap or are otherwise confused. This is an attempt to start +// straightening them out. +# if defined (ACE_HAS_PTHREADS_STD) /* POSIX.1c threads (pthreads) */ + // ... and 2-parameter asctime_r and ctime_r +# if !defined (ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R) && \ + !defined (ACE_HAS_STHREADS) +# define ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R +# endif +# endif /* ACE_HAS_PTHREADS_STD */ + + + +// By default we perform no tracing on the OS layer, otherwise the +// coupling between the OS layer and Log_Msg is too tight. But the +// application can override the default if they wish to. +# if !defined(ACE_OS_TRACE) +# define ACE_OS_TRACE(X) +# endif /* ACE_OS_TRACE */ + +# if !defined (ACE_HAS_WINCE) && !defined (ACE_PSOS_DIAB_MIPS) +# include /**/ +# if defined (__Lynx__) +# include /**/ +# include /**/ +# endif /* __Lynx__ */ +# endif /* ACE_HAS_WINCE ACE_PSOS_DIAB_MIPS */ + +# if defined (ACE_LACKS_SYSTIME_H) +// Some platforms may need to include this, but I suspect that most +// will get it from +# if defined (VXWORKS) +# include /**/ +# else +# include /**/ +# endif /* VXWORKS */ +# endif /* ACE_LACKS_SYSTIME_H */ + +# if defined (ACE_USES_STD_NAMESPACE_FOR_STDC_LIB) && \ + (ACE_USES_STD_NAMESPACE_FOR_STDC_LIB != 0) +using std::time_t; +using std::tm; +# if defined (ACE_WIN32) +using std::_timezone; +# else +using std::timezone; +# endif +using std::difftime; +# endif /* ACE_USES_STD_NAMESPACE_FOR_STDC_LIB */ + +# if !defined (ACE_HAS_POSIX_TIME) && !defined (ACE_PSOS) +// Definition per POSIX. +typedef struct timespec +{ + time_t tv_sec; // Seconds + long tv_nsec; // Nanoseconds +} timespec_t; +# elif defined (ACE_HAS_BROKEN_POSIX_TIME) +// OSF/1 defines struct timespec in - Tom Marrs +# include /**/ +# endif /* !ACE_HAS_POSIX_TIME */ + +# if defined(ACE_LACKS_TIMESPEC_T) +typedef struct timespec timespec_t; +# endif /* ACE_LACKS_TIMESPEC_T */ + +# if !defined (ACE_HAS_CLOCK_GETTIME) && !(defined (_CLOCKID_T_) || defined (_CLOCKID_T)) +typedef int clockid_t; +# if !defined (CLOCK_REALTIME) +# define CLOCK_REALTIME 0 +# endif /* CLOCK_REALTIME */ +# endif /* ! ACE_HAS_CLOCK_GETTIME && ! _CLOCKID_T_ */ + +// ------------------------------------------------------------------- +// These forward declarations are only used to circumvent a bug in +// MSVC 6.0 compiler. They shouldn't cause any problem for other +// compilers and they can be removed once MS release a SP that contains +// the fix. +class ACE_Time_Value; +ACE_OS_Export ACE_Time_Value operator + (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2); + +ACE_OS_Export ACE_Time_Value operator - (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2); + +// This forward declaration is needed by the set() and FILETIME() functions +#if defined (ACE_LACKS_LONGLONG_T) + class ACE_Export ACE_U_LongLong; +#endif //ghs +// ------------------------------------------------------------------- + +/** + * @class ACE_Time_Value + * + * @brief Operations on "timeval" structures, which express time in and . + * + * This class centralizes all the time related processing in + * ACE. These timers are typically used in conjunction with OS + * mechanisms like or other calls that may have + * *their own* implementation-specific maximum time representations. + * Its primary use is in time computations such as those used by the + * dynamic subpriority strategies in the + * class. + */ + static const ACE_Time_Value max_time; + + // = Initialization methods. + + /// Default Constructor. + ACE_Time_Value (void); + + /// Constructor. + ACE_Time_Value (long sec, long usec = 0); + + // = Methods for converting to/from various time formats. + /// Construct the from a . + ACE_Time_Value (const struct timeval &t); + + /// Initializes the object from a . + ACE_Time_Value (const timespec_t &t); + + /// Copy constructor. + ACE_Time_Value (const ACE_Time_Value &tv); + +# if defined (ACE_WIN32) + /// Initializes the ACE_Time_Value object from a Win32 FILETIME + ACE_Time_Value (const FILETIME &ft); +# endif /* ACE_WIN32 */ + + /// Construct a from two s. + void set (long sec, long usec); + + /// Construct a from a , which is assumed to be + /// in second format, with any remainder treated as microseconds. + void set (double d); + + /// Construct a from a . + void set (const timeval &t); + + /// Initializes the object from a . + void set (const timespec_t &t); + +# if defined (ACE_WIN32) + /// Initializes the object from a . + void set (const FILETIME &ft); +# endif /* ACE_WIN32 */ + + /// Converts from format into milli-seconds format. + long msec (void) const; + + /// Converts from milli-seconds format into format. + void msec (long); + + /// Returns the value of the object as a . + operator timespec_t () const; + + /// Returns the value of the object as a . + operator timeval () const; + + /// Returns a pointer to the object as a . + operator const timeval *() const; + +# if defined (ACE_WIN32) + /// Returns the value of the object as a Win32 FILETIME. + operator FILETIME () const; +# endif /* ACE_WIN32 */ + + // = The following are accessor/mutator methods. + + /// Get seconds. + long sec (void) const; + + /// Set seconds. + void sec (long sec); + + /// Get microseconds. + long usec (void) const; + + /// Set microseconds. + void usec (long usec); + + // = The following arithmetic methods operate on s. + + /// Add to this. + ACE_Time_Value &operator += (const ACE_Time_Value &tv); + + /// Subtract to this. + ACE_Time_Value &operator -= (const ACE_Time_Value &tv); + + /// Multiply the time value by the factor, which must be >= 0. + ACE_Time_Value &operator *= (double d); + + /// Increment microseconds (the only reason this is here is + /// to allow the use of ACE_Atomic_Op with ACE_Time_Value). + ACE_Time_Value operator++ (int); // Postfix advance + ACE_Time_Value &operator++ (void); // Prefix advance + + /// Decrement microseconds (the only reason this is here is + /// to allow the use of ACE_Atomic_Op with ACE_Time_Value). + ACE_Time_Value operator-- (int); // Postfix dec + ACE_Time_Value &operator-- (void); // Prefix dec + + /// Adds two ACE_Time_Value objects together, returns the sum. + friend ACE_OS_Export ACE_Time_Value operator + (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2); + + /// Subtracts two ACE_Time_Value objects, returns the difference. + friend ACE_OS_Export ACE_Time_Value operator - (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2); + + /// True if tv1 < tv2. + friend ACE_OS_Export int operator < (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2); + + /// True if tv1 > tv2. + friend ACE_OS_Export int operator > (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2); + + /// True if tv1 <= tv2. + friend ACE_OS_Export int operator <= (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2); + + /// True if tv1 >= tv2. + friend ACE_OS_Export int operator >= (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2); + + /// True if tv1 == tv2. + friend ACE_OS_Export int operator == (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2); + + /// True if tv1 != tv2. + friend ACE_OS_Export int operator != (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2); + + /// Dump the state of an object. + void dump (void) const; + +# if defined (ACE_WIN32) + /// Const time difference between FILETIME and POSIX time. +# if defined (ACE_LACKS_LONGLONG_T) + static const ACE_U_LongLong FILETIME_to_timval_skew; +# else + static const DWORDLONG FILETIME_to_timval_skew; +# endif // ACE_LACKS_LONGLONG_T +# endif /* ACE_WIN32 */ + +private: + /// Put the timevalue into a canonical form. + void normalize (void); + + /// Store the values as a . + timeval tv_; +}; + +/** + * @class ACE_Countdown_Time + * + * @brief Keeps track of the amount of elapsed time. + * + * This class has a side-effect on the -- every + * time the method is called the is + * updated. + */ +class ACE_OS_Export ACE_Countdown_Time +{ +public: + // = Initialization and termination methods. + /// Cache the and call . + ACE_Countdown_Time (ACE_Time_Value *max_wait_time); + + /// Call . + ~ACE_Countdown_Time (void); + + /// Cache the current time and enter a start state. + int start (void); + + /// Subtract the elapsed time from max_wait_time_ and enter a stopped + /// state. + int stop (void); + + /// Calls stop and then start. max_wait_time_ is modified by the + /// call to stop. + int update (void); + +private: + /// Maximum time we were willing to wait. + ACE_Time_Value *max_wait_time_; + + /// Beginning of the start time. + ACE_Time_Value start_time_; + + /// Keeps track of whether we've already been stopped. + int stopped_; +}; + +# if defined (ACE_HAS_USING_KEYWORD) +# define ACE_USING using +# else +# define ACE_USING +# endif /* ACE_HAS_USING_KEYWORD */ + +# if defined (ACE_HAS_TYPENAME_KEYWORD) +# define ACE_TYPENAME typename +# else +# define ACE_TYPENAME +# endif /* ACE_HAS_TYPENAME_KEYWORD */ + +# if defined (ACE_HAS_STD_TEMPLATE_SPECIALIZATION) +# define ACE_TEMPLATE_SPECIALIZATION template<> +# else +# define ACE_TEMPLATE_SPECIALIZATION +# endif /* ACE_HAS_STD_TEMPLATE_SPECIALIZATION */ + +# if defined (ACE_HAS_STD_TEMPLATE_METHOD_SPECIALIZATION) +# define ACE_TEMPLATE_METHOD_SPECIALIZATION template<> +# else +# define ACE_TEMPLATE_METHOD_SPECIALIZATION +# endif /* ACE_HAS_STD_TEMPLATE_SPECIALIZATION */ + +// The following is necessary since many C++ compilers don't support +// typedef'd types inside of classes used as formal template +// arguments... ;-(. Luckily, using the C++ preprocessor I can hide +// most of this nastiness! + +# if defined (ACE_HAS_TEMPLATE_TYPEDEFS) + +// Handle ACE_Message_Queue. +# define ACE_SYNCH_DECL class _ACE_SYNCH +# define ACE_SYNCH_USE _ACE_SYNCH +# define ACE_SYNCH_MUTEX_T ACE_TYPENAME _ACE_SYNCH::MUTEX +# define ACE_SYNCH_CONDITION_T ACE_TYPENAME _ACE_SYNCH::CONDITION +# define ACE_SYNCH_SEMAPHORE_T ACE_TYPENAME _ACE_SYNCH::SEMAPHORE + +// Handle ACE_Malloc* +# define ACE_MEM_POOL_1 class _ACE_MEM_POOL +# define ACE_MEM_POOL_2 _ACE_MEM_POOL +# define ACE_MEM_POOL _ACE_MEM_POOL +# define ACE_MEM_POOL_OPTIONS ACE_TYPENAME _ACE_MEM_POOL::OPTIONS + +// Handle ACE_Svc_Handler +# define ACE_PEER_STREAM_1 class _ACE_PEER_STREAM +# define ACE_PEER_STREAM_2 _ACE_PEER_STREAM +# define ACE_PEER_STREAM _ACE_PEER_STREAM +# define ACE_PEER_STREAM_ADDR ACE_TYPENAME _ACE_PEER_STREAM::PEER_ADDR + +// Handle ACE_Acceptor +# define ACE_PEER_ACCEPTOR_1 class _ACE_PEER_ACCEPTOR +# define ACE_PEER_ACCEPTOR_2 _ACE_PEER_ACCEPTOR +# define ACE_PEER_ACCEPTOR _ACE_PEER_ACCEPTOR +# define ACE_PEER_ACCEPTOR_ADDR ACE_TYPENAME _ACE_PEER_ACCEPTOR::PEER_ADDR + +// Handle ACE_Connector +# define ACE_PEER_CONNECTOR_1 class _ACE_PEER_CONNECTOR +# define ACE_PEER_CONNECTOR_2 _ACE_PEER_CONNECTOR +# define ACE_PEER_CONNECTOR _ACE_PEER_CONNECTOR +# define ACE_PEER_CONNECTOR_ADDR ACE_TYPENAME _ACE_PEER_CONNECTOR::PEER_ADDR +# if !defined(ACE_HAS_TYPENAME_KEYWORD) +# define ACE_PEER_CONNECTOR_ADDR_ANY ACE_PEER_CONNECTOR_ADDR::sap_any +# else + // + // If the compiler supports 'typename' we cannot use + // + // PEER_CONNECTOR::PEER_ADDR::sap_any + // + // because PEER_CONNECTOR::PEER_ADDR is not considered a type. But: + // + // typename PEER_CONNECTOR::PEER_ADDR::sap_any + // + // will not work either, because now we are declaring sap_any a + // type, further: + // + // (typename PEER_CONNECTOR::PEER_ADDR)::sap_any + // + // is considered a casting expression. All I can think of is using a + // typedef, I tried PEER_ADDR but that was a source of trouble on + // some platforms. I will try: + // +# define ACE_PEER_CONNECTOR_ADDR_ANY ACE_PEER_ADDR_TYPEDEF::sap_any +# endif /* ACE_HAS_TYPENAME_KEYWORD */ + +// Handle ACE_SOCK_* +# define ACE_SOCK_ACCEPTOR ACE_SOCK_Acceptor +# define ACE_SOCK_CONNECTOR ACE_SOCK_Connector +# define ACE_SOCK_STREAM ACE_SOCK_Stream + +// Handle ACE_MEM_* +# define ACE_MEM_ACCEPTOR ACE_MEM_Acceptor +# define ACE_MEM_CONNECTOR ACE_MEM_Connector +# define ACE_MEM_STREAM ACE_MEM_Stream + +// Handle ACE_LSOCK_* +# define ACE_LSOCK_ACCEPTOR ACE_LSOCK_Acceptor +# define ACE_LSOCK_CONNECTOR ACE_LSOCK_Connector +# define ACE_LSOCK_STREAM ACE_LSOCK_Stream + +// Handle ACE_TLI_* +# define ACE_TLI_ACCEPTOR ACE_TLI_Acceptor +# define ACE_TLI_CONNECTOR ACE_TLI_Connector +# define ACE_TLI_STREAM ACE_TLI_Stream + +// Handle ACE_SPIPE_* +# define ACE_SPIPE_ACCEPTOR ACE_SPIPE_Acceptor +# define ACE_SPIPE_CONNECTOR ACE_SPIPE_Connector +# define ACE_SPIPE_STREAM ACE_SPIPE_Stream + +// Handle ACE_UPIPE_* +# define ACE_UPIPE_ACCEPTOR ACE_UPIPE_Acceptor +# define ACE_UPIPE_CONNECTOR ACE_UPIPE_Connector +# define ACE_UPIPE_STREAM ACE_UPIPE_Stream + +// Handle ACE_FILE_* +# define ACE_FILE_CONNECTOR ACE_FILE_Connector +# define ACE_FILE_STREAM ACE_FILE_IO + +// Handle ACE_*_Memory_Pool. +# define ACE_MMAP_MEMORY_POOL ACE_MMAP_Memory_Pool +# define ACE_LITE_MMAP_MEMORY_POOL ACE_Lite_MMAP_Memory_Pool +# define ACE_SBRK_MEMORY_POOL ACE_Sbrk_Memory_Pool +# define ACE_SHARED_MEMORY_POOL ACE_Shared_Memory_Pool +# define ACE_LOCAL_MEMORY_POOL ACE_Local_Memory_Pool +# define ACE_PAGEFILE_MEMORY_POOL ACE_Pagefile_Memory_Pool + +# else /* TEMPLATES are broken in some form or another (i.e., most C++ compilers) */ + +// Handle ACE_Message_Queue. +# if defined (ACE_HAS_OPTIMIZED_MESSAGE_QUEUE) +# define ACE_SYNCH_DECL class _ACE_SYNCH_MUTEX_T, class _ACE_SYNCH_CONDITION_T, class _ACE_SYNCH_SEMAPHORE_T +# define ACE_SYNCH_USE _ACE_SYNCH_MUTEX_T, _ACE_SYNCH_CONDITION_T, _ACE_SYNCH_SEMAPHORE_T +# else +# define ACE_SYNCH_DECL class _ACE_SYNCH_MUTEX_T, class _ACE_SYNCH_CONDITION_T +# define ACE_SYNCH_USE _ACE_SYNCH_MUTEX_T, _ACE_SYNCH_CONDITION_T +# endif /* ACE_HAS_OPTIMIZED_MESSAGE_QUEUE */ +# define ACE_SYNCH_MUTEX_T _ACE_SYNCH_MUTEX_T +# define ACE_SYNCH_CONDITION_T _ACE_SYNCH_CONDITION_T +# define ACE_SYNCH_SEMAPHORE_T _ACE_SYNCH_SEMAPHORE_T + +// Handle ACE_Malloc* +# define ACE_MEM_POOL_1 class _ACE_MEM_POOL, class _ACE_MEM_POOL_OPTIONS +# define ACE_MEM_POOL_2 _ACE_MEM_POOL, _ACE_MEM_POOL_OPTIONS +# define ACE_MEM_POOL _ACE_MEM_POOL +# define ACE_MEM_POOL_OPTIONS _ACE_MEM_POOL_OPTIONS + +// Handle ACE_Svc_Handler +# define ACE_PEER_STREAM_1 class _ACE_PEER_STREAM, class _ACE_PEER_ADDR +# define ACE_PEER_STREAM_2 _ACE_PEER_STREAM, _ACE_PEER_ADDR +# define ACE_PEER_STREAM _ACE_PEER_STREAM +# define ACE_PEER_STREAM_ADDR _ACE_PEER_ADDR + +// Handle ACE_Acceptor +# define ACE_PEER_ACCEPTOR_1 class _ACE_PEER_ACCEPTOR, class _ACE_PEER_ADDR +# define ACE_PEER_ACCEPTOR_2 _ACE_PEER_ACCEPTOR, _ACE_PEER_ADDR +# define ACE_PEER_ACCEPTOR _ACE_PEER_ACCEPTOR +# define ACE_PEER_ACCEPTOR_ADDR _ACE_PEER_ADDR + +// Handle ACE_Connector +# define ACE_PEER_CONNECTOR_1 class _ACE_PEER_CONNECTOR, class _ACE_PEER_ADDR +# define ACE_PEER_CONNECTOR_2 _ACE_PEER_CONNECTOR, _ACE_PEER_ADDR +# define ACE_PEER_CONNECTOR _ACE_PEER_CONNECTOR +# define ACE_PEER_CONNECTOR_ADDR _ACE_PEER_ADDR +# define ACE_PEER_CONNECTOR_ADDR_ANY ACE_PEER_CONNECTOR_ADDR::sap_any + +// Handle ACE_SOCK_* +# define ACE_SOCK_ACCEPTOR ACE_SOCK_Acceptor, ACE_INET_Addr +# define ACE_SOCK_CONNECTOR ACE_SOCK_Connector, ACE_INET_Addr +# define ACE_SOCK_STREAM ACE_SOCK_Stream, ACE_INET_Addr + +// Handle ACE_MEM_* +# define ACE_MEM_ACCEPTOR ACE_MEM_Acceptor, ACE_MEM_Addr +# define ACE_MEM_CONNECTOR ACE_MEM_Connector, ACE_INET_Addr +# define ACE_MEM_STREAM ACE_MEM_Stream, ACE_INET_Addr + +// Handle ACE_LSOCK_* +# define ACE_LSOCK_ACCEPTOR ACE_LSOCK_Acceptor, ACE_UNIX_Addr +# define ACE_LSOCK_CONNECTOR ACE_LSOCK_Connector, ACE_UNIX_Addr +# define ACE_LSOCK_STREAM ACE_LSOCK_Stream, ACE_UNIX_Addr + +// Handle ACE_TLI_* +# define ACE_TLI_ACCEPTOR ACE_TLI_Acceptor, ACE_INET_Addr +# define ACE_TLI_CONNECTOR ACE_TLI_Connector, ACE_INET_Addr +# define ACE_TLI_STREAM ACE_TLI_Stream, ACE_INET_Addr + +// Handle ACE_SPIPE_* +# define ACE_SPIPE_ACCEPTOR ACE_SPIPE_Acceptor, ACE_SPIPE_Addr +# define ACE_SPIPE_CONNECTOR ACE_SPIPE_Connector, ACE_SPIPE_Addr +# define ACE_SPIPE_STREAM ACE_SPIPE_Stream, ACE_SPIPE_Addr + +// Handle ACE_UPIPE_* +# define ACE_UPIPE_ACCEPTOR ACE_UPIPE_Acceptor, ACE_SPIPE_Addr +# define ACE_UPIPE_CONNECTOR ACE_UPIPE_Connector, ACE_SPIPE_Addr +# define ACE_UPIPE_STREAM ACE_UPIPE_Stream, ACE_SPIPE_Addr + +// Handle ACE_FILE_* +# define ACE_FILE_CONNECTOR ACE_FILE_Connector, ACE_FILE_Addr +# define ACE_FILE_STREAM ACE_FILE_IO, ACE_FILE_Addr + +// Handle ACE_*_Memory_Pool. +# define ACE_MMAP_MEMORY_POOL ACE_MMAP_Memory_Pool, ACE_MMAP_Memory_Pool_Options +# define ACE_LITE_MMAP_MEMORY_POOL ACE_Lite_MMAP_Memory_Pool, ACE_MMAP_Memory_Pool_Options +# define ACE_SBRK_MEMORY_POOL ACE_Sbrk_Memory_Pool, ACE_Sbrk_Memory_Pool_Options +# define ACE_SHARED_MEMORY_POOL ACE_Shared_Memory_Pool, ACE_Shared_Memory_Pool_Options +# define ACE_LOCAL_MEMORY_POOL ACE_Local_Memory_Pool, ACE_Local_Memory_Pool_Options +# define ACE_PAGEFILE_MEMORY_POOL ACE_Pagefile_Memory_Pool, ACE_Pagefile_Memory_Pool_Options +# endif /* ACE_HAS_TEMPLATE_TYPEDEFS */ + +// These two are only for backward compatibility. You should avoid +// using them if not necessary. +# define ACE_SYNCH_1 ACE_SYNCH_DECL +# define ACE_SYNCH_2 ACE_SYNCH_USE + +// For Win32 compatibility... +# if !defined (ACE_WSOCK_VERSION) +# define ACE_WSOCK_VERSION 0, 0 +# endif /* ACE_WSOCK_VERSION */ + +# if defined (ACE_HAS_BROKEN_CTIME) +# undef ctime +# endif /* ACE_HAS_BROKEN_CTIME */ + +/// Service Objects, i.e., objects dynamically loaded via the service +/// configurator, must provide a destructor function with the +/// following prototype to perform object cleanup. +extern "C" { +typedef void (*ACE_Service_Object_Exterminator)(void *); +} + +/** @name Service Configurator macros + * + * The following macros are used to define helper objects used in + * ACE's Service Configurator. This is an implementation of the + * Service Configurator pattern: + * + * http://www.cs.wustl.edu/~schmidt/PDF/SvcConf.pdf + * + * The intent of this pattern is to allow developers to dynamically + * load and configure services into a system. With a little help from + * this macros statically linked services can also be dynamically + * configured. + * + * More details about this component are available in the documentation + * of the ACE_Service_Configurator class and also + * ACE_Dynamic_Service. + * + * Notice that in all the macros the SERVICE_CLASS parameter must be + * the name of a class derived from ACE_Service_Object. + */ +//@{ +/// Declare a the data structure required to register a statically +/// linked service into the service configurator. +/** + * The macro should be used in the header file where the service is + * declared, its only argument is usually the name of the class that + * implements the service. + * + * @param SERVICE_CLASS The name of the class implementing the + * service. + */ +# define ACE_STATIC_SVC_DECLARE(SERVICE_CLASS) \ +extern ACE_Static_Svc_Descriptor ace_svc_desc_##SERVICE_CLASS ; + +/// As ACE_STATIC_SVC_DECLARE, but using an export macro for NT +/// compilers. +/** + * NT compilers require the use of explicit directives to export and + * import symbols from a DLL. If you need to define a service in a + * dynamic library you should use this version instead. + * Normally ACE uses a macro to inject the correct export/import + * directives on NT. Naturally it also the macro expands to a blank + * on platforms that do not require such directives. + * The first argument (EXPORT_NAME) is the prefix for this export + * macro, the full name is formed by appending _Export. + * ACE provides tools to generate header files that define the macro + * correctly on all platforms, please see + * $ACE_ROOT/bin/generate_export_file.pl + * + * @param EXPORT_NAME The export macro name prefix. + * @param SERVICE_CLASS The name of the class implementing the service. + */ +#define ACE_STATIC_SVC_DECLARE_EXPORT(EXPORT_NAME,SERVICE_CLASS) \ +extern EXPORT_NAME##_Export ACE_Static_Svc_Descriptor ace_svc_desc_##SERVICE_CLASS; + +/// Define the data structure used to register a statically linked +/// service into the Service Configurator. +/** + * The service configurator requires several arguments to build and + * control an statically linked service, including its name, the + * factory function used to construct the service, and some flags. + * All those parameters are configured in a single structure, an + * instance of this structure is statically initialized using the + * following macro. + * + * @param SERVICE_CLASS The name of the class that implements the + * service, must derive from ACE_Service_Configurator. + * @param NAME The name for this service, this name is used by the + * service configurator to match configuration options provided in + * the svc.conf file. + * @param TYPE The type of object. Objects can be streams or service + * objects. Please read the ACE_Service_Configurator and ASX + * documentation for more details. + * @param FN The name of the factory function, usually the + * ACE_SVC_NAME macro can be used to generate the name. The + * factory function is often defined using ACE_FACTORY_DECLARE and + * ACE_FACTORY_DEFINE. + * @param FLAGS Flags to control the ownership and lifecycle of the + * object. Please read the ACE_Service_Configurator documentation + * for more details. + * @param ACTIVE If not zero then a thread will be dedicate to the + * service. Please read the ACE_Service_Configurator documentation + * for more details. + */ +#define ACE_STATIC_SVC_DEFINE(SERVICE_CLASS, NAME, TYPE, FN, FLAGS, ACTIVE) \ +ACE_Static_Svc_Descriptor ace_svc_desc_##SERVICE_CLASS = { NAME, TYPE, FN, FLAGS, ACTIVE }; + +/// Automatically register a service with the service configurator +/** + * In some applications the services must be automatically registered + * with the service configurator, before main() starts. + * The ACE_STATIC_SVC_REQUIRE macro defines a class whose constructor + * register the service, it also defines a static instance of that + * class to ensure that the service is registered before main. + * + * On platforms that lack adequate support for static C++ objects the + * macro ACE_STATIC_SVC_REGISTER can be used to explicitly register + * the service. + * + * @todo One class per-Service_Object seems wasteful. It should be + * possible to define a single class and re-use it for all the + * service objects, just by passing the Service_Descriptor as an + * argument to the constructor. + */ +#if defined(ACE_LACKS_STATIC_CONSTRUCTORS) +# define ACE_STATIC_SVC_REQUIRE(SERVICE_CLASS)\ +class ACE_Static_Svc_##SERVICE_CLASS {\ +public:\ + ACE_Static_Svc_##SERVICE_CLASS() { \ + ACE_Service_Config::static_svcs ()->insert (\ + &ace_svc_desc_##SERVICE_CLASS); \ + } \ +}; +#define ACE_STATIC_SVC_REGISTER(SERVICE_CLASS)\ +ACE_Static_Svc_##SERVICE_CLASS ace_static_svc_##SERVICE_CLASS + +#else /* !ACE_LACKS_STATIC_CONSTRUCTORS */ + +# define ACE_STATIC_SVC_REQUIRE(SERVICE_CLASS)\ +class ACE_Static_Svc_##SERVICE_CLASS {\ +public:\ + ACE_Static_Svc_##SERVICE_CLASS() { \ + ACE_Service_Config::static_svcs ()->insert (\ + &ace_svc_desc_##SERVICE_CLASS); \ + } \ +};\ +static ACE_Static_Svc_##SERVICE_CLASS ace_static_svc_##SERVICE_CLASS; +#define ACE_STATIC_SVC_REGISTER(SERVICE_CLASS) do {} while (0) + +#endif /* !ACE_LACKS_STATIC_CONSTRUCTORS */ + +/// Declare the factory method used to create dynamically loadable +/// services. +/** + * Once the service implementation is dynamically loaded the Service + * Configurator uses a factory method to create the object. + * This macro declares such a factory function with the proper + * interface and export macros. + * Normally used in the header file that declares the service + * implementation. + * + * @param CLS must match the prefix of the export macro used for this + * service. + * @param SERVICE_CLASS must match the name of the class that + * implements the service. + * + */ +#define ACE_FACTORY_DECLARE(CLS,SERVICE_CLASS) \ +extern "C" CLS##_Export ACE_Service_Object *\ +_make_##SERVICE_CLASS (ACE_Service_Object_Exterminator *); + +/// Define the factory method (and destructor) for a dynamically +/// loadable service. +/** + * Use with arguments matching ACE_FACTORY_DECLARE. + * Normally used in the .cpp file that defines the service + * implementation. + * + * This macro defines both the factory method and the function used to + * cleanup the service object. + */ +# define ACE_FACTORY_DEFINE(CLS,SERVICE_CLASS) \ +extern "C" void _gobble_##SERVICE_CLASS (void *p) { \ + ACE_Service_Object *_p = ACE_reinterpret_cast (ACE_Service_Object *, p); \ + ACE_ASSERT (_p != 0); \ + delete _p; } \ +extern "C" ACE_Service_Object *\ +_make_##SERVICE_CLASS (ACE_Service_Object_Exterminator *gobbler) \ +{ \ + ACE_TRACE (#SERVICE_CLASS); \ + if (gobbler != 0) \ + *gobbler = (ACE_Service_Object_Exterminator) _gobble_##SERVICE_CLASS; \ + return new SERVICE_CLASS; \ +} + +/// The canonical name for a service factory method +#define ACE_SVC_NAME(SERVICE_CLASS) _make_##SERVICE_CLASS + +/// The canonical way to invoke (i.e. construct) a service factory +/// method. +#define ACE_SVC_INVOKE(SERVICE_CLASS) _make_##SERVICE_CLASS (0) + +//@} + +/** @name Helper macros for services defined in the netsvcs library. + * + * The ACE services defined in netsvcs use this helper macros for + * simplicity. + * + */ +//@{ +# define ACE_SVC_FACTORY_DECLARE(X) ACE_FACTORY_DECLARE (ACE_Svc, X) +# define ACE_SVC_FACTORY_DEFINE(X) ACE_FACTORY_DEFINE (ACE_Svc, X) +//@} + +# if defined (ACE_HAS_THREADS) && (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION)) +# define ACE_TSS_TYPE(T) ACE_TSS< T > +# if defined (ACE_HAS_BROKEN_CONVERSIONS) +# define ACE_TSS_GET(I, T) (*(I)) +# else +# define ACE_TSS_GET(I, T) ((I)->operator T * ()) +# endif /* ACE_HAS_BROKEN_CONVERSIONS */ +# else +# define ACE_TSS_TYPE(T) T +# define ACE_TSS_GET(I, T) (I) +# endif /* ACE_HAS_THREADS && (ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATIOND) */ + +# if defined (ACE_LACKS_MODE_MASKS) +// MODE MASKS + +// the following macros are for POSIX conformance. + +# if !defined (ACE_HAS_USER_MODE_MASKS) +# define S_IRWXU 00700 /* read, write, execute: owner. */ +# define S_IRUSR 00400 /* read permission: owner. */ +# define S_IWUSR 00200 /* write permission: owner. */ +# define S_IXUSR 00100 /* execute permission: owner. */ +# endif /* ACE_HAS_USER_MODE_MASKS */ +# define S_IRWXG 00070 /* read, write, execute: group. */ +# define S_IRGRP 00040 /* read permission: group. */ +# define S_IWGRP 00020 /* write permission: group. */ +# define S_IXGRP 00010 /* execute permission: group. */ +# define S_IRWXO 00007 /* read, write, execute: other. */ +# define S_IROTH 00004 /* read permission: other. */ +# define S_IWOTH 00002 /* write permission: other. */ +# define S_IXOTH 00001 /* execute permission: other. */ + +# endif /* ACE_LACKS_MODE_MASKS */ + +# if defined (ACE_LACKS_SEMBUF_T) +struct sembuf +{ + unsigned short sem_num; // semaphore # + short sem_op; // semaphore operation + short sem_flg; // operation flags +}; +# endif /* ACE_LACKS_SEMBUF_T */ + +# if defined (ACE_LACKS_MSGBUF_T) +struct msgbuf {}; +# endif /* ACE_LACKS_MSGBUF_T */ + +# if defined (ACE_LACKS_STRRECVFD) +struct strrecvfd {}; +# endif /* ACE_LACKS_STRRECVFD */ + +# if defined (ACE_HAS_PROC_FS) +# include /**/ +# endif /* ACE_HAS_PROC_FS */ + +# if defined(__rtems__) +struct iovec { + char *iov_base; // Base address. + size_t iov_len; // Length. +}; +# endif + +# if defined (ACE_HAS_BROKEN_WRITEV) +typedef struct iovec ACE_WRITEV_TYPE; +# else +typedef const struct iovec ACE_WRITEV_TYPE; +# endif /* ACE_HAS_BROKEN_WRITEV */ + +# if defined (ACE_HAS_BROKEN_READV) +typedef const struct iovec ACE_READV_TYPE; +# else +typedef struct iovec ACE_READV_TYPE; +# endif /* ACE_HAS_BROKEN_READV */ + +# if defined (ACE_HAS_BROKEN_SETRLIMIT) +typedef struct rlimit ACE_SETRLIMIT_TYPE; +# else +typedef const struct rlimit ACE_SETRLIMIT_TYPE; +# endif /* ACE_HAS_BROKEN_SETRLIMIT */ + +# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) +# define ACE_MT(X) X +# if !defined (_REENTRANT) +# define _REENTRANT +# endif /* _REENTRANT */ +# else +# define ACE_MT(X) +# endif /* ACE_MT_SAFE */ + +# if !defined (ACE_DEFAULT_THREAD_PRIORITY) +# define ACE_DEFAULT_THREAD_PRIORITY (-0x7fffffffL - 1L) +# endif /* ACE_DEFAULT_THREAD_PRIORITY */ + +// Convenient macro for testing for deadlock, as well as for detecting +// when mutexes fail. +#define ACE_GUARD_ACTION(MUTEX, OBJ, LOCK, ACTION, REACTION) \ + ACE_Guard< MUTEX > OBJ (LOCK); \ + if (OBJ.locked () != 0) { ACTION; } \ + else { REACTION; } +#define ACE_GUARD_REACTION(MUTEX, OBJ, LOCK, REACTION) \ + ACE_GUARD_ACTION(MUTEX, OBJ, LOCK, ;, REACTION) +#define ACE_GUARD(MUTEX, OBJ, LOCK) \ + ACE_GUARD_REACTION(MUTEX, OBJ, LOCK, return) +#define ACE_GUARD_RETURN(MUTEX, OBJ, LOCK, RETURN) \ + ACE_GUARD_REACTION(MUTEX, OBJ, LOCK, return RETURN) +# define ACE_WRITE_GUARD(MUTEX,OBJ,LOCK) \ + ACE_Write_Guard< MUTEX > OBJ (LOCK); \ + if (OBJ.locked () == 0) return; +# define ACE_WRITE_GUARD_RETURN(MUTEX,OBJ,LOCK,RETURN) \ + ACE_Write_Guard< MUTEX > OBJ (LOCK); \ + if (OBJ.locked () == 0) return RETURN; +# define ACE_READ_GUARD(MUTEX,OBJ,LOCK) \ + ACE_Read_Guard< MUTEX > OBJ (LOCK); \ + if (OBJ.locked () == 0) return; +# define ACE_READ_GUARD_RETURN(MUTEX,OBJ,LOCK,RETURN) \ + ACE_Read_Guard< MUTEX > OBJ (LOCK); \ + if (OBJ.locked () == 0) return RETURN; + +# if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) +# include /**/ "pace/semaphore.h" +# if !defined (SEM_FAILED) +# define SEM_FAILED ((pace_sem_t *) -1) +# endif /* !SEM_FAILED */ + +typedef struct +{ + pace_sem_t *sema_; + // Pointer to semaphore handle. This is allocated by ACE if we are + // working with an unnamed POSIX semaphore or by the OS if we are + // working with a named POSIX semaphore. + + char *name_; + // Name of the semaphore (if this is non-NULL then this is a named + // POSIX semaphore, else its an unnamed POSIX semaphore). +} ACE_sema_t; + +# elif defined (ACE_HAS_POSIX_SEM) +# include /**/ +# if !defined (SEM_FAILED) && !defined (ACE_LACKS_NAMED_POSIX_SEM) +# define SEM_FAILED ((sem_t *) -1) +# endif /* !SEM_FAILED */ + +typedef struct +{ + sem_t *sema_; + // Pointer to semaphore handle. This is allocated by ACE if we are + // working with an unnamed POSIX semaphore or by the OS if we are + // working with a named POSIX semaphore. + + char *name_; + // Name of the semaphore (if this is non-NULL then this is a named + // POSIX semaphore, else its an unnamed POSIX semaphore). + +#if defined (ACE_LACKS_NAMED_POSIX_SEM) + int new_sema_; + // this->sema_ doesn't always get created dynamically if a platform + // doesn't support named posix semaphores. We use this flag to + // remember if we need to delete or not. +#endif /* ACE_LACKS_NAMED_POSIX_SEM */ +} ACE_sema_t; +# endif /* ACE_HAS_PACE && !ACE_WIN32 */ + +struct cancel_state +{ + int cancelstate; + // e.g., PTHREAD_CANCEL_ENABLE, PTHREAD_CANCEL_DISABLE, + // PTHREAD_CANCELED. + + int canceltype; + // e.g., PTHREAD_CANCEL_DEFERRED and PTHREAD_CANCEL_ASYNCHRONOUS. +}; + +# if defined (ACE_HAS_WINCE) +# include /**/ + +typedef DWORD nlink_t; + +// CE's add-on for c-style fstat/stat functionalities. This struct is +// by no mean complete compared to what you usually find in UNIX +// platforms. Only members that have direct conversion using Win32's +// BY_HANDLE_FILE_INFORMATION are defined so that users can discover +// non-supported members at compile time. Time values are of type +// ACE_Time_Value for easy comparison. + +struct stat +{ + // mode_t st_mode; // UNIX styled file attribute + // nlink_t st_nlink; // number of hard links + ACE_Time_Value st_atime; // time of last access + ACE_Time_Value st_mtime; // time of last data modification + off_t st_size; // file size, in bytes + // u_long st_blksize; // optimal blocksize for I/O + // u_long st_flags; // user defined flags for file +}; + +# else /* ! ACE_HAS_WINCE */ +# if defined (ACE_LACKS_SYS_TYPES_H) +# if ! defined (ACE_PSOS) + typedef unsigned char u_char; + typedef unsigned short u_short; + typedef unsigned int u_int; + typedef unsigned long u_long; + + typedef unsigned char uchar_t; + typedef unsigned short ushort_t; + typedef unsigned int uint_t; + typedef unsigned long ulong_t; +# endif /* ! defined (ACE_PSOS) */ +# else +# include /**/ +# endif /* ACE_LACKS_SYS_TYPES_H */ + +# if ! defined (ACE_PSOS) +# include /**/ +# endif +# endif /* ACE_HAS_WINCE */ + + +#if defined (ACE_HAS_NO_THROW_SPEC) +# define ACE_THROW_SPEC(X) +#else +# if defined (ACE_HAS_EXCEPTIONS) +# define ACE_THROW_SPEC(X) throw X +# if defined (ACE_WIN32) && defined(_MSC_VER) && !defined (ghs) +// @@ MSVC "supports" the keyword but doesn't implement it (Huh?). +// Therefore, we simply supress the warning for now. +# pragma warning( disable : 4290 ) +# endif /* ACE_WIN32 */ +# else /* ! ACE_HAS_EXCEPTIONS */ +# define ACE_THROW_SPEC(X) +# endif /* ! ACE_HAS_EXCEPTIONS */ +#endif /*ACE_HAS_NO_THROW_SPEC*/ + +#if !defined (ACE_LACKS_UNISTD_H) +# include /**/ +#endif /* ACE_LACKS_UNISTD_H */ + +#if defined (ACE_HAS_PRIOCNTL) + // Need to #include thread.h before #defining THR_BOUND, etc., + // when building without threads on SunOS 5.x. +# if defined (sun) +# include /**/ +# endif /* sun */ + + // Need to #include these before #defining USYNC_PROCESS on SunOS 5.x. +# include /**/ +# include /**/ +#endif /* ACE_HAS_PRIOCNTL */ + +# if defined (ACE_HAS_THREADS) + +# if defined (ACE_HAS_STHREADS) +# include /**/ +# include /**/ +# 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 */ + +# if !defined (ACE_HAS_PTHREADS) +# define ACE_SCHED_OTHER 0 +# define ACE_SCHED_FIFO 1 +# define ACE_SCHED_RR 2 +# endif /* ! ACE_HAS_PTHREADS */ + +# if defined (ACE_HAS_PTHREADS) +# define ACE_SCHED_OTHER SCHED_OTHER +# define ACE_SCHED_FIFO SCHED_FIFO +# define ACE_SCHED_RR SCHED_RR + +// Definitions for mapping POSIX pthreads draft 6 into 1003.1c names + +# if defined (ACE_HAS_PTHREADS_DRAFT6) +# define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_LOCAL +# define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_GLOBAL +# define PTHREAD_CREATE_UNDETACHED 0 +# define PTHREAD_CREATE_DETACHED 1 +# define PTHREAD_CREATE_JOINABLE 0 +# define PTHREAD_EXPLICIT_SCHED 0 +# define PTHREAD_MIN_PRIORITY 0 +# define PTHREAD_MAX_PRIORITY 126 +# endif /* ACE_HAS_PTHREADS_DRAFT6 */ + +// Definitions for THREAD- and PROCESS-LEVEL priorities...some +// implementations define these while others don't. In order to +// further complicate matters, we don't redefine the default (*_DEF) +// values if they've already been defined, which allows individual +// programs to have their own ACE-wide "default". + +// PROCESS-level values +# if defined (_POSIX_PRIORITY_SCHEDULING) && \ + !defined(_UNICOS) && !defined(UNIXWARE_7_1) +# define ACE_PROC_PRI_FIFO_MIN (sched_get_priority_min(SCHED_FIFO)) +# define ACE_PROC_PRI_RR_MIN (sched_get_priority_min(SCHED_RR)) +# if defined (HPUX) + // HP-UX's other is the SCHED_HPUX class, which uses historical + // values that have reverse semantics from POSIX (low value is + // more important priority). To use these in pthreads calls, + // the values need to be converted. The other scheduling classes + // don't need this special treatment. +# define ACE_PROC_PRI_OTHER_MIN \ + (sched_get_priority_min(SCHED_OTHER)) +# else +# define ACE_PROC_PRI_OTHER_MIN (sched_get_priority_min(SCHED_OTHER)) +# endif /* HPUX */ +# else /* UNICOS is missing a sched_get_priority_min() implementation, + SCO too */ +# define ACE_PROC_PRI_FIFO_MIN 0 +# define ACE_PROC_PRI_RR_MIN 0 +# define ACE_PROC_PRI_OTHER_MIN 0 +# endif + +# if defined (_POSIX_PRIORITY_SCHEDULING) && !defined(UNIXWARE_7_1) +# define ACE_PROC_PRI_FIFO_MAX (sched_get_priority_max(SCHED_FIFO)) +# define ACE_PROC_PRI_RR_MAX (sched_get_priority_max(SCHED_RR)) +# if defined (HPUX) +# define ACE_PROC_PRI_OTHER_MAX \ + (sched_get_priority_max(SCHED_OTHER)) +# else +# define ACE_PROC_PRI_OTHER_MAX (sched_get_priority_max(SCHED_OTHER)) +# endif /* HPUX */ +# else /* SCO missing sched_get_priority_max() implementation */ +# define ACE_PROC_PRI_FIFO_MAX 59 +# define ACE_PROC_PRI_RR_MAX 59 +# define ACE_PROC_PRI_OTHER_MAX 59 +# endif + +# if !defined(ACE_PROC_PRI_FIFO_DEF) +# define ACE_PROC_PRI_FIFO_DEF (ACE_PROC_PRI_FIFO_MIN + (ACE_PROC_PRI_FIFO_MAX - ACE_PROC_PRI_FIFO_MIN)/2) +# endif +# if !defined(ACE_PROC_PRI_RR_DEF) +# define ACE_PROC_PRI_RR_DEF (ACE_PROC_PRI_RR_MIN + (ACE_PROC_PRI_RR_MAX - ACE_PROC_PRI_RR_MIN)/2) +# endif +# if !defined(ACE_PROC_PRI_OTHER_DEF) +# define ACE_PROC_PRI_OTHER_DEF (ACE_PROC_PRI_OTHER_MIN + (ACE_PROC_PRI_OTHER_MAX - ACE_PROC_PRI_OTHER_MIN)/2) +# endif + +// THREAD-level values +# if defined(PRI_FIFO_MIN) && defined(PRI_FIFO_MAX) && defined(PRI_RR_MIN) && defined(PRI_RR_MAX) && defined(PRI_OTHER_MIN) && defined(PRI_OTHER_MAX) +# if !defined (ACE_THR_PRI_FIFO_MIN) +# define ACE_THR_PRI_FIFO_MIN (long) PRI_FIFO_MIN +# endif /* !ACE_THR_PRI_FIFO_MIN */ +# if !defined (ACE_THR_PRI_FIFO_MAX) +# define ACE_THR_PRI_FIFO_MAX (long) PRI_FIFO_MAX +# endif /* !ACE_THR_PRI_FIFO_MAX */ +# if !defined (ACE_THR_PRI_RR_MIN) +# define ACE_THR_PRI_RR_MIN (long) PRI_RR_MIN +# endif /* !ACE_THR_PRI_RR_MIN */ +# if !defined (ACE_THR_PRI_RR_MAX) +# define ACE_THR_PRI_RR_MAX (long) PRI_RR_MAX +# endif /* !ACE_THR_PRI_RR_MAX */ +# if !defined (ACE_THR_PRI_OTHER_MIN) +# define ACE_THR_PRI_OTHER_MIN (long) PRI_OTHER_MIN +# endif /* !ACE_THR_PRI_OTHER_MIN */ +# if !defined (ACE_THR_PRI_OTHER_MAX) +# define ACE_THR_PRI_OTHER_MAX (long) PRI_OTHER_MAX +# endif /* !ACE_THR_PRI_OTHER_MAX */ +# elif defined (AIX) + // AIX's priority range is 1 (low) to 127 (high). There aren't + // any preprocessor macros I can find. PRIORITY_MIN is for + // process priorities, as far as I can see, and does not apply + // to thread priority. The 1 to 127 range is from the + // pthread_attr_setschedparam man page (Steve Huston, 18-May-2001). +# if !defined (ACE_THR_PRI_FIFO_MIN) +# define ACE_THR_PRI_FIFO_MIN (long) 1 +# endif /* !ACE_THR_PRI_FIFO_MIN */ +# if !defined (ACE_THR_PRI_FIFO_MAX) +# define ACE_THR_PRI_FIFO_MAX (long) 127 +# endif /* !ACE_THR_PRI_FIFO_MAX */ +# if !defined (ACE_THR_PRI_RR_MIN) +# define ACE_THR_PRI_RR_MIN (long) 1 +# endif /* !ACE_THR_PRI_RR_MIN */ +# if !defined (ACE_THR_PRI_RR_MAX) +# define ACE_THR_PRI_RR_MAX (long) 127 +# endif /* !ACE_THR_PRI_RR_MAX */ +# if !defined (ACE_THR_PRI_OTHER_MIN) +# define ACE_THR_PRI_OTHER_MIN (long) 1 +# endif /* !ACE_THR_PRI_OTHER_MIN */ +# if !defined (ACE_THR_PRI_OTHER_MAX) +# define ACE_THR_PRI_OTHER_MAX (long) 127 +# endif /* !ACE_THR_PRI_OTHER_MAX */ +# elif defined (sun) +# if !defined (ACE_THR_PRI_FIFO_MIN) +# define ACE_THR_PRI_FIFO_MIN (long) 0 +# endif /* !ACE_THR_PRI_FIFO_MIN */ +# if !defined (ACE_THR_PRI_FIFO_MAX) +# define ACE_THR_PRI_FIFO_MAX (long) 59 +# endif /* !ACE_THR_PRI_FIFO_MAX */ +# if !defined (ACE_THR_PRI_RR_MIN) +# define ACE_THR_PRI_RR_MIN (long) 0 +# endif /* !ACE_THR_PRI_RR_MIN */ +# if !defined (ACE_THR_PRI_RR_MAX) +# define ACE_THR_PRI_RR_MAX (long) 59 +# endif /* !ACE_THR_PRI_RR_MAX */ +# if !defined (ACE_THR_PRI_OTHER_MIN) +# define ACE_THR_PRI_OTHER_MIN (long) 0 +# endif /* !ACE_THR_PRI_OTHER_MIN */ +# if !defined (ACE_THR_PRI_OTHER_MAX) +# define ACE_THR_PRI_OTHER_MAX (long) 127 +# endif /* !ACE_THR_PRI_OTHER_MAX */ +# else +# if !defined (ACE_THR_PRI_FIFO_MIN) +# define ACE_THR_PRI_FIFO_MIN (long) ACE_PROC_PRI_FIFO_MIN +# endif /* !ACE_THR_PRI_FIFO_MIN */ +# if !defined (ACE_THR_PRI_FIFO_MAX) +# define ACE_THR_PRI_FIFO_MAX (long) ACE_PROC_PRI_FIFO_MAX +# endif /* !ACE_THR_PRI_FIFO_MAX */ +# if !defined (ACE_THR_PRI_RR_MIN) +# define ACE_THR_PRI_RR_MIN (long) ACE_PROC_PRI_RR_MIN +# endif /* !ACE_THR_PRI_RR_MIN */ +# if !defined (ACE_THR_PRI_RR_MAX) +# define ACE_THR_PRI_RR_MAX (long) ACE_PROC_PRI_RR_MAX +# endif /* !ACE_THR_PRI_RR_MAX */ +# if !defined (ACE_THR_PRI_OTHER_MIN) +# define ACE_THR_PRI_OTHER_MIN (long) ACE_PROC_PRI_OTHER_MIN +# endif /* !ACE_THR_PRI_OTHER_MIN */ +# if !defined (ACE_THR_PRI_OTHER_MAX) +# define ACE_THR_PRI_OTHER_MAX (long) ACE_PROC_PRI_OTHER_MAX +# endif /* !ACE_THR_PRI_OTHER_MAX */ +# endif +# if !defined(ACE_THR_PRI_FIFO_DEF) +# define ACE_THR_PRI_FIFO_DEF ((ACE_THR_PRI_FIFO_MIN + ACE_THR_PRI_FIFO_MAX)/2) +# endif +# if !defined(ACE_THR_PRI_RR_DEF) +# define ACE_THR_PRI_RR_DEF ((ACE_THR_PRI_RR_MIN + ACE_THR_PRI_RR_MAX)/2) +# endif +# if !defined(ACE_THR_PRI_OTHER_DEF) +# define ACE_THR_PRI_OTHER_DEF ((ACE_THR_PRI_OTHER_MIN + ACE_THR_PRI_OTHER_MAX)/2) +# endif + +// Typedefs to help compatibility with Windows NT and Pthreads. +typedef pthread_t ACE_hthread_t; +typedef pthread_t ACE_thread_t; + +# if defined (ACE_HAS_TSS_EMULATION) + typedef pthread_key_t ACE_OS_thread_key_t; + typedef u_long ACE_thread_key_t; +# else /* ! ACE_HAS_TSS_EMULATION */ + typedef pthread_key_t ACE_thread_key_t; +# endif /* ! ACE_HAS_TSS_EMULATION */ + +# if !defined (ACE_LACKS_COND_T) +typedef pthread_mutex_t ACE_mutex_t; +typedef pthread_cond_t ACE_cond_t; +typedef pthread_condattr_t ACE_condattr_t; +typedef pthread_mutexattr_t ACE_mutexattr_t; +# endif /* ! ACE_LACKS_COND_T */ +typedef pthread_mutex_t ACE_thread_mutex_t; + +# if !defined (PTHREAD_CANCEL_DISABLE) +# define PTHREAD_CANCEL_DISABLE 0 +# endif /* PTHREAD_CANCEL_DISABLE */ + +# if !defined (PTHREAD_CANCEL_ENABLE) +# define PTHREAD_CANCEL_ENABLE 0 +# endif /* PTHREAD_CANCEL_ENABLE */ + +# if !defined (PTHREAD_CANCEL_DEFERRED) +# define PTHREAD_CANCEL_DEFERRED 0 +# endif /* PTHREAD_CANCEL_DEFERRED */ + +# if !defined (PTHREAD_CANCEL_ASYNCHRONOUS) +# define PTHREAD_CANCEL_ASYNCHRONOUS 0 +# endif /* PTHREAD_CANCEL_ASYNCHRONOUS */ + +# define THR_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE +# define THR_CANCEL_ENABLE PTHREAD_CANCEL_ENABLE +# define THR_CANCEL_DEFERRED PTHREAD_CANCEL_DEFERRED +# define THR_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_ASYNCHRONOUS + +# if !defined (PTHREAD_CREATE_JOINABLE) +# if defined (PTHREAD_CREATE_UNDETACHED) +# define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED +# else +# define PTHREAD_CREATE_JOINABLE 0 +# endif /* PTHREAD_CREATE_UNDETACHED */ +# endif /* PTHREAD_CREATE_JOINABLE */ + +# if !defined (PTHREAD_CREATE_DETACHED) +# define PTHREAD_CREATE_DETACHED 1 +# endif /* PTHREAD_CREATE_DETACHED */ + +# if !defined (PTHREAD_PROCESS_PRIVATE) && !defined (ACE_HAS_PTHREAD_PROCESS_ENUM) +# if defined (PTHREAD_MUTEXTYPE_FAST) +# define PTHREAD_PROCESS_PRIVATE PTHREAD_MUTEXTYPE_FAST +# else +# define PTHREAD_PROCESS_PRIVATE 0 +# endif /* PTHREAD_MUTEXTYPE_FAST */ +# endif /* PTHREAD_PROCESS_PRIVATE */ + +# if !defined (PTHREAD_PROCESS_SHARED) && !defined (ACE_HAS_PTHREAD_PROCESS_ENUM) +# if defined (PTHREAD_MUTEXTYPE_FAST) +# define PTHREAD_PROCESS_SHARED PTHREAD_MUTEXTYPE_FAST +# else +# define PTHREAD_PROCESS_SHARED 1 +# endif /* PTHREAD_MUTEXTYPE_FAST */ +# endif /* PTHREAD_PROCESS_SHARED */ + +# if defined (ACE_HAS_PTHREADS_DRAFT4) +# if defined (PTHREAD_PROCESS_PRIVATE) +# if !defined (USYNC_THREAD) +# define USYNC_THREAD PTHREAD_PROCESS_PRIVATE +# endif /* ! USYNC_THREAD */ +# else +# if !defined (USYNC_THREAD) +# define USYNC_THREAD MUTEX_NONRECURSIVE_NP +# endif /* ! USYNC_THREAD */ +# endif /* PTHREAD_PROCESS_PRIVATE */ + +# if defined (PTHREAD_PROCESS_SHARED) +# if !defined (USYNC_PROCESS) +# define USYNC_PROCESS PTHREAD_PROCESS_SHARED +# endif /* ! USYNC_PROCESS */ +# else +# if !defined (USYNC_PROCESS) +# define USYNC_PROCESS MUTEX_NONRECURSIVE_NP +# endif /* ! USYNC_PROCESS */ +# endif /* PTHREAD_PROCESS_SHARED */ +# elif !defined (ACE_HAS_STHREADS) +# if !defined (USYNC_THREAD) +# define USYNC_THREAD PTHREAD_PROCESS_PRIVATE +# endif /* ! USYNC_THREAD */ +# if !defined (USYNC_PROCESS) +# define USYNC_PROCESS PTHREAD_PROCESS_SHARED +# endif /* ! USYNC_PROCESS */ +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + +/* MM-Graz: prevent warnings */ +#undef THR_BOUND +#undef THR_NEW_LWP +#undef THR_DETACHED +#undef THR_SUSPENDED +#undef THR_DAEMON + +# define THR_BOUND 0x00000001 +# if defined (CHORUS) +# define THR_NEW_LWP 0x00000000 +# else +# define THR_NEW_LWP 0x00000002 +# endif /* CHORUS */ +# define THR_DETACHED 0x00000040 +# define THR_SUSPENDED 0x00000080 +# define THR_DAEMON 0x00000100 +# define THR_JOINABLE 0x00010000 +# define THR_SCHED_FIFO 0x00020000 +# define THR_SCHED_RR 0x00040000 +# define THR_SCHED_DEFAULT 0x00080000 + +# if defined (ACE_HAS_IRIX62_THREADS) +# define THR_SCOPE_SYSTEM 0x00100000 +# else +# define THR_SCOPE_SYSTEM THR_BOUND +#endif /*ACE_HAS_IRIX62_THREADS*/ + +# define THR_SCOPE_PROCESS 0x00200000 +# define THR_INHERIT_SCHED 0x00400000 +# define THR_EXPLICIT_SCHED 0x00800000 +# define THR_SCHED_IO 0x01000000 + +# if !defined (ACE_HAS_STHREADS) +# if !defined (ACE_HAS_POSIX_SEM) +/** + * @class ACE_sema_t + * + * @brief This is used to implement semaphores for platforms that support + * POSIX pthreads, but do *not* support POSIX semaphores, i.e., + * it's a different type than the POSIX . + */ +class ACE_OS_Export ACE_sema_t +{ +friend class ACE_OS; +protected: + /// Serialize access to internal state. + ACE_mutex_t lock_; + + /// Block until there are no waiters. + ACE_cond_t count_nonzero_; + + /// Count of the semaphore. + u_long count_; + + /// Number of threads that have called . + u_long waiters_; +}; +# endif /* !ACE_HAS_POSIX_SEM */ + +# if defined (ACE_LACKS_PTHREAD_YIELD) && defined (ACE_HAS_THR_YIELD) + // If we are on Solaris we can just reuse the existing + // implementations of these synchronization types. +# if !defined (ACE_LACKS_RWLOCK_T) +# include /**/ +typedef rwlock_t ACE_rwlock_t; +# endif /* !ACE_LACKS_RWLOCK_T */ +# include /**/ +# endif /* (ACE_LACKS_PTHREAD_YIELD) && defined (ACE_HAS_THR_YIELD) */ + +# else +# if !defined (ACE_HAS_POSIX_SEM) +typedef sema_t ACE_sema_t; +# endif /* !ACE_HAS_POSIX_SEM */ +# endif /* !ACE_HAS_STHREADS */ +# elif defined (ACE_HAS_STHREADS) +// Solaris threads, without PTHREADS. +// Typedefs to help compatibility with Windows NT and Pthreads. +typedef thread_t ACE_thread_t; +typedef thread_key_t ACE_thread_key_t; +typedef mutex_t ACE_mutex_t; +# if !defined (ACE_LACKS_RWLOCK_T) +typedef rwlock_t ACE_rwlock_t; +# endif /* !ACE_LACKS_RWLOCK_T */ +# if !defined (ACE_HAS_POSIX_SEM) +typedef sema_t ACE_sema_t; +# endif /* !ACE_HAS_POSIX_SEM */ + +typedef cond_t ACE_cond_t; +struct ACE_OS_Export ACE_condattr_t +{ + int type; +}; +struct ACE_OS_Export ACE_mutexattr_t +{ + int type; +}; +typedef ACE_thread_t ACE_hthread_t; +typedef ACE_mutex_t ACE_thread_mutex_t; + +# define THR_CANCEL_DISABLE 0 +# define THR_CANCEL_ENABLE 0 +# define THR_CANCEL_DEFERRED 0 +# define THR_CANCEL_ASYNCHRONOUS 0 +# define THR_JOINABLE 0 +# define THR_SCHED_FIFO 0 +# define THR_SCHED_RR 0 +# define THR_SCHED_DEFAULT 0 + +# elif defined (ACE_PSOS) + +// Some versions of pSOS provide native mutex support. For others, +// implement ACE_thread_mutex_t and ACE_mutex_t using pSOS semaphores. +// Either way, the types are all u_longs. +typedef u_long ACE_mutex_t; +typedef u_long ACE_thread_mutex_t; +typedef u_long ACE_thread_t; +typedef u_long ACE_hthread_t; + +#if defined (ACE_PSOS_HAS_COND_T) +typedef u_long ACE_cond_t; +typedef u_long ACE_condattr_t; +struct ACE_OS_Export ACE_mutexattr_t +{ + int type; +}; +#endif /* ACE_PSOS_HAS_COND_T */ + + +// TCB registers 0-7 are for application use +# define PSOS_TASK_REG_TSS 0 +# define PSOS_TASK_REG_MAX 7 + +# define PSOS_TASK_MIN_PRIORITY 1 +# define PSOS_TASK_MAX_PRIORITY 239 + +// Key type: the ACE TSS emulation requires the key type be unsigned, +// for efficiency. Current POSIX and Solaris TSS implementations also +// use unsigned int, so the ACE TSS emulation is compatible with them. +// Native pSOS TSD, where available, uses unsigned long as the key type. +# if defined (ACE_PSOS_HAS_TSS) +typedef u_long ACE_thread_key_t; +# else +typedef u_int ACE_thread_key_t; +# endif /* ACE_PSOS_HAS_TSS */ + +# define THR_CANCEL_DISABLE 0 /* thread can never be cancelled */ +# define THR_CANCEL_ENABLE 0 /* thread can be cancelled */ +# define THR_CANCEL_DEFERRED 0 /* cancellation deferred to cancellation point */ +# define THR_CANCEL_ASYNCHRONOUS 0 /* cancellation occurs immediately */ + +# define THR_BOUND 0 +# define THR_NEW_LWP 0 +# define THR_DETACHED 0 +# define THR_SUSPENDED 0 +# define THR_DAEMON 0 +# define THR_JOINABLE 0 + +# define THR_SCHED_FIFO 0 +# define THR_SCHED_RR 0 +# define THR_SCHED_DEFAULT 0 +# define USYNC_THREAD T_LOCAL +# define USYNC_PROCESS T_GLOBAL + +/* from psos.h */ +/* #define T_NOPREEMPT 0x00000001 Not preemptible bit */ +/* #define T_PREEMPT 0x00000000 Preemptible */ +/* #define T_TSLICE 0x00000002 Time-slicing enabled bit */ +/* #define T_NOTSLICE 0x00000000 No Time-slicing */ +/* #define T_NOASR 0x00000004 ASRs disabled bit */ +/* #define T_ASR 0x00000000 ASRs enabled */ + +/* #define SM_GLOBAL 0x00000001 1 = Global */ +/* #define SM_LOCAL 0x00000000 0 = Local */ +/* #define SM_PRIOR 0x00000002 Queue by priority */ +/* #define SM_FIFO 0x00000000 Queue by FIFO order */ + +/* #define T_NOFPU 0x00000000 Not using FPU */ +/* #define T_FPU 0x00000002 Using FPU bit */ + +# elif defined (VXWORKS) +// For mutex implementation using mutual-exclusion semaphores (which +// can be taken recursively). +# include /**/ + +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ + +extern "C" +struct sockaddr_un { + short sun_family; // AF_UNIX. + char sun_path[108]; // path name. +}; + +# define MAXPATHLEN 1024 +# define MAXNAMLEN 255 +# define NSIG (_NSIGS + 1) + +// task options: the other options are either obsolete, internal, or for +// Fortran or Ada support +# define VX_UNBREAKABLE 0x0002 /* breakpoints ignored */ +# define VX_FP_TASK 0x0008 /* floating point coprocessor */ +# define VX_PRIVATE_ENV 0x0080 /* private environment support */ +# define VX_NO_STACK_FILL 0x0100 /* do not stack fill for + checkstack () */ + +# define THR_CANCEL_DISABLE 0 +# define THR_CANCEL_ENABLE 0 +# define THR_CANCEL_DEFERRED 0 +# define THR_CANCEL_ASYNCHRONOUS 0 +# define THR_BOUND 0 +# define THR_NEW_LWP 0 +# define THR_DETACHED 0 +# define THR_SUSPENDED 0 +# define THR_DAEMON 0 +# define THR_JOINABLE 0 +# define THR_SCHED_FIFO 0 +# define THR_SCHED_RR 0 +# define THR_SCHED_DEFAULT 0 +# define THR_INHERIT_SCHED 0 +# define THR_EXPLICIT_SCHED 0 +# define THR_SCHED_IO 0 +# define THR_SCOPE_SYSTEM 0 +# define THR_SCOPE_PROCESS 0 +# define USYNC_THREAD 0 +# define USYNC_PROCESS 1 /* It's all global on VxWorks + (without MMU option). */ +# if defined (ACE_HAS_PACE) +# define ACE_PROC_PRI_FIFO_MIN (sched_get_priority_min(SCHED_FIFO)) +# define ACE_PROC_PRI_FIFO_MAX (sched_get_priority_max(SCHED_FIFO)) +# define ACE_PROC_PRI_RR_MIN (sched_get_priority_min(SCHED_RR)) +# define ACE_PROC_PRI_RR_MAX (sched_get_priority_max(SCHED_RR)) +# define ACE_PROC_PRI_OTHER_MIN (sched_get_priority_min(SCHED_OTHER)) +# define ACE_PROC_PRI_OTHER_MAX (sched_get_priority_max(SCHED_OTHER)) +# if !defined (ACE_THR_PRI_FIFO_MIN) +# define ACE_THR_PRI_FIFO_MIN (long) ACE_PROC_PRI_FIFO_MIN +# endif /* !ACE_THR_PRI_FIFO_MIN */ +# if !defined (ACE_THR_PRI_FIFO_MAX) +# define ACE_THR_PRI_FIFO_MAX (long) ACE_PROC_PRI_FIFO_MAX +# endif /* !ACE_THR_PRI_FIFO_MAX */ +# if !defined (ACE_THR_PRI_RR_MIN) +# define ACE_THR_PRI_RR_MIN (long) ACE_PROC_PRI_RR_MIN +# endif /* !ACE_THR_PRI_RR_MIN */ +# if !defined (ACE_THR_PRI_RR_MAX) +# define ACE_THR_PRI_RR_MAX (long) ACE_PROC_PRI_RR_MAX +# endif /* !ACE_THR_PRI_RR_MAX */ +# if !defined (ACE_THR_PRI_OTHER_MIN) +# define ACE_THR_PRI_OTHER_MIN (long) ACE_PROC_PRI_OTHER_MIN +# endif /* !ACE_THR_PRI_OTHER_MIN */ +# if !defined (ACE_THR_PRI_OTHER_MAX) +# define ACE_THR_PRI_OTHER_MAX (long) ACE_PROC_PRI_OTHER_MAX +# endif /* !ACE_THR_PRI_OTHER_MAX */ +# endif /* ACE_HAS_PACE */ + +# if !defined (ACE_DEFAULT_SYNCH_TYPE) + // Types include these options: SEM_Q_PRIORITY, SEM_Q_FIFO, + // SEM_DELETE_SAFE, and SEM_INVERSION_SAFE. SEM_Q_FIFO is + // used as the default because that is VxWorks' default. +# define ACE_DEFAULT_SYNCH_TYPE SEM_Q_FIFO +# endif /* ! ACE_DEFAULT_SYNCH_TYPE */ + +# if defined (ACE_HAS_PACE) +typedef pace_pthread_mutex_t ACE_mutex_t; +typedef pace_pthread_mutexattr_t ACE_mutexattr_t; +typedef pace_pthread_cond_t ACE_cond_t; +typedef pace_pthread_condattr_t ACE_condattr_t; +# else +typedef SEM_ID ACE_mutex_t; +# endif /* ACE_HAS_PACE */ +// Implement ACE_thread_mutex_t with ACE_mutex_t because there's just +// one process . . . +typedef ACE_mutex_t ACE_thread_mutex_t; +# if !defined (ACE_HAS_POSIX_SEM) +// Use VxWorks semaphores, wrapped ... +typedef struct +{ +# if defined (ACE_HAS_PACE) + pace_pthread_mutex_t sema_; +# else + SEM_ID sema_; +# endif /* ACE_HAS_PACE */ + // Semaphore handle. This is allocated by VxWorks. + + char *name_; + // Name of the semaphore: always NULL with VxWorks. +} ACE_sema_t; +# endif /* !ACE_HAS_POSIX_SEM */ +# if defined (ACE_HAS_PACE) +typedef pace_pthread_t ACE_thread_t; +typedef pace_pthread_t ACE_hthread_t; +# else +typedef char * ACE_thread_t; +typedef int ACE_hthread_t; +# endif /* ACE_HAS_PACE */ +// Key type: the ACE TSS emulation requires the key type be unsigned, +// for efficiency. (Current POSIX and Solaris TSS implementations also +// use u_int, so the ACE TSS emulation is compatible with them.) +typedef u_int ACE_thread_key_t; + + // Marker for ACE_Thread_Manager to indicate that it allocated + // an ACE_thread_t. It is placed at the beginning of the ID. +# define ACE_THR_ID_ALLOCATED '\022' + +# elif defined (ACE_HAS_WTHREADS) + +typedef CRITICAL_SECTION ACE_thread_mutex_t; + +# if defined (ACE_HAS_PACE) +typedef pace_pthread_mutex_t ACE_mutex_t; +# else +typedef struct +{ + int type_; // Either USYNC_THREAD or USYNC_PROCESS + union + { + HANDLE proc_mutex_; + CRITICAL_SECTION thr_mutex_; + }; +} ACE_mutex_t; +# endif /* ACE_HAS_PACE */ + +// Wrapper for NT Events. +typedef HANDLE ACE_event_t; + +# if !defined (ACE_HAS_PACE) || defined (ACE_WIN32) +// This can probably get _wider_ as more types are defined in PACE. +// ie: see above ACE_mutex_t + +//@@ ACE_USES_WINCE_SEMA_SIMULATION is used to debug +// semaphore simulation on WinNT. It should be +// changed to ACE_USES_HAS_WINCE at some later point. +# if !defined (ACE_USES_WINCE_SEMA_SIMULATION) +typedef HANDLE ACE_sema_t; +# else +/** + * @class ACE_sema_t + * + * @brief Semaphore simulation for Windows CE. + */ +class ACE_OS_Export ACE_sema_t +{ +public: + /// Serializes access to . + ACE_thread_mutex_t lock_; + + /// This event is signaled whenever the count becomes non-zero. + ACE_event_t count_nonzero_; + + /// Current count of the semaphore. + u_int count_; +}; + +# endif /* ACE_USES_WINCE_SEMA_SIMULATION */ +# endif /* !ACE_HAS_PACE || defined (ACE_WIN32) */ + +// These need to be different values, neither of which can be 0... +# define USYNC_THREAD 1 +# define USYNC_PROCESS 2 + +# define THR_CANCEL_DISABLE 0 +# define THR_CANCEL_ENABLE 0 +# define THR_CANCEL_DEFERRED 0 +# define THR_CANCEL_ASYNCHRONOUS 0 +# define THR_DETACHED 0x02000000 /* ignore in most places */ +# define THR_BOUND 0 /* ignore in most places */ +# define THR_NEW_LWP 0 /* ignore in most places */ +# define THR_DAEMON 0 /* ignore in most places */ +# define THR_JOINABLE 0 /* ignore in most places */ +# define THR_SUSPENDED CREATE_SUSPENDED +# define THR_USE_AFX 0x01000000 +# define THR_SCHED_FIFO 0 +# define THR_SCHED_RR 0 +# define THR_SCHED_DEFAULT 0 +# define THR_SCOPE_PROCESS 0 +# define THR_SCOPE_SYSTEM 0 +# endif /* ACE_HAS_PTHREADS / STHREADS / PSOS / VXWORKS / WTHREADS */ + +// If we're using PACE then we don't want this class (since PACE +// takes care of it) unless we're on Windows. Win32 mutexes, semaphores, +// and condition variables are not yet supported in PACE. +# if defined (ACE_LACKS_COND_T) && (!defined (ACE_HAS_PACE) || defined (ACE_WIN32)) +/** + * @class ACE_cond_t + * + * @brief This structure is used to implement condition variables on + * platforms that lack it natively, such as VxWorks, pSoS, and + * Win32. + * + * At the current time, this stuff only works for threads + * within the same process. + */ +class ACE_OS_Export ACE_cond_t +{ +public: + friend class ACE_OS; + + /// Returns the number of waiters. + long waiters (void) const; + +protected: + /// Number of waiting threads. + long waiters_; + + /// Serialize access to the waiters count. + ACE_thread_mutex_t waiters_lock_; + + /// Queue up threads waiting for the condition to become signaled. + ACE_sema_t sema_; + +# if defined (VXWORKS) || defined (ACE_PSOS) + /** + * A semaphore used by the broadcast/signal thread to wait for all + * the waiting thread(s) to wake up and be released from the + * semaphore. + */ + ACE_sema_t waiters_done_; +# elif defined (ACE_WIN32) + /** + * An auto reset event used by the broadcast/signal thread to wait + * for the waiting thread(s) to wake up and get a chance at the + * semaphore. + */ + HANDLE waiters_done_; +# else +# error "Please implement this feature or check your config.h file!" +# endif /* VXWORKS || ACE_PSOS */ + + /// Keeps track of whether we were broadcasting or just signaling. + size_t was_broadcast_; +}; + +struct ACE_OS_Export ACE_condattr_t +{ + int type; +}; + +# if defined (ACE_HAS_PACE) +typedef pace_pthread_mutexattr_t ACE_mutexattr_t; +# else +struct ACE_OS_Export ACE_mutexattr_t +{ + int type; +}; +# endif /* ACE_HAS_PACE */ +# endif /* ACE_LACKS_COND_T */ + +# if defined (ACE_LACKS_RWLOCK_T) && !defined (ACE_HAS_PTHREADS_UNIX98_EXT) + +/** + * @class ACE_rwlock_t + * + * @brief This is used to implement readers/writer locks on NT, + * VxWorks, and POSIX pthreads. + * + * At the current time, this stuff only works for threads + * within the same process. + */ +struct ACE_OS_Export ACE_rwlock_t +{ +protected: + friend class ACE_OS; + + ACE_mutex_t lock_; + // Serialize access to internal state. + + ACE_cond_t waiting_readers_; + // Reader threads waiting to acquire the lock. + + int num_waiting_readers_; + // Number of waiting readers. + + ACE_cond_t waiting_writers_; + // Writer threads waiting to acquire the lock. + + int num_waiting_writers_; + // Number of waiting writers. + + int ref_count_; + // Value is -1 if writer has the lock, else this keeps track of the + // number of readers holding the lock. + + int important_writer_; + // indicate that a reader is trying to upgrade + + ACE_cond_t waiting_important_writer_; + // condition for the upgrading reader +}; +# elif defined (ACE_HAS_PTHREADS_UNIX98_EXT) +typedef pthread_rwlock_t ACE_rwlock_t; +# elif defined (ACE_HAS_STHREADS) +# include /**/ +typedef rwlock_t ACE_rwlock_t; +# endif /* ACE_LACKS_RWLOCK_T */ + +// Define some default thread priorities on all threaded platforms, if +// not defined above or in the individual platform config file. +// ACE_THR_PRI_FIFO_DEF should be used by applications for default +// real-time thread priority. ACE_THR_PRI_OTHER_DEF should be used +// for non-real-time priority. +# if !defined(ACE_THR_PRI_FIFO_DEF) +# if defined (ACE_WTHREADS) + // It would be more in spirit to use THREAD_PRIORITY_NORMAL. But, + // using THREAD_PRIORITY_ABOVE_NORMAL should give preference to the + // threads in this process, even if the process is not in the + // REALTIME_PRIORITY_CLASS. +# define ACE_THR_PRI_FIFO_DEF THREAD_PRIORITY_ABOVE_NORMAL +# else /* ! ACE_WTHREADS */ +# define ACE_THR_PRI_FIFO_DEF 0 +# endif /* ! ACE_WTHREADS */ +# endif /* ! ACE_THR_PRI_FIFO_DEF */ + +# if !defined(ACE_THR_PRI_OTHER_DEF) +# if defined (ACE_WTHREADS) + // It would be more in spirit to use THREAD_PRIORITY_NORMAL. But, + // using THREAD_PRIORITY_ABOVE_NORMAL should give preference to the + // threads in this process, even if the process is not in the + // REALTIME_PRIORITY_CLASS. +# define ACE_THR_PRI_OTHER_DEF THREAD_PRIORITY_NORMAL +# else /* ! ACE_WTHREADS */ +# define ACE_THR_PRI_OTHER_DEF 0 +# endif /* ! ACE_WTHREADS */ +# endif /* ! ACE_THR_PRI_OTHER_DEF */ + +#if defined (ACE_HAS_RECURSIVE_MUTEXES) +typedef ACE_thread_mutex_t ACE_recursive_thread_mutex_t; +#else +/** + * @class ACE_recursive_thread_mutex_t + * + * @brief Implement a thin C++ wrapper that allows nested acquisition + * and release of a mutex that occurs in the same thread. + * + * This implementation is based on an algorithm sketched by Dave + * Butenhof . Naturally, I take the + * credit for any mistakes ;-) + */ +class ACE_recursive_thread_mutex_t +{ +public: + /// Guards the state of the nesting level and thread id. + ACE_thread_mutex_t nesting_mutex_; + + /// This condition variable suspends other waiting threads until the + /// mutex is available. + ACE_cond_t lock_available_; + + /// Current nesting level of the recursion. + int nesting_level_; + + /// Current owner of the lock. + ACE_thread_t owner_id_; +}; +#endif /* ACE_WIN32 */ + +# else /* !ACE_HAS_THREADS, i.e., the OS/platform doesn't support threading. */ + +// Give these things some reasonable value... +# define ACE_SCOPE_PROCESS 0 +# define ACE_SCOPE_LWP 1 +# define ACE_SCOPE_THREAD 2 +# define ACE_SCHED_OTHER 0 +# define ACE_SCHED_FIFO 1 +# define ACE_SCHED_RR 2 +# if !defined (THR_CANCEL_DISABLE) +# define THR_CANCEL_DISABLE 0 +# endif /* ! THR_CANCEL_DISABLE */ +# if !defined (THR_CANCEL_ENABLE) +# define THR_CANCEL_ENABLE 0 +# endif /* ! THR_CANCEL_ENABLE */ +# if !defined (THR_CANCEL_DEFERRED) +# define THR_CANCEL_DEFERRED 0 +# endif /* ! THR_CANCEL_DEFERRED */ +# if !defined (THR_CANCEL_ASYNCHRONOUS) +# define THR_CANCEL_ASYNCHRONOUS 0 +# endif /* ! THR_CANCEL_ASYNCHRONOUS */ +# if !defined (THR_JOINABLE) +# define THR_JOINABLE 0 /* ignore in most places */ +# endif /* ! THR_JOINABLE */ +# if !defined (THR_DETACHED) +# define THR_DETACHED 0 /* ignore in most places */ +# endif /* ! THR_DETACHED */ +# if !defined (THR_DAEMON) +# define THR_DAEMON 0 /* ignore in most places */ +# endif /* ! THR_DAEMON */ +# if !defined (THR_BOUND) +# define THR_BOUND 0 /* ignore in most places */ +# endif /* ! THR_BOUND */ +# if !defined (THR_NEW_LWP) +# define THR_NEW_LWP 0 /* ignore in most places */ +# endif /* ! THR_NEW_LWP */ +# if !defined (THR_SUSPENDED) +# define THR_SUSPENDED 0 /* ignore in most places */ +# endif /* ! THR_SUSPENDED */ +# if !defined (THR_SCHED_FIFO) +# define THR_SCHED_FIFO 0 +# endif /* ! THR_SCHED_FIFO */ +# if !defined (THR_SCHED_RR) +# define THR_SCHED_RR 0 +# endif /* ! THR_SCHED_RR */ +# if !defined (THR_SCHED_DEFAULT) +# define THR_SCHED_DEFAULT 0 +# endif /* ! THR_SCHED_DEFAULT */ +# if !defined (USYNC_THREAD) +# define USYNC_THREAD 0 +# endif /* ! USYNC_THREAD */ +# if !defined (USYNC_PROCESS) +# define USYNC_PROCESS 0 +# endif /* ! USYNC_PROCESS */ +# if !defined (THR_SCOPE_PROCESS) +# define THR_SCOPE_PROCESS 0 +# endif /* ! THR_SCOPE_PROCESS */ +# if !defined (THR_SCOPE_SYSTEM) +# define THR_SCOPE_SYSTEM 0 +# endif /* ! THR_SCOPE_SYSTEM */ + +// These are dummies needed for class OS.h +typedef int ACE_cond_t; +struct ACE_OS_Export ACE_condattr_t +{ + int type; +}; +struct ACE_OS_Export ACE_mutexattr_t +{ + int type; +}; +typedef int ACE_mutex_t; +typedef int ACE_thread_mutex_t; +typedef int ACE_recursive_thread_mutex_t; +# if !defined (ACE_HAS_POSIX_SEM) && !defined (ACE_PSOS) +typedef int ACE_sema_t; +# endif /* !ACE_HAS_POSIX_SEM && !ACE_PSOS */ +typedef int ACE_rwlock_t; +typedef int ACE_thread_t; +typedef int ACE_hthread_t; +typedef u_int ACE_thread_key_t; + +// Ensure that ACE_THR_PRI_FIFO_DEF and ACE_THR_PRI_OTHER_DEF are +// defined on non-threaded platforms, to support application source +// code compatibility. ACE_THR_PRI_FIFO_DEF should be used by +// applications for default real-time thread priority. +// ACE_THR_PRI_OTHER_DEF should be used for non-real-time priority. +# if !defined(ACE_THR_PRI_FIFO_DEF) +# define ACE_THR_PRI_FIFO_DEF 0 +# endif /* ! ACE_THR_PRI_FIFO_DEF */ +# if !defined(ACE_THR_PRI_OTHER_DEF) +# define ACE_THR_PRI_OTHER_DEF 0 +# endif /* ! ACE_THR_PRI_OTHER_DEF */ + +# endif /* ACE_HAS_THREADS */ + +# if defined (ACE_PSOS) + +// Wrapper for NT events on pSOS. +class ACE_OS_Export ACE_event_t +{ + friend class ACE_OS; + +protected: + + /// Protect critical section. + ACE_mutex_t lock_; + + /// Keeps track of waiters. + ACE_cond_t condition_; + + /// Specifies if this is an auto- or manual-reset event. + int manual_reset_; + + /// "True" if signaled. + int is_signaled_; + + /// Number of waiting threads. + u_long waiting_threads_; +}; + +# endif /* ACE_PSOS */ + +// Standard C Library includes +// NOTE: stdarg.h must be #included before stdio.h on LynxOS. +# include /**/ +# if !defined (ACE_HAS_WINCE) +# include /**/ +# include /**/ +// this is a nasty hack to get around problems with the +// pSOS definition of BUFSIZ as the config table entry +// (which is valued using the LC_BUFSIZ value anyway) +# if defined (ACE_PSOS) +# if defined (BUFSIZ) +# undef BUFSIZ +# endif /* defined (BUFSIZ) */ +# define BUFSIZ LC_BUFSIZ +# endif /* defined (ACE_PSOS) */ + +#if defined (ACE_PSOS_DIAB_MIPS) +#undef size_t +typedef unsigned int size_t; +#endif + +# if !defined (ACE_LACKS_NEW_H) +# include /**/ +# endif /* ! ACE_LACKS_NEW_H */ + +# if !defined (ACE_PSOS_DIAB_MIPS) && !defined (VXWORKS) +# define ACE_DONT_INCLUDE_ACE_SIGNAL_H +# include /**/ +# undef ACE_DONT_INCLUDE_ACE_SIGNAL_H +# endif /* ! ACE_PSOS_DIAB_MIPS && ! VXWORKS */ + +# if ! defined (ACE_PSOS_DIAB_MIPS) +# include /**/ +# endif /* ! ACE_PSOS_DIAB_MIPS */ +# endif /* ACE_HAS_WINCE */ + +# include /**/ +# include /**/ +# if ! defined (ACE_PSOS_DIAB_MIPS) +# include /**/ +# include /**/ +# endif /* ! ACE_PSOS_DIAB_MIPS */ +# include /**/ + +// This is defined by XOPEN to be a minimum of 16. POSIX.1g +// also defines this value. platform-specific config.h can +// override this if need be. +# if !defined (IOV_MAX) +# define IOV_MAX 16 +# endif /* IOV_MAX */ + +# if !defined (ACE_IOV_MAX) +#define ACE_IOV_MAX IOV_MAX +# endif /* ACE_IOV_MAX */ + +# if defined (ACE_PSOS_SNARFS_HEADER_INFO) + // Header information snarfed from compiler provided header files + // that are not included because there is already an identically + // named file provided with pSOS, which does not have this info + // from compiler supplied stdio.h + extern FILE *fdopen(int, const char *); + extern int getopt(int, char *const *, const char *); + extern char *tempnam(const char *, const char *); + extern "C" int fileno(FILE *); + +// #define fileno(stream) ((stream)->_file) + + // from compiler supplied string.h + extern char *strdup (const char *); + + // from compiler supplied stat.h + extern mode_t umask (mode_t); + extern int mkfifo (const char *, mode_t); + extern int mkdir (const char *, mode_t); + + // from compiler supplied stdlib.h + extern int putenv (char *); + + int isatty (int h); + +# endif /* ACE_PSOS_SNARFS_HEADER_INFO */ + +# if defined (ACE_NEEDS_SCHED_H) +# include /**/ +# endif /* ACE_NEEDS_SCHED_H */ + +#if !defined (ACE_OSTREAM_TYPE) +# if defined (ACE_LACKS_IOSTREAM_TOTALLY) +# define ACE_OSTREAM_TYPE FILE +# else /* ! ACE_LACKS_IOSTREAM_TOTALLY */ +# define ACE_OSTREAM_TYPE ostream +# endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */ +#endif /* ! ACE_OSTREAM_TYPE */ + +#if !defined (ACE_DEFAULT_LOG_STREAM) +# if defined (ACE_LACKS_IOSTREAM_TOTALLY) +# define ACE_DEFAULT_LOG_STREAM 0 +# else /* ! ACE_LACKS_IOSTREAM_TOTALLY */ +# define ACE_DEFAULT_LOG_STREAM (&cerr) +# endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */ +#endif /* ! ACE_DEFAULT_LOG_STREAM */ + +// If the user wants minimum IOStream inclusion, we will just include +// the forward declarations +# if defined (ACE_HAS_MINIMUM_IOSTREAMH_INCLUSION) +// Forward declaration for streams +# include "ace/iosfwd.h" +# else /* ACE_HAS_MINIMUM_IOSTREAMH_INCLUSION */ +// Else they will get all the stream header files +# include "ace/streams.h" +# endif /* ACE_HAS_MINIMUM_IOSTREAMH_INCLUSION */ + +# if !defined (ACE_HAS_WINCE) +# if ! defined (ACE_PSOS_DIAB_MIPS) +# include /**/ +# endif /* ! ACE_PSOS_DIAB_MIPS */ +# endif /* ACE_HAS_WINCE */ + +// This must come after signal.h is #included. +# if defined (SCO) +# define SIGIO SIGPOLL +# include /**/ +# endif /* SCO */ + +# if defined ACE_HAS_BYTESEX_H +# include /**/ +# endif /* ACE_HAS_BYTESEX_H */ +# include "Basic_Types.h" + +/* This should work for linux, solaris 5.6 and above, IRIX, OSF */ +# if defined (ACE_HAS_LLSEEK) || defined (ACE_HAS_LSEEK64) +# if ACE_SIZEOF_LONG == 8 + typedef off_t ACE_LOFF_T; +# elif defined (__sgi) || defined (AIX) || defined (HPUX) \ + || defined (__QNX__) + typedef off64_t ACE_LOFF_T; +# elif defined (__sun) + typedef offset_t ACE_LOFF_T; +# elif defined (WIN32) //Add by Nick Lin -- for win32 llseek + typedef __int64 ACE_LOFF_T; //Add by Nick Lin -- for win32 llseek +# else + typedef loff_t ACE_LOFF_T; +# endif +# endif /* ACE_HAS_LLSEEK || ACE_HAS_LSEEK64 */ + +// Define some helpful constants. +// Not type-safe, and signed. For backward compatibility. +#define ACE_ONE_SECOND_IN_MSECS 1000L +#define ACE_ONE_SECOND_IN_USECS 1000000L +#define ACE_ONE_SECOND_IN_NSECS 1000000000L + +// Type-safe, and unsigned. +static const ACE_UINT32 ACE_U_ONE_SECOND_IN_MSECS = 1000U; +static const ACE_UINT32 ACE_U_ONE_SECOND_IN_USECS = 1000000U; +static const ACE_UINT32 ACE_U_ONE_SECOND_IN_NSECS = 1000000000U; + +# if defined (ACE_HAS_SIG_MACROS) +# undef sigemptyset +# undef sigfillset +# undef sigaddset +# undef sigdelset +# undef sigismember +# endif /* ACE_HAS_SIG_MACROS */ + +// This must come after signal.h is #included. It's to counteract +// the sigemptyset and sigfillset #defines, which only happen +// when __OPTIMIZE__ is #defined (really!) on Linux. +# if defined (linux) && defined (__OPTIMIZE__) +# undef sigemptyset +# undef sigfillset +# endif /* linux && __OPTIMIZE__ */ + +// Prototypes should come after ace/Basic_Types.h since some types may +// be used in the prototypes. + +#if defined (ACE_LACKS_GETPGID_PROTOTYPE) && \ + !defined (_XOPEN_SOURCE) && !defined (_XOPEN_SOURCE_EXTENDED) +extern "C" pid_t getpgid (pid_t pid); +#endif /* ACE_LACKS_GETPGID_PROTOTYPE && + !_XOPEN_SOURCE && !_XOPEN_SOURCE_EXTENDED */ + +#if defined (ACE_LACKS_STRPTIME_PROTOTYPE) && !defined (_XOPEN_SOURCE) +extern "C" char *strptime (const char *s, const char *fmt, struct tm *tp); +#endif /* ACE_LACKS_STRPTIME_PROTOTYPE */ + +#if defined (ACE_LACKS_STRTOK_R_PROTOTYPE) && !defined (_POSIX_SOURCE) +extern "C" char *strtok_r (char *s, const char *delim, char **save_ptr); +#endif /* ACE_LACKS_STRTOK_R_PROTOTYPE */ + +#if !defined (_LARGEFILE64_SOURCE) +# if defined (ACE_LACKS_LSEEK64_PROTOTYPE) && \ + defined (ACE_LACKS_LLSEEK_PROTOTYPE) +# error Define either ACE_LACKS_LSEEK64_PROTOTYPE or ACE_LACKS_LLSEEK_PROTOTYPE, not both! +# elif defined (ACE_LACKS_LSEEK64_PROTOTYPE) +extern "C" ACE_LOFF_T lseek64 (int fd, ACE_LOFF_T offset, int whence); +# elif defined (ACE_LACKS_LLSEEK_PROTOTYPE) +extern "C" ACE_LOFF_T llseek (int fd, ACE_LOFF_T offset, int whence); +# endif +#endif /* _LARGEFILE64_SOURCE */ + +#if defined (ACE_LACKS_PREAD_PROTOTYPE) && (_XOPEN_SOURCE - 0) < 500 +// _XOPEN_SOURCE == 500 Single Unix conformance +// It seems that _XOPEN_SOURCE == 500 means that the prototypes are +// already defined in the system headers. +extern "C" ssize_t pread (int fd, + void *buf, + size_t nbytes, + off_t offset); + +extern "C" ssize_t pwrite (int fd, + const void *buf, + size_t n, + off_t offset); +#endif /* ACE_LACKS_PREAD_PROTOTYPE && (_XOPEN_SOURCE - 0) < 500 */ + +# if defined (ACE_LACKS_UALARM_PROTOTYPE) +extern "C" u_int ualarm (u_int usecs, u_int interval); +# endif /* ACE_LACKS_UALARM_PROTOTYPE */ + +# if defined (ACE_HAS_BROKEN_SENDMSG) +typedef struct msghdr ACE_SENDMSG_TYPE; +# else +typedef const struct msghdr ACE_SENDMSG_TYPE; +# endif /* ACE_HAS_BROKEN_SENDMSG */ + +# if defined (ACE_HAS_BROKEN_RANDR) +// The SunOS 5.4.X version of rand_r is inconsistent with the header +// files... +typedef u_int ACE_RANDR_TYPE; +extern "C" int rand_r (ACE_RANDR_TYPE seed); +# else +# if defined (HPUX_10) +// HP-UX 10.x's stdlib.h (long *) doesn't match that man page (u_int *) +typedef long ACE_RANDR_TYPE; +# else +typedef u_int ACE_RANDR_TYPE; +# endif /* HPUX_10 */ +# endif /* ACE_HAS_BROKEN_RANDR */ + +# if defined (ACE_HAS_UTIME) +# include /**/ +# endif /* ACE_HAS_UTIME */ + +# if !defined (ACE_HAS_MSG) && !defined (SCO) +struct msghdr {}; +# endif /* ACE_HAS_MSG */ + +# if defined (ACE_HAS_MSG) && defined (ACE_LACKS_MSG_ACCRIGHTS) +# if !defined (msg_accrights) +# undef msg_control +# define msg_accrights msg_control +# endif /* ! msg_accrights */ + +# if !defined (msg_accrightslen) +# undef msg_controllen +# define msg_accrightslen msg_controllen +# endif /* ! msg_accrightslen */ +# endif /* ACE_HAS_MSG && ACE_LACKS_MSG_ACCRIGHTS */ + +# if !defined (ACE_HAS_SIG_ATOMIC_T) +typedef int sig_atomic_t; +# endif /* !ACE_HAS_SIG_ATOMIC_T */ + +# if !defined (ACE_HAS_SSIZE_T) +typedef int ssize_t; +# endif /* ACE_HAS_SSIZE_T */ + +# if defined (ACE_HAS_PACE) +# if defined (ACE_HAS_LYNXOS_SIGNALS) +typedef void (*ACE_SignalHandler)(...); +typedef void (*ACE_SignalHandlerV)(...); +# else +typedef pace_sig_pf ACE_SignalHandler; +typedef pace_sig_pf ACE_SignalHandlerV; +# endif /* ACE_HAS_LYNXOS_SIGNALS */ +# elif defined (ACE_HAS_CONSISTENT_SIGNAL_PROTOTYPES) +// Prototypes for both signal() and struct sigaction are consistent.. +# if defined (ACE_HAS_SIG_C_FUNC) +extern "C" { +# endif /* ACE_HAS_SIG_C_FUNC */ +# if !defined (ACE_PSOS) +typedef void (*ACE_SignalHandler)(int); +typedef void (*ACE_SignalHandlerV)(int); +# endif /* !defined (ACE_PSOS) */ +# if defined (ACE_HAS_SIG_C_FUNC) +} +# endif /* ACE_HAS_SIG_C_FUNC */ +# elif defined (ACE_HAS_LYNXOS_SIGNALS) +typedef void (*ACE_SignalHandler)(...); +typedef void (*ACE_SignalHandlerV)(...); +# elif defined (ACE_HAS_TANDEM_SIGNALS) +typedef void (*ACE_SignalHandler)(...); +typedef void (*ACE_SignalHandlerV)(...); +# elif defined (ACE_HAS_IRIX_53_SIGNALS) +typedef void (*ACE_SignalHandler)(...); +typedef void (*ACE_SignalHandlerV)(...); +# elif defined (ACE_HAS_SPARCWORKS_401_SIGNALS) +typedef void (*ACE_SignalHandler)(int, ...); +typedef void (*ACE_SignalHandlerV)(int,...); +# elif defined (ACE_HAS_SUNOS4_SIGNAL_T) +typedef void (*ACE_SignalHandler)(...); +typedef void (*ACE_SignalHandlerV)(...); +# elif defined (ACE_HAS_SVR4_SIGNAL_T) +// SVR4 Signals are inconsistent (e.g., see struct sigaction).. +typedef void (*ACE_SignalHandler)(int); +# if !defined (m88k) /* with SVR4_SIGNAL_T */ +typedef void (*ACE_SignalHandlerV)(void); +# else +typedef void (*ACE_SignalHandlerV)(int); +# endif /* m88k */ /* with SVR4_SIGNAL_T */ +# elif defined (ACE_WIN32) +typedef void (__cdecl *ACE_SignalHandler)(int); +typedef void (__cdecl *ACE_SignalHandlerV)(int); +# elif defined (ACE_HAS_UNIXWARE_SVR4_SIGNAL_T) +typedef void (*ACE_SignalHandler)(int); +typedef void (*ACE_SignalHandlerV)(...); +# else /* This is necessary for some older broken version of cfront */ +# if defined (SIG_PF) +# define ACE_SignalHandler SIG_PF +# else +typedef void (*ACE_SignalHandler)(int); +# endif /* SIG_PF */ +typedef void (*ACE_SignalHandlerV)(...); +# endif /* ACE_HAS_PACE */ + +# if defined (BUFSIZ) +# define ACE_STREAMBUF_SIZE BUFSIZ +# else +# define ACE_STREAMBUF_SIZE 1024 +# endif /* BUFSIZ */ + +# if defined (ACE_WIN32) +// Turn off warnings for /W4 +// To resume any of these warning: #pragma warning(default: 4xxx) +// which should be placed after these defines + +# if !defined (ALL_WARNINGS) && defined(_MSC_VER) && !defined(ghs) && !defined(__MINGW32__) +// #pragma warning(disable: 4101) // unreferenced local variable +# pragma warning(disable: 4127) /* constant expression for TRACE/ASSERT */ +# pragma warning(disable: 4134) /* message map member fxn casts */ +# pragma warning(disable: 4511) /* private copy constructors are good to have */ +# pragma warning(disable: 4512) /* private operator= are good to have */ +# pragma warning(disable: 4514) /* unreferenced inlines are common */ +# pragma warning(disable: 4710) /* private constructors are disallowed */ +# pragma warning(disable: 4705) /* statement has no effect in optimized code */ +// #pragma warning(disable: 4701) // local variable *may* be used without init +// #pragma warning(disable: 4702) // unreachable code caused by optimizations +# pragma warning(disable: 4791) /* loss of debugging info in retail version */ +// #pragma warning(disable: 4204) // non-constant aggregate initializer +# pragma warning(disable: 4275) /* deriving exported class from non-exported */ +# pragma warning(disable: 4251) /* using non-exported as public in exported */ +# pragma warning(disable: 4786) /* identifier was truncated to '255' characters in the browser information */ +# pragma warning(disable: 4097) /* typedef-name used as synonym for class-name */ +# endif /* !ALL_WARNINGS && _MSV_VER && !ghs && !__MINGW32__ */ + +// STRICT type checking in WINDOWS.H enhances type safety for Windows +// programs by using distinct types to represent all the different +// HANDLES in Windows. So for example, STRICT prevents you from +// mistakenly passing an HPEN to a routine expecting an HBITMAP. +// Note that we only use this if we +# if defined (ACE_HAS_STRICT) && (ACE_HAS_STRICT != 0) +# if !defined (STRICT) /* may already be defined */ +# define STRICT +# endif /* !STRICT */ +# endif /* ACE_HAS_STRICT */ + +# if !defined (ACE_HAS_WINCE) +# include /**/ +# endif /* ACE_HAS_WINCE */ + +// Need to work around odd glitches with NT. +# if !defined (ACE_MAX_DEFAULT_PORT) +# define ACE_MAX_DEFAULT_PORT 65535 +# endif /* ACE_MAX_DEFAULT_PORT */ + +// We're on WinNT or Win95 +# define ACE_PLATFORM_A "Win32" +# define ACE_PLATFORM_EXE_SUFFIX_A ".exe" + +// Used for dynamic linking +# if !defined (ACE_DEFAULT_SVC_CONF) +# define ACE_DEFAULT_SVC_CONF ACE_LIB_TEXT (".\\svc.conf") +# endif /* ACE_DEFAULT_SVC_CONF */ + +// The following are #defines and #includes that are specific to +// WIN32. +# define ACE_STDIN GetStdHandle (STD_INPUT_HANDLE) +# define ACE_STDOUT GetStdHandle (STD_OUTPUT_HANDLE) +# define ACE_STDERR GetStdHandle (STD_ERROR_HANDLE) + +// Default semaphore key and mutex name +# if !defined (ACE_DEFAULT_SEM_KEY) +# define ACE_DEFAULT_SEM_KEY "ACE_SEM_KEY" +# endif /* ACE_DEFAULT_SEM_KEY */ + +# define ACE_INVALID_SEM_KEY 0 + +# if defined (ACE_HAS_WINCE) +// @@ WinCE probably doesn't have structural exception support +// But I need to double check to find this out +# define ACE_SEH_TRY if (1) +# define ACE_SEH_EXCEPT(X) while (0) +# define ACE_SEH_FINALLY if (1) +# else +# if !defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) +# define ACE_SEH_TRY if (1) +# define ACE_SEH_EXCEPT(X) while (0) +# define ACE_SEH_FINALLY if (1) +# elif defined(__BORLANDC__) +# if (__BORLANDC__ >= 0x0530) /* Borland C++ Builder 3.0 */ +# define ACE_SEH_TRY try +# define ACE_SEH_EXCEPT(X) __except(X) +# define ACE_SEH_FINALLY __finally +# else +# define ACE_SEH_TRY if (1) +# define ACE_SEH_EXCEPT(X) while (0) +# define ACE_SEH_FINALLY if (1) +# endif +# elif defined (__IBMCPP__) && (__IBMCPP__ >= 400) +# define ACE_SEH_TRY if (1) +# define ACE_SEH_EXCEPT(X) while (0) +# define ACE_SEH_FINALLY if (1) +# else +# define ACE_SEH_TRY __try +# define ACE_SEH_EXCEPT(X) __except(X) +# define ACE_SEH_FINALLY __finally +# endif /* __BORLANDC__ */ +# endif /* ACE_HAS_WINCE */ + +// The "null" device on Win32. +# define ACE_DEV_NULL "nul" + +// Define the pathname separator characters for Win32 (ugh). +# define ACE_DIRECTORY_SEPARATOR_STR_A "\\" +# define ACE_DIRECTORY_SEPARATOR_CHAR_A '\\' +# define ACE_LD_SEARCH_PATH ACE_LIB_TEXT ("PATH") +# define ACE_LD_SEARCH_PATH_SEPARATOR_STR ACE_LIB_TEXT (";") +# define ACE_DLL_SUFFIX ACE_LIB_TEXT (".dll") +# if defined (__MINGW32__) +# define ACE_DLL_PREFIX ACE_LIB_TEXT ("lib") +# else /* __MINGW32__ */ +# define ACE_DLL_PREFIX ACE_LIB_TEXT ("") +# endif /* __MINGW32__ */ + +// This will help until we figure out everything: +# define NFDBITS 32 /* only used in unused functions... */ +// These two may be used for internal flags soon: +# define MAP_PRIVATE 1 +# define MAP_SHARED 2 +# define MAP_FIXED 4 + +# define RUSAGE_SELF 1 + +struct shmaddr { }; +struct msqid_ds {}; + +// Fake the UNIX rusage structure. Perhaps we can add more to this +// later on? +struct rusage +{ + FILETIME ru_utime; + FILETIME ru_stime; +}; + +// MMAP flags +# define PROT_READ PAGE_READONLY +# define PROT_WRITE PAGE_READWRITE +# define PROT_RDWR PAGE_READWRITE +/* If we can find suitable use for these flags, here they are: +PAGE_WRITECOPY +PAGE_EXECUTE +PAGE_EXECUTE_READ +PAGE_EXECUTE_READWRITE +PAGE_EXECUTE_WRITECOPY +PAGE_GUARD +PAGE_NOACCESS +PAGE_NOCACHE */ + +# if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) +# include /**/ +# endif /* ACE_HAS_WINSOCK2 */ + +// error code mapping +# define ETIME ERROR_SEM_TIMEOUT +# define EWOULDBLOCK WSAEWOULDBLOCK +# define EINPROGRESS WSAEINPROGRESS +# define EALREADY WSAEALREADY +# define ENOTSOCK WSAENOTSOCK +# define EDESTADDRREQ WSAEDESTADDRREQ +# define EMSGSIZE WSAEMSGSIZE +# define EPROTOTYPE WSAEPROTOTYPE +# define ENOPROTOOPT WSAENOPROTOOPT +# define EPROTONOSUPPORT WSAEPROTONOSUPPORT +# define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT +# define EOPNOTSUPP WSAEOPNOTSUPP +# define EPFNOSUPPORT WSAEPFNOSUPPORT +# define EAFNOSUPPORT WSAEAFNOSUPPORT +# define EADDRINUSE WSAEADDRINUSE +# define EADDRNOTAVAIL WSAEADDRNOTAVAIL +# define ENETDOWN WSAENETDOWN +# define ENETUNREACH WSAENETUNREACH +# define ENETRESET WSAENETRESET +# define ECONNABORTED WSAECONNABORTED +# define ECONNRESET WSAECONNRESET +# define ENOBUFS WSAENOBUFS +# define EISCONN WSAEISCONN +# define ENOTCONN WSAENOTCONN +# define ESHUTDOWN WSAESHUTDOWN +# define ETOOMANYREFS WSAETOOMANYREFS +# define ETIMEDOUT WSAETIMEDOUT +# define ECONNREFUSED WSAECONNREFUSED +# define ELOOP WSAELOOP +# define EHOSTDOWN WSAEHOSTDOWN +# define EHOSTUNREACH WSAEHOSTUNREACH +# define EPROCLIM WSAEPROCLIM +# define EUSERS WSAEUSERS +# define EDQUOT WSAEDQUOT +# define ESTALE WSAESTALE +# define EREMOTE WSAEREMOTE +// Grrr! These two are already defined by the horrible 'standard' +// library. +// #define ENAMETOOLONG WSAENAMETOOLONG +// #define ENOTEMPTY WSAENOTEMPTY + +# if !defined (ACE_HAS_WINCE) +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# endif /* ACE_HAS_WINCE */ + +# if defined (__BORLANDC__) +# include /**/ +# define _chdir chdir +# define _ftime ftime +# undef _access +# define _access access +# if (__BORLANDC__ <= 0x540) +# define _getcwd getcwd +# define _stat stat +# endif +# define _isatty isatty +# define _umask umask +# define _fstat fstat +# define _stricmp stricmp +# define _strnicmp strnicmp + +# define _timeb timeb + +# define _O_CREAT O_CREAT +# define _O_EXCL O_EXCL +# define _O_TRUNC O_TRUNC + // 0x0800 is used for O_APPEND. 0x08 looks free. +# define _O_TEMPORARY 0x08 /* see fcntl.h */ +# define _O_RDWR O_RDWR +# define _O_WRONLY O_WRONLY +# define _O_RDONLY O_RDONLY +# define _O_APPEND O_APPEND +# define _O_BINARY O_BINARY +# define _O_TEXT O_TEXT +# endif /* __BORLANDC__ */ + +typedef OVERLAPPED ACE_OVERLAPPED; + +typedef DWORD ACE_thread_t; +# if !defined(__MINGW32__) +typedef long pid_t; +# endif /* __MINGW32__ */ +typedef HANDLE ACE_hthread_t; + +#define ACE_INVALID_PID ((pid_t) -1) +# if defined (ACE_HAS_TSS_EMULATION) + typedef DWORD ACE_OS_thread_key_t; + typedef u_int ACE_thread_key_t; +# else /* ! ACE_HAS_TSS_EMULATION */ + typedef DWORD ACE_thread_key_t; +# endif /* ! ACE_HAS_TSS_EMULATION */ + +# if !defined (ACE_LACKS_LONGLONG_T) +// 64-bit quad-word definitions. +typedef unsigned __int64 ACE_QWORD; +typedef unsigned __int64 ACE_hrtime_t; +inline ACE_QWORD ACE_MAKE_QWORD (DWORD lo, DWORD hi) { return ACE_QWORD (lo) | (ACE_QWORD (hi) << 32); } +inline DWORD ACE_LOW_DWORD (ACE_QWORD q) { return (DWORD) q; } +inline DWORD ACE_HIGH_DWORD (ACE_QWORD q) { return (DWORD) (q >> 32); } +# else +// Can't find ANY place that ACE_QWORD is used, but hrtime_t is. +typedef ACE_UINT64 ACE_hrtime_t; +# endif // ACE_LACKS_LONGLONG_T + +// Win32 dummies to help compilation. + +# if !defined (__BORLANDC__) +# if defined (ACE_HAS_PACE) +typedef pace_nlink_t nlink_t; +typedef pace_mode_t mode_t; +typedef pace_uid_t uid_t; +typedef pace_gid_t gid_t; +# else /* !ACE_HAS_PACE */ +typedef DWORD nlink_t; +# if !defined(__MINGW32__) +typedef u_short mode_t; +# endif /* !__MINGW32__ */ +typedef long uid_t; +typedef long gid_t; +# endif /* ACE_HAS_PACE */ +# endif /* __BORLANDC__ */ +typedef char *caddr_t; + +typedef DWORD ACE_exitcode; +# define ACE_SYSCALL_FAILED 0xFFFFFFFF + +// Needed to map calls to NT transparently. +# define MS_ASYNC 0 +# define MS_INVALIDATE 0 + +// Reliance on CRT - I don't really like this. + +# define O_NDELAY 1 +# if !defined (MAXPATHLEN) +# define MAXPATHLEN _MAX_PATH +# endif /* !MAXPATHLEN */ +# define MAXNAMLEN _MAX_FNAME +# define EADDRINUSE WSAEADDRINUSE + +// The ordering of the fields in this struct is important. It has to +// match those in WSABUF. +struct iovec +{ + size_t iov_len; // byte count to read/write + char *iov_base; // data to be read/written + + // WSABUF is a Winsock2-only type. +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + operator WSABUF &(void) { return *((WSABUF *) this); } +#endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */ +}; + +struct msghdr +{ + sockaddr * msg_name; + // optional address + + int msg_namelen; + // size of address + + iovec *msg_iov; + /* scatter/gather array */ + + int msg_iovlen; + // # elements in msg_iov + + caddr_t msg_accrights; + // access rights sent/received + + int msg_accrightslen; +}; + +typedef int ACE_idtype_t; +typedef DWORD ACE_id_t; +# define ACE_SELF (0) +typedef int ACE_pri_t; + +// Dynamic loading-related types - used for dlopen and family. +typedef HINSTANCE ACE_SHLIB_HANDLE; +# define ACE_SHLIB_INVALID_HANDLE 0 +# define ACE_DEFAULT_SHLIB_MODE 0 + +# elif defined (ACE_PSOS) + +typedef ACE_UINT64 ACE_hrtime_t; + +# if defined (ACE_SIGINFO_IS_SIGINFO_T) + typedef struct siginfo siginfo_t; +# endif /* ACE_LACKS_SIGINFO_H */ + +# else /* !defined (ACE_WIN32) && !defined (ACE_PSOS) */ + +# if defined (m88k) +# define RUSAGE_SELF 1 +# endif /* m88k */ + +// Default port is MAX_SHORT. +# define ACE_MAX_DEFAULT_PORT 65535 + +// Default semaphore key +# if !defined (ACE_DEFAULT_SEM_KEY) +# define ACE_DEFAULT_SEM_KEY 1234 +# endif /* ACE_DEFAULT_SEM_KEY */ + +# define ACE_INVALID_SEM_KEY -1 + +// Define the pathname separator characters for UNIX. +# define ACE_DIRECTORY_SEPARATOR_STR_A "/" +# define ACE_DIRECTORY_SEPARATOR_CHAR_A '/' + +// We're some kind of UNIX... +# define ACE_PLATFORM_A "UNIX" +# define ACE_PLATFORM_EXE_SUFFIX_A "" + +# if !defined (ACE_LD_SEARCH_PATH) +# define ACE_LD_SEARCH_PATH "LD_LIBRARY_PATH" +# endif /* ACE_LD_SEARCH_PATH */ +# if !defined (ACE_LD_SEARCH_PATH_SEPARATOR_STR) +# define ACE_LD_SEARCH_PATH_SEPARATOR_STR ":" +# endif /* ACE_LD_SEARCH_PATH_SEPARATOR_STR */ + +# if !defined (ACE_DLL_SUFFIX) +# define ACE_DLL_SUFFIX ".so" +# endif /* ACE_DLL_SUFFIX */ +# if !defined (ACE_DLL_PREFIX) +# define ACE_DLL_PREFIX "lib" +# endif /* ACE_DLL_PREFIX */ + +// Used for dynamic linking. +# if !defined (ACE_DEFAULT_SVC_CONF) +# define ACE_DEFAULT_SVC_CONF ACE_LIB_TEXT ("./svc.conf") +# endif /* ACE_DEFAULT_SVC_CONF */ + +// The following are #defines and #includes that are specific to UNIX. + +# define ACE_STDIN 0 +# define ACE_STDOUT 1 +# define ACE_STDERR 2 + +// Be consistent with Winsock naming +typedef int ACE_exitcode; +# define ACE_INVALID_HANDLE -1 +# define ACE_SYSCALL_FAILED -1 + +# define ACE_SEH_TRY if (1) +# define ACE_SEH_EXCEPT(X) while (0) +# define ACE_SEH_FINALLY if (1) + +# if !defined (ACE_INVALID_PID) +# define ACE_INVALID_PID ((pid_t) -1) +# endif /* ACE_INVALID_PID */ + +// The "null" device on UNIX. +# define ACE_DEV_NULL "/dev/null" + +// Wrapper for NT events on UNIX. +class ACE_OS_Export ACE_event_t +{ + friend class ACE_OS; +protected: + /// Protect critical section. + ACE_mutex_t lock_; + + /// Keeps track of waiters. + ACE_cond_t condition_; + + /// Specifies if this is an auto- or manual-reset event. + int manual_reset_; + + /// "True" if signaled. + int is_signaled_; + + /// Number of waiting threads. + u_long waiting_threads_; +}; + +struct ACE_OVERLAPPED +{ + u_long Internal; + u_long InternalHigh; + u_long Offset; + u_long OffsetHigh; + ACE_HANDLE hEvent; +}; + + +// Add some typedefs and macros to enhance Win32 conformance... +# if !defined (LPSECURITY_ATTRIBUTES) +# define LPSECURITY_ATTRIBUTES int +# endif /* !defined LPSECURITY_ATTRIBUTES */ +# if !defined (GENERIC_READ) +# define GENERIC_READ 0 +# endif /* !defined GENERIC_READ */ +# if !defined (FILE_SHARE_READ) +# define FILE_SHARE_READ 0 +# endif /* !defined FILE_SHARE_READ */ +# if !defined (OPEN_EXISTING) +# define OPEN_EXISTING 0 +# endif /* !defined OPEN_EXISTING */ +# if !defined (FILE_ATTRIBUTE_NORMAL) +# define FILE_ATTRIBUTE_NORMAL 0 +# endif /* !defined FILE_ATTRIBUTE_NORMAL */ +# if !defined (MAXIMUM_WAIT_OBJECTS) +# define MAXIMUM_WAIT_OBJECTS 0 +# endif /* !defined MAXIMUM_WAIT_OBJECTS */ +# if !defined (FILE_FLAG_OVERLAPPED) +# define FILE_FLAG_OVERLAPPED 0 +# endif /* !defined FILE_FLAG_OVERLAPPED */ +# if !defined (FILE_FLAG_SEQUENTIAL_SCAN) +# define FILE_FLAG_SEQUENTIAL_SCAN 0 +# endif /* FILE_FLAG_SEQUENTIAL_SCAN */ + +# if defined (ACE_HAS_BROKEN_IF_HEADER) +struct ifafilt; +# endif /* ACE_HAS_BROKEN_IF_HEADER */ + +# if defined (ACE_HAS_AIX_BROKEN_SOCKET_HEADER) +# undef __cplusplus +# include /**/ +# define __cplusplus +# else +# include /**/ +# endif /* ACE_HAS_AIX_BROKEN_SOCKET_HEADER */ + +extern "C" +{ +# if defined (VXWORKS) + struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* aliases: not used on VxWorks */ + int h_addrtype; /* host address type */ + int h_length; /* address length */ + char **h_addr_list; /* (first, only) address from name server */ +# define h_addr h_addr_list[0] /* the first address */ + }; +# elif defined (ACE_HAS_CYGWIN32_SOCKET_H) +# include /**/ +# else +# if defined (ACE_HAS_STL_QUEUE_CONFLICT) +# define queue _Queue_ +# endif /* ACE_HAS_STL_QUEUE_CONFLICT */ +# include /**/ +# if defined (ACE_HAS_STL_QUEUE_CONFLICT) +# undef queue +# endif /* ACE_HAS_STL_QUEUE_CONFLICT */ +# endif /* VXWORKS */ + + +// This part if to avoid STL name conflict with the map structure +// in net/if.h. +# if defined (ACE_HAS_STL_MAP_CONFLICT) +# define map _Resource_Allocation_Map_ +# endif /* ACE_HAS_STL_MAP_CONFLICT */ +# include /**/ +# if defined (ACE_HAS_STL_MAP_CONFLICT) +# undef map +# endif /* ACE_HAS_STL_MAP_CONFLICT */ + +# if defined (ACE_HAS_STL_QUEUE_CONFLICT) +# define queue _Queue_ +# endif /* ACE_HAS_STL_QUEUE_CONFLICT */ +# include /**/ +# if defined (ACE_HAS_STL_QUEUE_CONFLICT) +# undef queue +# endif /* ACE_HAS_STL_QUEUE_CONFLICT */ + +# if defined (VXWORKS) + // Work around a lack of ANSI prototypes for these functions on VxWorks. + unsigned long inet_addr (const char *); + char *inet_ntoa (const struct in_addr); + struct in_addr inet_makeaddr (const int, const int); + unsigned long inet_network (const char *); +# else /* ! VXWORKS */ +# include /**/ +# endif /* ! VXWORKS */ +} +# if !defined (ACE_LACKS_TCP_H) +# if defined(ACE_HAS_CONFLICTING_XTI_MACROS) +# if defined(TCP_NODELAY) +# undef TCP_NODELAY +# endif +# if defined(TCP_MAXSEG) +# undef TCP_MAXSEG +# endif +# endif +# include /**/ +# endif /* ACE_LACKS_TCP_H */ + +# if defined (__Lynx__) +# ifndef howmany +# define howmany(x, y) (((x)+((y)-1))/(y)) +# endif /* howmany */ +# endif /* __Lynx__ */ + +# if defined (CHORUS) +# include /**/ +# if !defined(CHORUS_4) +# include /**/ +# else +# include /**/ +# endif +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +extern_C int getgid __((void)); +extern_C int getuid __((void)); +extern_C char* getcwd __((char* buf, size_t size)); +extern_C int pipe __((int* fildes)); +extern_C int gethostname __((char*, size_t)); + +// This must come after limits.h is included +# define MAXPATHLEN _POSIX_PATH_MAX + +# if !defined(CHORUS_4) +typedef cx_fd_mask fd_mask; +typedef void (*__sighandler_t)(int); // keep Signal compilation happy +# endif +# ifndef howmany +# define howmany(x, y) (((x)+((y)-1))/(y)) +# endif /* howmany */ +# elif defined (CYGWIN32) +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# elif defined (__QNX__) +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ + // sets O_NDELAY +# include /**/ +# include /**/ /* for NBBY */ + typedef long fd_mask; +# if !defined (NFDBITS) +# define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ +# endif /* ! NFDBITS */ +# if !defined (howmany) +# define howmany(x, y) (((x)+((y)-1))/(y)) +# endif /* ! howmany */ +# elif defined(__rtems__) +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ + +extern "C" +{ + int select (int n, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, const struct timeval *timeout); +}; +# elif ! defined (VXWORKS) +# include /**/ +# include /**/ +# if !defined(ACE_LACKS_SYSV_SHMEM) +// No reason to #include this if the platform lacks support for SHMEM +# include /**/ +# endif /* ACE_LACKS_SYSV_SHMEM */ +# if ! defined (__MACOSX__) +# include /**/ +# endif /* ! defined (__MACOSX__) */ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# endif /* ! VXWORKS */ +# include /**/ + +// IRIX5 defines bzero() in this odd file... +# if defined (ACE_HAS_BSTRING) +# include /**/ +# endif /* ACE_HAS_BSTRING */ + +// AIX defines bzero() in this odd file... +# if defined (ACE_HAS_STRINGS) +# include /**/ +# endif /* ACE_HAS_STRINGS */ + +# if defined (ACE_HAS_TERM_IOCTLS) +# if defined (__QNX__) +# include /**/ +# else /* ! __QNX__ */ +# include /**/ +# endif /* ! __QNX__ */ +# if defined (HPUX) +# include /**/ +# endif /* HPUX */ +# endif /* ACE_HAS_TERM_IOCTLS */ + +#if !defined (VMIN) +#define ACE_VMIN 4 +#else +#define ACE_VMIN VMIN +#endif /* VMIN */ + +#if !defined (VTIME) +#define ACE_VTIME 5 +#else +#define ACE_VTIME VTIME +#endif /* VTIME */ + +# if defined (ACE_HAS_AIO_CALLS) +# include /**/ +# endif /* ACE_HAS_AIO_CALLS */ + +# if !defined (ACE_LACKS_PARAM_H) +# include /**/ +# endif /* ACE_LACKS_PARAM_H */ + +# if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS) && !defined (VXWORKS) +# include /**/ +# endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */ + +# if defined (ACE_HAS_SIGINFO_T) +# if !defined (ACE_LACKS_SIGINFO_H) +# if defined (__QNX__) +# include /**/ +# elif defined(__rtems__) +# include /**/ +# else /* ! __QNX__ */ +# include /**/ +# endif /* ! __QNX__ */ +# endif /* ACE_LACKS_SIGINFO_H */ +# if !defined (ACE_LACKS_UCONTEXT_H) +# include /**/ +# endif /* ACE_LACKS_UCONTEXT_H */ +# endif /* ACE_HAS_SIGINFO_T */ + +# if defined (ACE_HAS_POLL) +# include /**/ +# endif /* ACE_HAS_POLL */ + +# if defined (ACE_HAS_STREAMS) +# if defined (AIX) +# if !defined (_XOPEN_EXTENDED_SOURCE) +# define _XOPEN_EXTENDED_SOURCE +# endif /* !_XOPEN_EXTENDED_SOURCE */ +# include /**/ +# undef _XOPEN_EXTENDED_SOURCE +# else +# include /**/ +# endif /* AIX */ +# endif /* ACE_HAS_STREAMS */ + +# if defined (DIGITAL_UNIX) + // sigwait is yet another macro on Digital UNIX 4.0, just causing + // trouble when introducing member functions with the same name. + // Thanks to Thilo Kielmann" for + // this fix. +# if defined (__DECCXX_VER) +# undef sigwait + // cxx on Digital Unix 4.0 needs this declaration. With it, + // <::_Psigwait> works with cxx -pthread. g++ does _not_ need + // it. + extern "C" int _Psigwait __((const sigset_t *set, int *sig)); +# elif defined (__KCC) +# undef sigwait + inline int sigwait (const sigset_t* set, int* sig) + { return _Psigwait (set, sig); } +# endif /* __DECCXX_VER */ +# elif !defined (ACE_HAS_SIGWAIT) +# if defined(__rtems__) + extern "C" int sigwait (const sigset_t *set, int *sig); +# else + extern "C" int sigwait (sigset_t *set); +# endif /* __rtems__ */ +# endif /* ! DIGITAL_UNIX && ! ACE_HAS_SIGWAIT */ + +# if defined (ACE_HAS_SELECT_H) +# include /**/ +# endif /* ACE_HAS_SELECT_H */ + +# if defined (ACE_HAS_ALLOCA_H) +# include /**/ +# endif /* ACE_HAS_ALLOCA_H */ + +/* Set the proper handle type for dynamically-loaded libraries. */ +/* Also define a default 'mode' for loading a library - the names and values */ +/* differ between OSes, so if you write code that uses the mode, be careful */ +/* of the platform differences. */ +# if defined (ACE_HAS_SVR4_DYNAMIC_LINKING) +# if defined (ACE_HAS_DLFCN_H_BROKEN_EXTERN_C) +extern "C" { +# endif /* ACE_HAS_DLFCN_H_BROKEN_EXTERN_C */ +# include /**/ +# if defined (ACE_HAS_DLFCN_H_BROKEN_EXTERN_C) +} +# endif /* ACE_HAS_DLFCN_H_BROKEN_EXTERN_C */ + typedef void *ACE_SHLIB_HANDLE; +# define ACE_SHLIB_INVALID_HANDLE 0 +# if defined (__KCC) && defined(RTLD_GROUP) && defined(RTLD_NODELETE) +# define ACE_DEFAULT_SHLIB_MODE RTLD_LAZY | RTLD_GROUP | RTLD_NODELETE +# else +# define ACE_DEFAULT_SHLIB_MODE RTLD_LAZY +# endif /* KCC */ +# elif defined (__hpux) +# if defined(__GNUC__) || __cplusplus >= 199707L +# include /**/ +# else +# include /**/ +# endif /* (g++ || HP aC++) vs. HP C++ */ + typedef shl_t ACE_SHLIB_HANDLE; +# define ACE_SHLIB_INVALID_HANDLE 0 +# define ACE_DEFAULT_SHLIB_MODE BIND_DEFERRED +# else + typedef void *ACE_SHLIB_HANDLE; +# define ACE_SHLIB_INVALID_HANDLE 0 +# define ACE_DEFAULT_SHLIB_MODE RTLD_LAZY + +# endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */ + +#if !defined (RTLD_LAZY) +#define RTLD_LAZY 1 +#endif /* !RTLD_LAZY */ + +#if !defined (RTLD_NOW) +#define RTLD_NOW 2 +#endif /* !RTLD_NOW */ + +#if !defined (RTLD_GLOBAL) +#define RTLD_GLOBAL 3 +#endif /* !RTLD_GLOBAL */ + +# if defined (ACE_HAS_SOCKIO_H) +# include /**/ +# endif /* ACE_HAS_SOCKIO_ */ + +// There must be a better way to do this... +# if !defined (RLIMIT_NOFILE) +# if defined (linux) || defined (AIX) || defined (SCO) +# if defined (RLIMIT_OFILE) +# define RLIMIT_NOFILE RLIMIT_OFILE +# else +# define RLIMIT_NOFILE 200 +# endif /* RLIMIT_OFILE */ +# endif /* defined (linux) || defined (AIX) || defined (SCO) */ +# endif /* RLIMIT_NOFILE */ + +# if defined (ACE_LACKS_MMAP) +# define PROT_READ 0 +# define PROT_WRITE 0 +# define PROT_EXEC 0 +# define PROT_NONE 0 +# define PROT_RDWR 0 +# define MAP_PRIVATE 0 +# define MAP_SHARED 0 +# define MAP_FIXED 0 +# endif /* ACE_LACKS_MMAP */ + +// Fixes a problem with HP/UX. +# if defined (ACE_HAS_BROKEN_MMAP_H) +extern "C" +{ +# include /**/ +} +# elif !defined (ACE_LACKS_MMAP) +# include /**/ +# endif /* ACE_HAS_BROKEN_MMAP_H */ + +// OSF1 has problems with sys/msg.h and C++... +# if defined (ACE_HAS_BROKEN_MSG_H) +# define _KERNEL +# endif /* ACE_HAS_BROKEN_MSG_H */ +# if !defined (ACE_LACKS_SYSV_MSG_H) +# include /**/ +# endif /* ACE_LACKS_SYSV_MSG_H */ +# if defined (ACE_HAS_BROKEN_MSG_H) +# undef _KERNEL +# endif /* ACE_HAS_BROKEN_MSG_H */ + +# if defined (ACE_LACKS_SYSV_MSQ_PROTOS) +extern "C" +{ + int msgget (key_t, int); + int msgrcv (int, void *, size_t, long, int); + int msgsnd (int, const void *, size_t, int); + int msgctl (int, int, struct msqid_ds *); +} +# endif /* ACE_LACKS_SYSV_MSQ_PROTOS */ + +# if defined (ACE_HAS_PRIOCNTL) +# include /**/ +# endif /* ACE_HAS_PRIOCNTL */ + +# if defined (ACE_HAS_IDTYPE_T) + typedef idtype_t ACE_idtype_t; +# else + typedef int ACE_idtype_t; +# endif /* ACE_HAS_IDTYPE_T */ + +# if defined (ACE_HAS_STHREADS) || defined (DIGITAL_UNIX) +# if defined (ACE_LACKS_PRI_T) + typedef int pri_t; +# endif /* ACE_LACKS_PRI_T */ + typedef id_t ACE_id_t; +# define ACE_SELF P_MYID + typedef pri_t ACE_pri_t; +# else /* ! ACE_HAS_STHREADS && ! DIGITAL_UNIX */ + typedef long ACE_id_t; +# define ACE_SELF (-1) + typedef short ACE_pri_t; +# endif /* ! ACE_HAS_STHREADS && ! DIGITAL_UNIX */ + +# if defined (ACE_HAS_HI_RES_TIMER) && !defined (ACE_LACKS_LONGLONG_T) + /* hrtime_t is defined on systems (Suns) with ACE_HAS_HI_RES_TIMER */ + typedef hrtime_t ACE_hrtime_t; +# else /* ! ACE_HAS_HI_RES_TIMER || ACE_LACKS_LONGLONG_T */ + typedef ACE_UINT64 ACE_hrtime_t; +# endif /* ! ACE_HAS_HI_RES_TIMER || ACE_LACKS_LONGLONG_T */ + +# endif /* !defined (ACE_WIN32) && !defined (ACE_PSOS) */ + +// Define the Wide character and normal versions of some of the string macros +# if defined (ACE_HAS_WCHAR) +# define ACE_DIRECTORY_SEPARATOR_STR_W ACE_TEXT_WIDE(ACE_DIRECTORY_SEPARATOR_STR_A) +# define ACE_DIRECTORY_SEPARATOR_CHAR_W ACE_TEXT_WIDE(ACE_DIRECTORY_SEPARATOR_CHAR_A) +# define ACE_PLATFORM_W ACE_TEXT_WIDE(ACE_PLATFORM_A) +# define ACE_PLATFORM_EXE_SUFFIX_W ACE_TEXT_WIDE(ACE_PLATFORM_EXE_SUFFIX_A) +# endif /* ACE_HAS_WCHAR */ + +# define ACE_DIRECTORY_SEPARATOR_STR ACE_LIB_TEXT (ACE_DIRECTORY_SEPARATOR_STR_A) +# define ACE_DIRECTORY_SEPARATOR_CHAR ACE_LIB_TEXT (ACE_DIRECTORY_SEPARATOR_CHAR_A) +# define ACE_PLATFORM ACE_LIB_TEXT (ACE_PLATFORM_A) +# define ACE_PLATFORM_EXE_SUFFIX ACE_LIB_TEXT (ACE_PLATFORM_EXE_SUFFIX_A) + +// Theses defines are used by the ACE Name Server. +# if !defined (ACE_DEFAULT_LOCALNAME_A) +# define ACE_DEFAULT_LOCALNAME_A "localnames" +# endif /* ACE_DEFAULT_LOCALNAME_A */ +# if !defined (ACE_DEFAULT_GLOBALNAME_A) +# define ACE_DEFAULT_GLOBALNAME_A "globalnames" +# endif /* ACE_DEFAULT_GLOBALNAME_A */ + +// ACE_DEFAULT_NAMESPACE_DIR is for legacy mode apps. A better +// way of doing this is something like ACE_Lib_Find::get_temp_dir, since +// this directory may not exist +# if defined (ACE_LEGACY_MODE) +# if defined (ACE_WIN32) +# define ACE_DEFAULT_NAMESPACE_DIR_A "C:\\temp" +# else /* ACE_WIN32 */ +# define ACE_DEFAULT_NAMESPACE_DIR_A "/tmp" +# endif /* ACE_WIN32 */ +# if defined (ACE_HAS_WCHAR) +# define ACE_DEFAULT_NAMESPACE_DIR_W ACE_TEXT_WIDE(ACE_DEFAULT_NAMESPACE_DIR_A) +# endif /* ACE_HAS_WCHAR */ +# define ACE_DEFAULT_NAMESPACE_DIR ACE_LIB_TEXT(ACE_DEFAULT_NAMESPACE_DIR_A) +# endif /* ACE_LEGACY_MODE */ + +# if defined (ACE_HAS_WCHAR) +# define ACE_DEFAULT_LOCALNAME_W ACE_TEXT_WIDE(ACE_DEFAULT_LOCALNAME_A) +# define ACE_DEFAULT_GLOBALNAME_W ACE_TEXT_WIDE(ACE_DEFAULT_GLOBALNAME_A) +# endif /* ACE_HAS_WCHAR */ + +# define ACE_DEFAULT_LOCALNAME ACE_LIB_TEXT (ACE_DEFAULT_LOCALNAME_A) +# define ACE_DEFAULT_GLOBALNAME ACE_LIB_TEXT (ACE_DEFAULT_GLOBALNAME_A) + +// defined Win32 specific macros for UNIX platforms +# if !defined (O_BINARY) +# define O_BINARY 0 +# endif /* O_BINARY */ +# if !defined (_O_BINARY) +# define _O_BINARY O_BINARY +# endif /* _O_BINARY */ +# if !defined (O_TEXT) +# define O_TEXT 0 +# endif /* O_TEXT */ +# if !defined (_O_TEXT) +# define _O_TEXT O_TEXT +# endif /* _O_TEXT */ +# if !defined (O_RAW) +# define O_RAW 0 +# endif /* O_RAW */ +# if !defined (_O_RAW) +# define _O_RAW O_RAW +# endif /* _O_RAW */ + +# if !defined (ACE_DEFAULT_SYNCH_TYPE) +# define ACE_DEFAULT_SYNCH_TYPE USYNC_THREAD +# endif /* ! ACE_DEFAULT_SYNCH_TYPE */ + +# if !defined (ACE_MAP_PRIVATE) +# define ACE_MAP_PRIVATE MAP_PRIVATE +# endif /* ! ACE_MAP_PRIVATE */ + +# if !defined (ACE_MAP_SHARED) +# define ACE_MAP_SHARED MAP_SHARED +# endif /* ! ACE_MAP_SHARED */ + +# if !defined (ACE_MAP_FIXED) +# define ACE_MAP_FIXED MAP_FIXED +# endif /* ! ACE_MAP_FIXED */ + +#if defined (ACE_LACKS_UTSNAME_T) +# if !defined (SYS_NMLN) +# define SYS_NMLN 257 +# endif /* SYS_NMLN */ +# if !defined (_SYS_NMLN) +# define _SYS_NMLN SYS_NMLN +# endif /* _SYS_NMLN */ +struct ACE_utsname +{ + ACE_TCHAR sysname[_SYS_NMLN]; + ACE_TCHAR nodename[_SYS_NMLN]; + ACE_TCHAR release[_SYS_NMLN]; + ACE_TCHAR version[_SYS_NMLN]; + ACE_TCHAR machine[_SYS_NMLN]; +}; +# else +# include /**/ +typedef struct utsname ACE_utsname; +# endif /* ACE_LACKS_UTSNAME_T */ + +// Increase the range of "address families". Please note that this +// must appear _after_ the include of sys/socket.h, for the AF_FILE +// definition on Linux/glibc2. +#if !defined (AF_ANY) +# define AF_ANY (-1) +#endif /* AF_ANY */ + +# define AF_SPIPE (AF_MAX + 1) +# if !defined (AF_FILE) +# define AF_FILE (AF_MAX + 2) +# endif /* ! AF_FILE */ +# define AF_DEV (AF_MAX + 3) +# define AF_UPIPE (AF_SPIPE) + +# if defined (ACE_SELECT_USES_INT) +typedef int ACE_FD_SET_TYPE; +# else +typedef fd_set ACE_FD_SET_TYPE; +# endif /* ACE_SELECT_USES_INT */ + +# if !defined (MAXNAMELEN) +# if defined (FILENAME_MAX) +# define MAXNAMELEN FILENAME_MAX +# else +# define MAXNAMELEN 256 +# endif /* FILENAME_MAX */ +# endif /* MAXNAMELEN */ + +# if !defined(MAXHOSTNAMELEN) +# define MAXHOSTNAMELEN 256 +# endif /* MAXHOSTNAMELEN */ + +// Define INET loopback address constant if it hasn't been defined +// Dotted Decimal 127.0.0.1 == Hexidecimal 0x7f000001 +# if !defined (INADDR_LOOPBACK) +# define INADDR_LOOPBACK ((ACE_UINT32) 0x7f000001) +# endif /* INADDR_LOOPBACK */ + +// The INADDR_NONE address is generally 255.255.255.255. +# if !defined (INADDR_NONE) +# define INADDR_NONE ((ACE_UINT32) 0xffffffff) +# endif /* INADDR_NONE */ + +// Define INET string length constants if they haven't been defined +// +// for IPv4 dotted-decimal +# if !defined (INET_ADDRSTRLEN) +# define INET_ADDRSTRLEN 16 +# endif /* INET_ADDRSTRLEN */ +// +// for IPv6 hex string +# if !defined (INET6_ADDRSTRLEN) +# define INET6_ADDRSTRLEN 46 +# endif /* INET6_ADDRSTRLEN */ + +#if defined (ACE_HAS_IPV6) + +# if defined (ACE_USES_IPV4_IPV6_MIGRATION) +# define ACE_ADDRESS_FAMILY_INET AF_UNSPEC +# define ACE_PROTOCOL_FAMILY_INET PF_UNSPEC +# else +# define ACE_ADDRESS_FAMILY_INET AF_INET6 +# define ACE_PROTOCOL_FAMILY_INET PF_INET6 +# endif /* ACE_USES_IPV4_IPV6_MIGRATION */ + +#else +# define ACE_ADDRESS_FAMILY_INET AF_INET +# define ACE_PROTOCOL_FAMILY_INET PF_INET +#endif + +# if defined (ACE_LACKS_SIGSET) +# if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) +typedef pace_sigset_t sigset_t; +# elif !defined(__MINGW32__) +typedef u_int sigset_t; +# endif /* !ACE_HAS_PACE && !__MINGW32__*/ +# endif /* ACE_LACKS_SIGSET */ + +# if defined (ACE_LACKS_SIGACTION) +struct sigaction +{ + int sa_flags; + ACE_SignalHandlerV sa_handler; + sigset_t sa_mask; +}; +# endif /* ACE_LACKS_SIGACTION */ + +# if !defined (SIGHUP) +# define SIGHUP 0 +# endif /* SIGHUP */ + +# if !defined (SIGINT) +# define SIGINT 0 +# endif /* SIGINT */ + +# if !defined (SIGSEGV) +# define SIGSEGV 0 +# endif /* SIGSEGV */ + +# if !defined (SIGIO) +# define SIGIO 0 +# endif /* SIGSEGV */ + +# if !defined (SIGUSR1) +# define SIGUSR1 0 +# endif /* SIGUSR1 */ + +# if !defined (SIGUSR2) +# define SIGUSR2 0 +# endif /* SIGUSR2 */ + +# if !defined (SIGCHLD) +# define SIGCHLD 0 +# endif /* SIGCHLD */ + +# if !defined (SIGCLD) +# define SIGCLD SIGCHLD +# endif /* SIGCLD */ + +# if !defined (SIGQUIT) +# define SIGQUIT 0 +# endif /* SIGQUIT */ + +# if !defined (SIGPIPE) +# define SIGPIPE 0 +# endif /* SIGPIPE */ + +# if !defined (SIGALRM) +# define SIGALRM 0 +# endif /* SIGALRM */ + +# if !defined (SIG_DFL) +# if defined (ACE_PSOS_DIAB_MIPS) || defined (ACE_PSOS_DIAB_PPC) +# define SIG_DFL ((void *) 0) +# else +# define SIG_DFL ((__sighandler_t) 0) +# endif +# endif /* SIG_DFL */ + +# if !defined (SIG_IGN) +# if defined (ACE_PSOS_DIAB_MIPS) || defined (ACE_PSOS_DIAB_PPC) +# define SIG_IGN ((void *) 1) /* ignore signal */ +# else +# define SIG_IGN ((__sighandler_t) 1) /* ignore signal */ +# endif +# endif /* SIG_IGN */ + +# if !defined (SIG_ERR) +# if defined (ACE_PSOS_DIAB_MIPS) || defined (ACE_PSOS_DIAB_PPC) +# define SIG_ERR ((void *) -1) /* error return from signal */ +# else +# define SIG_ERR ((__sighandler_t) -1) /* error return from signal */ +# endif +# endif /* SIG_ERR */ + +# if !defined (O_NONBLOCK) +# define O_NONBLOCK 1 +# endif /* O_NONBLOCK */ + +# if !defined (SIG_BLOCK) +# define SIG_BLOCK 1 +# endif /* SIG_BLOCK */ + +# if !defined (SIG_UNBLOCK) +# define SIG_UNBLOCK 2 +# endif /* SIG_UNBLOCK */ + +# if !defined (SIG_SETMASK) +# define SIG_SETMASK 3 +# endif /* SIG_SETMASK */ + +# if !defined (IPC_CREAT) +# define IPC_CREAT 0 +# endif /* IPC_CREAT */ + +# if !defined (IPC_NOWAIT) +# define IPC_NOWAIT 0 +# endif /* IPC_NOWAIT */ + +# if !defined (IPC_RMID) +# define IPC_RMID 0 +# endif /* IPC_RMID */ + +# if !defined (IPC_EXCL) +# define IPC_EXCL 0 +# endif /* IPC_EXCL */ + +# if !defined (IP_DROP_MEMBERSHIP) +# define IP_DROP_MEMBERSHIP 0 +# endif /* IP_DROP_MEMBERSHIP */ + +# if !defined (IP_ADD_MEMBERSHIP) +# define IP_ADD_MEMBERSHIP 0 +# define ACE_LACKS_IP_ADD_MEMBERSHIP +# endif /* IP_ADD_MEMBERSHIP */ + +# if !defined (IP_DEFAULT_MULTICAST_TTL) +# define IP_DEFAULT_MULTICAST_TTL 0 +# endif /* IP_DEFAULT_MULTICAST_TTL */ + +# if !defined (IP_DEFAULT_MULTICAST_LOOP) +# define IP_DEFAULT_MULTICAST_LOOP 0 +# endif /* IP_DEFAULT_MULTICAST_LOOP */ + +# if !defined (IP_MULTICAST_IF) +# define IP_MULTICAST_IF 0 +#endif /* IP_MULTICAST_IF */ + +# if !defined (IP_MULTICAST_TTL) +# define IP_MULTICAST_TTL 1 +#endif /* IP_MULTICAST_TTL */ + +# if !defined (IP_MAX_MEMBERSHIPS) +# define IP_MAX_MEMBERSHIPS 0 +# endif /* IP_MAX_MEMBERSHIP */ + +# if !defined (SIOCGIFBRDADDR) +# define SIOCGIFBRDADDR 0 +# endif /* SIOCGIFBRDADDR */ + +# if !defined (SIOCGIFADDR) +# define SIOCGIFADDR 0 +# endif /* SIOCGIFADDR */ + +# if !defined (IPC_PRIVATE) +# define IPC_PRIVATE ACE_INVALID_SEM_KEY +# endif /* IPC_PRIVATE */ + +# if !defined (IPC_STAT) +# define IPC_STAT 0 +# endif /* IPC_STAT */ + +# if !defined (GETVAL) +# define GETVAL 0 +# endif /* GETVAL */ + +# if !defined (F_GETFL) +# define F_GETFL 0 +# endif /* F_GETFL */ + +# if !defined (SETVAL) +# define SETVAL 0 +# endif /* SETVAL */ + +# if !defined (GETALL) +# define GETALL 0 +# endif /* GETALL */ + +# if !defined (SETALL) +# define SETALL 0 +# endif /* SETALL */ + +# if !defined (SEM_UNDO) +# define SEM_UNDO 0 +# endif /* SEM_UNDO */ + +# if defined (__Lynx__) + // LynxOS Neutrino sets NSIG to the highest-numbered signal. +# define ACE_NSIG (NSIG + 1) +# elif defined (__rtems__) +# define ACE_NSIG (SIGRTMAX) +# else + // All other platforms set NSIG to one greater than the + // highest-numbered signal. +# define ACE_NSIG NSIG +# endif /* __Lynx__ */ + +# if !defined (R_OK) +# define R_OK 04 /* Test for Read permission. */ +# endif /* R_OK */ + +# if !defined (W_OK) +# define W_OK 02 /* Test for Write permission. */ +# endif /* W_OK */ + +# if !defined (X_OK) +# define X_OK 01 /* Test for eXecute permission. */ +# endif /* X_OK */ + +# if !defined (F_OK) +# define F_OK 0 /* Test for existence of File. */ +# endif /* F_OK */ + +# if !defined (ESUCCESS) +# define ESUCCESS 0 +# endif /* !ESUCCESS */ + +# if !defined (EIDRM) +# define EIDRM 0 +# endif /* !EIDRM */ + +# if !defined (ENFILE) +# define ENFILE EMFILE /* No more socket descriptors are available. */ +# endif /* !ENOSYS */ + +# if !defined (ECOMM) + // Not the same, but ECONNABORTED is provided on NT. +# define ECOMM ECONNABORTED +# endif /* ECOMM */ + +# if !defined (WNOHANG) +# define WNOHANG 0100 +# endif /* !WNOHANG */ + +# if !defined (EDEADLK) +# define EDEADLK 1000 /* Some large number.... */ +# endif /* !EDEADLK */ + +# if !defined (MS_SYNC) +# define MS_SYNC 0x0 +# endif /* !MS_SYNC */ + +# if !defined (PIPE_BUF) +# define PIPE_BUF 5120 +# endif /* PIPE_BUF */ + +# if !defined (PROT_RDWR) +# define PROT_RDWR (PROT_READ|PROT_WRITE) +# endif /* PROT_RDWR */ + +# if defined (ACE_HAS_POSIX_NONBLOCK) +# define ACE_NONBLOCK O_NONBLOCK +# else +# define ACE_NONBLOCK O_NDELAY +# endif /* ACE_HAS_POSIX_NONBLOCK */ + +// These are used by the and +// methods. They must be unique and cannot +// conflict with the value of . We make the numbers +// negative here so they won't conflict with other values like SIGIO, +// etc. +# define ACE_SIGIO -1 +# define ACE_SIGURG -2 +# define ACE_CLOEXEC -3 + +# define LOCALNAME 0 +# define REMOTENAME 1 + +# if !defined (ETIMEDOUT) && defined (ETIME) +# define ETIMEDOUT ETIME +# endif /* ETIMEDOUT */ + +# if !defined (ETIME) && defined (ETIMEDOUT) +# define ETIME ETIMEDOUT +# endif /* ETIMED */ + +# if !defined (EBUSY) +# define EBUSY ETIME +# endif /* EBUSY */ + +# if !defined (_SC_TIMER_MAX) +# define _SC_TIMER_MAX 44 +# endif /* _SC_TIMER_MAX */ + +// Default number of s supported by +// . +# if !defined (ACE_DEFAULT_TIMERS) +# define ACE_DEFAULT_TIMERS _SC_TIMER_MAX +# endif /* ACE_DEFAULT_TIMERS */ + +# if defined (ACE_HAS_STRUCT_NETDB_DATA) +typedef char ACE_HOSTENT_DATA[sizeof(struct hostent_data)]; +typedef char ACE_SERVENT_DATA[sizeof(struct servent_data)]; +typedef char ACE_PROTOENT_DATA[sizeof(struct protoent_data)]; +# else +# if !defined ACE_HOSTENT_DATA_SIZE +# define ACE_HOSTENT_DATA_SIZE (4*1024) +# endif /*ACE_HOSTENT_DATA_SIZE */ +# if !defined ACE_SERVENT_DATA_SIZE +# define ACE_SERVENT_DATA_SIZE (4*1024) +# endif /*ACE_SERVENT_DATA_SIZE */ +# if !defined ACE_PROTOENT_DATA_SIZE +# define ACE_PROTOENT_DATA_SIZE (2*1024) +# endif /*ACE_PROTOENT_DATA_SIZE */ +typedef char ACE_HOSTENT_DATA[ACE_HOSTENT_DATA_SIZE]; +typedef char ACE_SERVENT_DATA[ACE_SERVENT_DATA_SIZE]; +typedef char ACE_PROTOENT_DATA[ACE_PROTOENT_DATA_SIZE]; +# endif /* ACE_HAS_STRUCT_NETDB_DATA */ + +# if !defined (ACE_HAS_SEMUN) || (defined (__GLIBC__) && defined (_SEM_SEMUN_UNDEFINED)) +union semun +{ + int val; // value for SETVAL + struct semid_ds *buf; // buffer for IPC_STAT & IPC_SET + u_short *array; // array for GETALL & SETALL +}; +# endif /* !ACE_HAS_SEMUN || (defined (__GLIBC__) && defined (_SEM_SEMUN_UNDEFINED)) */ + +// Max size of an ACE Log Record data buffer. This can be reset in +// the config.h file if you'd like to increase or decrease the size. +# if !defined (ACE_MAXLOGMSGLEN) +# define ACE_MAXLOGMSGLEN 4 * 1024 +# endif /* ACE_MAXLOGMSGLEN */ + +// Max size of an ACE Token. +# define ACE_MAXTOKENNAMELEN 40 + +// Max size of an ACE Token client ID. +# define ACE_MAXCLIENTIDLEN MAXHOSTNAMELEN + 20 + +// Create some useful typedefs. + +typedef const char **SYS_SIGLIST; + +// This is for C++ static methods. +# if defined (VXWORKS) +typedef int ACE_THR_FUNC_INTERNAL_RETURN_TYPE; +typedef FUNCPTR ACE_THR_FUNC_INTERNAL; // where typedef int (*FUNCPTR) (...) +# elif defined (ACE_PSOS) +typedef void (*ACE_THR_FUNC_INTERNAL)(void *); +# else +typedef ACE_THR_FUNC ACE_THR_FUNC_INTERNAL; +# endif /* VXWORKS */ + +extern "C" { +typedef void (*ACE_THR_C_DEST)(void *); +} +typedef void (*ACE_THR_DEST)(void *); + +# if !defined (MAP_FAILED) || defined (ACE_HAS_BROKEN_MAP_FAILED) +# undef MAP_FAILED +# define MAP_FAILED ((void *) -1) +# elif defined (ACE_HAS_LONG_MAP_FAILED) +# undef MAP_FAILED +# define MAP_FAILED ((void *) -1L) +# endif /* !MAP_FAILED || ACE_HAS_BROKEN_MAP_FAILED */ + +# if defined (ACE_HAS_CHARPTR_DL) +typedef ACE_TCHAR * ACE_DL_TYPE; +# else +typedef const ACE_TCHAR * ACE_DL_TYPE; +# endif /* ACE_HAS_CHARPTR_DL */ + +# if !defined (ACE_HAS_SIGINFO_T) +# if defined (ACE_HAS_PACE) +typedef pace_siginfo_t siginfo_t; +# else +struct ACE_OS_Export siginfo_t +{ + siginfo_t (ACE_HANDLE handle); + siginfo_t (ACE_HANDLE *handles); // JCEJ 12/23/96 + + ACE_HANDLE si_handle_; + // Win32 HANDLE that has become signaled. + + ACE_HANDLE *si_handles_; + // Array of Win32 HANDLEs all of which have become signaled. +}; +# endif /* ACE_HAS_PACE */ +# endif /* ACE_HAS_SIGINFO_T */ + +// Typedef for the null handler func. +extern "C" +{ + typedef void (*ACE_SIGNAL_C_FUNC)(int,siginfo_t*,void*); +} + +# if !defined (ACE_HAS_UCONTEXT_T) +typedef int ucontext_t; +# endif /* ACE_HAS_UCONTEXT_T */ + +# if !defined (SA_SIGINFO) +# define SA_SIGINFO 0 +# endif /* SA_SIGINFO */ + +# if !defined (SA_RESTART) +# define SA_RESTART 0 +# endif /* SA_RESTART */ + +# if defined (ACE_HAS_TIMOD_H) +# if defined (ACE_HAS_STL_QUEUE_CONFLICT) +# define queue _Queue_ +# endif /* ACE_HAS_STL_QUEUE_CONFLICT */ +# include /**/ +# if defined (ACE_HAS_STL_QUEUE_CONFLICT) +# undef queue +# endif /* ACE_HAS_STL_QUEUE_CONFLICT */ +# elif defined (ACE_HAS_OSF_TIMOD_H) +# include /**/ +# endif /* ACE_HAS_TIMOD_H */ + +/** + * @class ACE_Thread_ID + * + * @brief Defines a platform-independent thread ID. + */ +class ACE_OS_Export ACE_Thread_ID +{ +public: + // = Initialization method. + ACE_Thread_ID (ACE_thread_t, ACE_hthread_t); + ACE_Thread_ID (const ACE_Thread_ID &id); + + // = Set/Get the Thread ID. + ACE_thread_t id (void); + void id (ACE_thread_t); + + // = Set/Get the Thread handle. + ACE_hthread_t handle (void); + void handle (ACE_hthread_t); + + // != Comparison operator. + int operator== (const ACE_Thread_ID &) const; + int operator!= (const ACE_Thread_ID &) const; + +private: + /// Identify the thread. + ACE_thread_t thread_id_; + + /// Handle to the thread (typically used to "wait" on Win32). + ACE_hthread_t thread_handle_; +}; + +// Type of the extended signal handler. +typedef void (*ACE_Sig_Handler_Ex) (int, siginfo_t *siginfo, ucontext_t *ucontext); + +// = The ACE_Sched_Priority type should be used for platform- +// independent thread and process priorities, by convention. +// int should be used for OS-specific priorities. +typedef int ACE_Sched_Priority; + +// forward declaration +class ACE_Sched_Params; + +# if defined (ACE_LACKS_FILELOCKS) +# if ! defined (VXWORKS) && ! defined (ACE_PSOS) && ! defined (__rtems__) +// VxWorks defines struct flock in sys/fcntlcom.h. But it doesn't +// appear to support flock (). RTEMS defines struct flock but +// currently does not support locking. +struct flock +{ + short l_type; + short l_whence; + off_t l_start; + off_t l_len; /* len == 0 means until end of file */ + long l_sysid; + pid_t l_pid; + long l_pad[4]; /* reserve area */ +}; +# endif /* ! VXWORKS */ +# endif /* ACE_LACKS_FILELOCKS */ + +# if !defined (ACE_HAS_IP_MULTICAST) && defined (ACE_LACKS_IP_ADD_MEMBERSHIP) + // Even if ACE_HAS_IP_MULTICAST is not defined, if IP_ADD_MEMBERSHIP + // is defined, assume that the ip_mreq struct is also defined + // (presumably in netinet/in.h). + struct ip_mreq + { + struct in_addr imr_multiaddr; + // IP multicast address of group + struct in_addr imr_interface; + // local IP address of interface + }; +# endif /* ! ACE_HAS_IP_MULTICAST && ACE_LACKS_IP_ADD_MEMBERSHIP */ + +# if !defined (ACE_HAS_STRBUF_T) +struct strbuf +{ + int maxlen; // no. of bytes in buffer. + int len; // no. of bytes returned. + void *buf; // pointer to data. +}; +# endif /* ACE_HAS_STRBUF_T */ + +/** + * @class ACE_Str_Buf + * + * @brief Simple wrapper for STREAM pipes strbuf. + */ +class ACE_OS_Export ACE_Str_Buf : public strbuf +{ +public: + // = Initialization method + /// Constructor. + ACE_Str_Buf (void *b = 0, int l = 0, int max = 0); + + /// Constructor. + ACE_Str_Buf (strbuf &); +}; + +# if defined (ACE_HAS_BROKEN_BITSHIFT) + // This might not be necessary any more: it was added prior to the + // (fd_mask) cast being added to the version below. Maybe that cast + // will fix the problem on tandems. Fri Dec 12 1997 David L. Levine +# define ACE_MSB_MASK (~(ACE_UINT32 (1) << ACE_UINT32 (NFDBITS - 1))) +# else + // This needs to go here to avoid overflow problems on some compilers. +# if defined (ACE_WIN32) + // Does ACE_WIN32 have an fd_mask? +# define ACE_MSB_MASK (~(1 << (NFDBITS - 1))) +# else /* ! ACE_WIN32 */ +# define ACE_MSB_MASK (~((fd_mask) 1 << (NFDBITS - 1))) +# endif /* ! ACE_WIN32 */ +# endif /* ACE_HAS_BROKEN_BITSHIFT */ + +// Signature for registering a cleanup function that is used by the +// and the . +# if defined (ACE_HAS_SIG_C_FUNC) +extern "C" { +# endif /* ACE_HAS_SIG_C_FUNC */ +typedef void (*ACE_CLEANUP_FUNC)(void *object, void *param) /* throw () */; +# if defined (ACE_HAS_SIG_C_FUNC) +} +# endif /* ACE_HAS_SIG_C_FUNC */ + +# if defined (ACE_WIN32) +// Default WIN32 structured exception handler. +int ACE_SEH_Default_Exception_Selector (void *); +int ACE_SEH_Default_Exception_Handler (void *); +# endif /* ACE_WIN32 */ + +/** + * @class ACE_Cleanup + * + * @brief Base class for objects that are cleaned by ACE_Object_Manager. + */ +class ACE_OS_Export ACE_Cleanup +{ +public: + /// No-op constructor. + ACE_Cleanup (void); + + /// Destructor. + virtual ~ACE_Cleanup (void); + + /// Cleanup method that, by default, simply deletes itself. + virtual void cleanup (void *param = 0); +}; + +// Adapter for cleanup, used by ACE_Object_Manager. +extern "C" ACE_OS_Export +void ace_cleanup_destroyer (ACE_Cleanup *, void *param = 0); + +/** + * @class ACE_Cleanup_Info + * + * @brief Hold cleanup information for thread/process + */ +class ACE_OS_Export ACE_Cleanup_Info +{ +public: + /// Default constructor. + ACE_Cleanup_Info (void); + + /// Equality operator. + int operator== (const ACE_Cleanup_Info &o) const; + + /// Inequality operator. + int operator!= (const ACE_Cleanup_Info &o) const; + + /// Point to object that gets passed into the . + void *object_; + + /// Cleanup hook that gets called back. + ACE_CLEANUP_FUNC cleanup_hook_; + + /// Parameter passed to the . + void *param_; +}; + +class ACE_Cleanup_Info_Node; + +/** + * @class ACE_OS_Exit_Info + * + * @brief Hold Object Manager cleanup (exit) information. + * + * For internal use by the ACE library, only. + */ +class ACE_OS_Export ACE_OS_Exit_Info +{ +public: + /// Default constructor. + ACE_OS_Exit_Info (void); + + /// Destructor. + ~ACE_OS_Exit_Info (void); + + /// Use to register a cleanup hook. + int at_exit_i (void *object, ACE_CLEANUP_FUNC cleanup_hook, void *param); + + /// Look for a registered cleanup hook object. Returns 1 if already + /// registered, 0 if not. + int find (void *object); + + /// Call all registered cleanup hooks, in reverse order of + /// registration. + void call_hooks (); + +private: + /** + * Keeps track of all registered objects. The last node is only + * used to terminate the list (it doesn't contain a valid + * ACE_Cleanup_Info). + */ + ACE_Cleanup_Info_Node *registered_objects_; +}; + +class ACE_Base_Thread_Adapter; +class ACE_Thread_Hook; + +# if defined (ACE_HAS_PHARLAP_RT) +#define ACE_IPPROTO_TCP SOL_SOCKET +# else +#define ACE_IPPROTO_TCP IPPROTO_TCP +# endif /* ACE_HAS_PHARLAP_RT */ + +# if defined (ACE_LACKS_FLOATING_POINT) +typedef ACE_UINT32 ACE_timer_t; +# else +typedef double ACE_timer_t; +# endif /* ACE_LACKS_FLOATING_POINT */ + +# if defined (ACE_HAS_PRUSAGE_T) + typedef prusage_t ACE_Rusage; +# elif defined (ACE_HAS_GETRUSAGE) + typedef rusage ACE_Rusage; +# else + typedef int ACE_Rusage; +# endif /* ACE_HAS_PRUSAGE_T */ + +# if !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SYSLOG) +# include /**/ +# endif /* !defined (ACE_WIN32) && !defined (ACE_LACKS_UNIX_SYSLOG) */ + +#if defined (ACE_HAS_SYS_FILIO_H) +# include /**/ +#endif /* ACE_HAS_SYS_FILIO_H */ + +# if defined (ACE_HAS_PACE) + // = typedef for the _stat data structure + typedef pace_stat_s ACE_stat; +# else +# if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) && !defined (__BORLANDC__) + typedef struct _stat ACE_stat; +# else + typedef struct stat ACE_stat; +# endif /* ACE_WIN32 */ +# endif /* ACE_HAS_PACE */ + +// We need this for MVS... +extern "C" { + typedef int (*ACE_COMPARE_FUNC)(const void *, const void *); +} + + + +/// Helper for the ACE_OS::timezone() function +/** + * We put all the timezone stuff that used to be in ACE_OS::timezone() + * here because on some platforms "timezone" is a macro. Because of this, + * the name ACE_OS::timezone will cause errors. So in order to use the + * macro as it is defined but also keep the name ACE_OS::timezone, we + * use timezone first here in this inline function, and then undefine + * timezone. + */ +inline long ace_timezone() +{ +#if !defined (ACE_HAS_WINCE) && !defined (VXWORKS) && !defined (ACE_PSOS) \ + && !defined (CHORUS) +# if defined (ACE_WIN32) + return _timezone; // For Win32. +# elif defined (__Lynx__) || defined (__FreeBSD__) || defined (ACE_HAS_SUNOS4_GETTIMEOFDAY) + long result = 0; + struct timeval time; + struct timezone zone; + ACE_UNUSED_ARG (result); + ACE_OSCALL (::gettimeofday (&time, &zone), int, -1, result); + return zone.tz_minuteswest * 60; +# else /* __Lynx__ || __FreeBSD__ ... */ + return timezone; +# endif /* __Lynx__ || __FreeBSD__ ... */ +#else + ACE_NOTSUP_RETURN (0); +#endif /* !ACE_HAS_WINCE && !VXWORKS && !ACE_PSOS */ +} + + +#if !defined (ACE_LACKS_DIFFTIME) +/// Helper for the ACE_OS::difftime() function +/** + * We moved the difftime code that used to be in ACE_OS::difftime() + * here because on some platforms "difftime" is a macro. Because of this, + * the name ACE_OS::difftime will cause errors. So in order to use the + * macro as it is defined but also keep the name ACE_OS::difftime, we + * use difftime first here in this inline function, and then undefine + * it. + */ +inline double ace_difftime(time_t t1, time_t t0) +{ +# if defined (ACE_HAS_PACE) + return ::pace_difftime (t1, t0); +# elif defined (ACE_PSOS) && ! defined (ACE_PSOS_HAS_TIME) + // simulate difftime ; just subtracting ; ACE_PSOS case + return ((double)t1) - ((double)t0); +# else + return difftime (t1, t0); +# endif /* ACE_HAS_PACE */ +} +#endif /* !ACE_LACKS_DIFFTIME */ + + +/// Helper for the ACE_OS::cuserid() function +/** + * On some platforms cuserid is a macro. Defining ACE_OS::cuserid() + * becomes really hard, as there is no way to save the macro + * definition using the pre-processor. + * This inline function achieves the same effect, without namespace + * pollution or performance penalties. + * + * @todo We maybe should move a lot of the code in ACE_OS::cuserid here so + * it is treated the same as the above ace_difftime and ace_timezone. + * But since there is a good deal more code in ACE_OS::cuserid, we + * probably need to move some of it off into some sort of emulation + * function. + */ +#if !defined (ACE_LACKS_CUSERID) && !defined(ACE_HAS_ALT_CUSERID) \ + && !defined(ACE_WIN32) && !defined (VXWORKS) +inline char *ace_cuserid(char *user) +{ + return cuserid(user); +} +#endif /* !ACE_LACKS_CUSERID && !ACE_HAS_ALT_CUSERID && ... */ + +#if defined (SD_RECEIVE) +#define ACE_SHUTDOWN_READ SD_RECEIVE +#elif defined (SHUT_RD) +#define ACE_SHUTDOWN_READ SHUT_RD +#else +#define ACE_SHUTDOWN_READ 0 +#endif /* SD_RECEIVE */ + +#if defined (SD_SEND) +#define ACE_SHUTDOWN_WRITE SD_SEND +#elif defined (SHUT_WR) +#define ACE_SHUTDOWN_WRITE SHUT_WR +#else +#define ACE_SHUTDOWN_WRITE 1 +#endif /* SD_RECEIVE */ + +#if defined (SD_BOTH) +#define ACE_SHUTDOWN_BOTH SD_BOTH +#elif defined (SHUT_RDWR) +#define ACE_SHUTDOWN_BOTH SHUT_RDWR +#else +#define ACE_SHUTDOWN_BOTH 2 +#endif /* SD_RECEIVE */ + +// forward declarations of QoS data structures +class ACE_QoS; +class ACE_QoS_Params; +class ACE_Accept_QoS_Params; + +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) +typedef WSAPROTOCOL_INFO ACE_Protocol_Info; + +// Callback function that's used by the QoS-enabled +// method. +typedef LPWSAOVERLAPPED_COMPLETION_ROUTINE ACE_OVERLAPPED_COMPLETION_FUNC; +typedef GROUP ACE_SOCK_GROUP; +#else /* (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */ +struct ACE_Protocol_Info +{ + u_long dwServiceFlags1; + int iAddressFamily; + int iProtocol; + char szProtocol[255+1]; +}; + +// Callback function that's used by the QoS-enabled +// method. +typedef void (*ACE_OVERLAPPED_COMPLETION_FUNC) (u_long error, + u_long bytes_transferred, + ACE_OVERLAPPED *overlapped, + u_long flags); +typedef u_long ACE_SOCK_GROUP; + +#endif /* (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */ + + +/** + * @class ACE_OS + * + * @brief This class defines an OS independent programming API that + * shields developers from nonportable aspects of writing + * efficient system programs on Win32, POSIX and other versions + * of UNIX, and various real-time operating systems. + * + * This class encapsulates the differences between various OS + * platforms. When porting ACE to a new platform, this class is + * the place to focus on. Once this file is ported to a new + * platform, pretty much everything else comes for "free." See + * + * for instructions on porting ACE. Please see the README file + * in this directory for complete information on the meaning of + * the various macros. + */ +class ACE_OS_Export ACE_OS + : public ACE_OS_Dirent, + public ACE_OS_String, + public ACE_OS_Memory, + public ACE_OS_TLI +{ + + ACE_CLASS_IS_NAMESPACE (ACE_OS); +public: + friend class ACE_Timeout_Manager; + +# if defined (CHORUS) && !defined (CHORUS_4) + // We must format this code as follows to avoid confusing OSE. + enum ACE_HRTimer_Op + { + ACE_HRTIMER_START = K_BSTART, + ACE_HRTIMER_INCR = K_BPOINT, + ACE_HRTIMER_STOP = K_BSTOP, + ACE_HRTIMER_GETTIME = 0xFFFF + }; +# else /* ! CHORUS */ + enum ACE_HRTimer_Op + { + ACE_HRTIMER_START = 0x0, // Only use these if you can stand + ACE_HRTIMER_INCR = 0x1, // for interrupts to be disabled during + ACE_HRTIMER_STOP = 0x2, // the timed interval!!!! + ACE_HRTIMER_GETTIME = 0xFFFF + }; +# endif /* ! CHORUS */ + + /** + * @class ace_flock_t + * + * @brief OS file locking structure. + */ + class ace_flock_t + { + public: + /// Dump state of the object. + void dump (void) const; + +# if defined (ACE_WIN32) + ACE_OVERLAPPED overlapped_; +# else + struct flock lock_; +# endif /* ACE_WIN32 */ + + /// Name of this filelock. + const ACE_TCHAR *lockname_; + + /// Handle to the underlying file. + ACE_HANDLE handle_; + +# if defined (CHORUS) + /// This is the mutex that's stored in shared memory. It can only + /// be destroyed by the actor that initialized it. + ACE_mutex_t *process_lock_; +# endif /* CHORUS */ + }; + +# if defined (ACE_WIN32) + // = Default Win32 Security Attributes definition. + static LPSECURITY_ATTRIBUTES default_win32_security_attributes (LPSECURITY_ATTRIBUTES); + + // = Win32 OS version determination function. + /// Return the win32 OSVERSIONINFO structure. + static const OSVERSIONINFO &get_win32_versioninfo (void); + + // = A pair of functions for modifying ACE's Win32 resource usage. + /// Return the handle of the module containing ACE's resources. By + /// default, for a DLL build of ACE this is a handle to the ACE DLL + /// itself, and for a static build it is a handle to the executable. + static HINSTANCE get_win32_resource_module (void); + + /// Allow an application to modify which module contains ACE's + /// resources. This is mainly useful for a static build of ACE where + /// the required resources reside somewhere other than the executable. + static void set_win32_resource_module (HINSTANCE); + +# endif /* ACE_WIN32 */ + + // = A set of wrappers for miscellaneous operations. + static int atoi (const char *s); + +# if defined (ACE_HAS_WCHAR) + static int atoi (const wchar_t *s); +# endif /* ACE_HAS_WCHAR */ + + /// This method computes the largest integral value not greater than x. + static double floor (double x); + + /// This method computes the smallest integral value not less than x. + static double ceil (double x); + + static char *getenv (const char *symbol); +# if defined (ACE_HAS_WCHAR) && defined (ACE_WIN32) + static wchar_t *getenv (const wchar_t *symbol); +# endif /* ACE_HAS_WCHAR && ACE_WIN32 */ + static int putenv (const ACE_TCHAR *string); + static ACE_TCHAR *strenvdup (const ACE_TCHAR *str); + static ACE_TCHAR *getenvstrings (void); + + static int getopt (int argc, + char *const *argv, + const char *optstring); + static int argv_to_string (ACE_TCHAR **argv, + ACE_TCHAR *&buf, + int substitute_env_args = 1); + static int string_to_argv (ACE_TCHAR *buf, + size_t &argc, + ACE_TCHAR **&argv, + int substitute_env_args = 1); + static long sysconf (int); + + //@{ @name A set of wrappers for condition variables. + static int condattr_init (ACE_condattr_t &attributes, + int type = ACE_DEFAULT_SYNCH_TYPE); + static int condattr_destroy (ACE_condattr_t &attributes); + static int cond_broadcast (ACE_cond_t *cv); + static int cond_destroy (ACE_cond_t *cv); + static int cond_init (ACE_cond_t *cv, + short type = ACE_DEFAULT_SYNCH_TYPE, + const char *name = 0, + void *arg = 0); + static int cond_init (ACE_cond_t *cv, + ACE_condattr_t &attributes, + const char *name = 0, + void *arg = 0); +# if defined (ACE_HAS_WCHAR) + static int cond_init (ACE_cond_t *cv, + short type, + const wchar_t *name, + void *arg = 0); + static int cond_init (ACE_cond_t *cv, + ACE_condattr_t &attributes, + const wchar_t *name, + void *arg = 0); +# endif /* ACE_HAS_WCHAR */ + static int cond_signal (ACE_cond_t *cv); + static int cond_timedwait (ACE_cond_t *cv, + ACE_mutex_t *m, + ACE_Time_Value *); + static int cond_wait (ACE_cond_t *cv, + ACE_mutex_t *m); +# if defined (ACE_WIN32) && defined (ACE_HAS_WTHREADS) + static int cond_timedwait (ACE_cond_t *cv, + ACE_thread_mutex_t *m, + ACE_Time_Value *); + static int cond_wait (ACE_cond_t *cv, + ACE_thread_mutex_t *m); +# endif /* ACE_WIN32 && ACE_HAS_WTHREADS */ + //@} + + + //@{ @name Wrappers to obtain the current user id +# if !defined (ACE_LACKS_CUSERID) +#if defined(cuserid) +# undef cuserid +#endif /* cuserid */ + static char *cuserid (char *user, + size_t maxlen = ACE_MAX_USERID); + +# if defined (ACE_HAS_WCHAR) + static wchar_t *cuserid (wchar_t *user, + size_t maxlen = ACE_MAX_USERID); +# endif /* ACE_HAS_WCHAR */ +# endif /* ACE_LACKS_CUSERID */ + //@} + + //@{ @name Wrappers to obtain configuration info + static int uname (ACE_utsname *name); + static long sysinfo (int cmd, + char *buf, + long count); + static int hostname (char *name, + size_t maxnamelen); + +#if defined (ACE_HAS_WCHAR) + static int hostname (wchar_t *name, + size_t maxnamelen); +#endif /* ACE_HAS_WCHAR */ + //@} + + //@{ @name A set of wrappers for explicit dynamic linking. + static int dlclose (ACE_SHLIB_HANDLE handle); + + static ACE_TCHAR *dlerror (void); + static ACE_SHLIB_HANDLE dlopen (const ACE_TCHAR *filename, + int mode = ACE_DEFAULT_SHLIB_MODE); + static void *dlsym (ACE_SHLIB_HANDLE handle, + const ACE_TCHAR *symbol); + //@} + + //{@ @name A set of wrappers for stdio file operations. + static int last_error (void); + static void last_error (int); + static int set_errno_to_last_error (void); + static int set_errno_to_wsa_last_error (void); + static int fclose (FILE *fp); + static int fcntl (ACE_HANDLE handle, + int cmd, + long arg = 0); + static int fdetach (const char *file); + + static int fsync (ACE_HANDLE handle); + + static FILE *fopen (const ACE_TCHAR *filename, const ACE_TCHAR *mode); + static FILE *freopen (const ACE_TCHAR *filename, const ACE_TCHAR *mode, FILE* stream); +# if defined (fdopen) +# undef fdopen +# endif /* fdopen */ + static FILE *fdopen (ACE_HANDLE handle, const ACE_TCHAR *mode); + static ACE_TCHAR *fgets (ACE_TCHAR *buf, int size, FILE *fp); + static int stat (const ACE_TCHAR *file, ACE_stat *); + static int truncate (const ACE_TCHAR *filename, off_t length); + + static int fprintf (FILE *fp, const char *format, ...); + static int sprintf (char *buf, const char *format, ...); + static int vsprintf (char *buffer, const char *format, va_list argptr); + static int printf (const char *format, ...); +# if defined (ACE_HAS_WCHAR) + static int sprintf (wchar_t *buf, const wchar_t *format, ...); + static int fprintf (FILE *fp, const wchar_t *format, ...); + static int vsprintf (wchar_t *buffer, const wchar_t *format, va_list argptr); +# endif /* ACE_HAS_WCHAR */ + + static void perror (const ACE_TCHAR *s); + + // The old gets () which directly maps to the evil, unprotected + // gets () has been deprecated. If you really need gets (), + // consider the following one. + + // A better gets (). + // If n == 0, input is swallowed, but NULL is returned. + // Otherwise, reads up to n-1 bytes (not including the newline), + // then swallows rest up to newline + // then swallows newline + static char *gets (char *str, int n = 0); + static int puts (const ACE_TCHAR *s); + static int fputs (const ACE_TCHAR *s, + FILE *stream); + + static int fflush (FILE *fp); + static size_t fread (void *ptr, + size_t size, + size_t nelems, + FILE *fp); + static int fseek (FILE *fp, + long offset, + int ptrname); + static int fstat (ACE_HANDLE, + ACE_stat *); + static int lstat (const char *, + ACE_stat *); + static int ftruncate (ACE_HANDLE, + off_t); + static size_t fwrite (const void *ptr, + size_t size, + size_t nitems, + FILE *fp); + static void rewind (FILE *fp); + //@} + + //@{ @name Wrappers for searching and sorting. + static void *bsearch (const void *key, + const void *base, + size_t nel, + size_t size, + ACE_COMPARE_FUNC); + static void qsort (void *base, + size_t nel, + size_t width, + ACE_COMPARE_FUNC); + //@} + + //@{ @name A set of wrappers for file locks. + static int flock_init (ACE_OS::ace_flock_t *lock, + int flags = 0, + const ACE_TCHAR *name = 0, + mode_t perms = 0); + static int flock_destroy (ACE_OS::ace_flock_t *lock, + int unlink_file = 1); +# if defined (ACE_WIN32) + static void adjust_flock_params (ACE_OS::ace_flock_t *lock, + short whence, + off_t &start, + off_t &len); +# endif /* ACE_WIN32 */ + static int flock_rdlock (ACE_OS::ace_flock_t *lock, + short whence = 0, + off_t start = 0, + off_t len = 0); + static int flock_tryrdlock (ACE_OS::ace_flock_t *lock, + short whence = 0, + off_t start = 0, + off_t len = 0); + static int flock_trywrlock (ACE_OS::ace_flock_t *lock, + short whence = 0, + off_t start = 0, + off_t len = 0); + static int flock_unlock (ACE_OS::ace_flock_t *lock, + short whence = 0, + off_t start = 0, + off_t len = 0); + static int flock_wrlock (ACE_OS::ace_flock_t *lock, + short whence = 0, + off_t start = 0, + off_t len = 0); + //@} + + //@{ @name A set of wrappers for low-level process operations. + static int atexit (ACE_EXIT_HOOK func); + static int execl (const char *path, + const char *arg0, ...); + static int execle (const char *path, + const char *arg0, ...); + static int execlp (const char *file, + const char *arg0, ...); + static int execv (const char *path, + char *const argv[]); + static int execvp (const char *file, + char *const argv[]); + static int execve (const char *path, + char *const argv[], + char *const envp[]); + static void _exit (int status = 0); + static void exit (int status = 0); + static void abort (void); + static pid_t fork (void); + + //@{ + /// Forks and exec's a process in a manner that works on Solaris and + /// NT. argv[0] must be the full path name to the executable. + static pid_t fork (const ACE_TCHAR *program_name); + static pid_t fork_exec (ACE_TCHAR *argv[]); + //@} + + static int getpagesize (void); + static int allocation_granularity (void); + + static gid_t getgid (void); + static int setgid (gid_t); + static pid_t getpid (void); + static pid_t getpgid (pid_t pid); + static pid_t getppid (void); + static uid_t getuid (void); + static int setuid (uid_t); + static pid_t setsid (void); + static int setpgid (pid_t pid, pid_t pgid); + static int setreuid (uid_t ruid, uid_t euid); + static int setregid (gid_t rgid, gid_t egid); + static int system (const ACE_TCHAR *s); + //@} + + /** + * Calls <::waitpid> on UNIX/POSIX platforms and <::await> on + * Chorus. Does not work on Vxworks, or pSoS. + * On Win32, is ignored if the is not equal to 0. + * Passing the process is prefer on Win32 because using + * to wait on the project doesn't always work correctly + * if the waited process has already terminated. + */ + static pid_t waitpid (pid_t pid, + ACE_exitcode *status = 0, + int wait_options = 0, + ACE_HANDLE handle = 0); + + /** + * Calls <::WaitForSingleObject> on Win32 and + * otherwise. Returns the passed in on success and -1 on + * failure. + * On Win32, is ignored if the is not equal to 0. + * Passing the process is prefer on Win32 because using + * to wait on the project doesn't always work correctly + * if the waited process has already terminated. + */ + static pid_t wait (pid_t pid, + ACE_exitcode *status, + int wait_options = 0, + ACE_HANDLE handle = 0); + + /// Calls OS <::wait> function, so it's only portable to UNIX/POSIX + /// platforms. + static pid_t wait (int * = 0); + + //@{ @name A set of wrappers for timers and resource stats. + static u_int alarm (u_int secs); + static u_int ualarm (u_int usecs, + u_int interval = 0); + static u_int ualarm (const ACE_Time_Value &tv, + const ACE_Time_Value &tv_interval = ACE_Time_Value::zero); + static ACE_hrtime_t gethrtime (const ACE_HRTimer_Op = ACE_HRTIMER_GETTIME); +# if defined (ACE_HAS_POWERPC_TIMER) && (defined (ghs) || defined (__GNUG__)) + static void readPPCTimeBase (u_long &most, + u_long &least); +# endif /* ACE_HAS_POWERPC_TIMER && (ghs or __GNUG__) */ + static int clock_gettime (clockid_t, + struct timespec *); + static ACE_Time_Value gettimeofday (void); + static int getrusage (int who, + struct rusage *rusage); + static int getrlimit (int resource, + struct rlimit *rl); + static int setrlimit (int resource, + ACE_SETRLIMIT_TYPE *rl); + static int sleep (u_int seconds); + static int sleep (const ACE_Time_Value &tv); + static int nanosleep (const struct timespec *requested, + struct timespec *remaining = 0); + +# if defined (ACE_HAS_BROKEN_R_ROUTINES) +# undef ctime_r +# undef asctime_r +# undef rand_r +# undef getpwnam_r +# endif /* ACE_HAS_BROKEN_R_ROUTINES */ + //@} + + //@{ @name A set of wrappers for operations on time. +# if !defined (ACE_HAS_WINCE) + static time_t mktime (struct tm *timeptr); +# endif /* !ACE_HAS_WINCE */ + + // wrapper for time zone information. + static void tzset (void); + +# if defined (timezone) +# undef timezone +# endif /* timezone */ + static long timezone (void); + +# if defined (difftime) +# undef difftime +# endif /* difftime */ + static double difftime (time_t t1, + time_t t0); + static time_t time (time_t *tloc = 0); + static struct tm *localtime (const time_t *clock); + static struct tm *localtime_r (const time_t *clock, + struct tm *res); + static struct tm *gmtime (const time_t *clock); + static struct tm *gmtime_r (const time_t *clock, + struct tm *res); + static char *asctime (const struct tm *tm); + static char *asctime_r (const struct tm *tm, + char *buf, int buflen); + static ACE_TCHAR *ctime (const time_t *t); + static ACE_TCHAR *ctime_r (const time_t *clock, ACE_TCHAR *buf, int buflen); + static size_t strftime (char *s, + size_t maxsize, + const char *format, + const struct tm *timeptr); + //@} + + //@{ @name A set of wrappers for System V message queues. + static int msgctl (int msqid, + int cmd, + struct msqid_ds *); + static int msgget (key_t key, + int msgflg); + static int msgrcv (int int_id, + void *buf, + size_t len, + long type, + int flags); + static int msgsnd (int int_id, + const void *buf, + size_t len, + int flags); + //@} + + //@{ @name A set of wrappers for memory mapped files. + static int madvise (caddr_t addr, + size_t len, + int advice); + static void *mmap (void *addr, + size_t len, + int prot, + int flags, + ACE_HANDLE handle, + off_t off = 0, + ACE_HANDLE *file_mapping = 0, + LPSECURITY_ATTRIBUTES sa = 0, + const ACE_TCHAR *file_mapping_name = 0); + static int mprotect (void *addr, + size_t len, + int prot); + static int msync (void *addr, + size_t len, + int sync); + static int munmap (void *addr, + size_t len); + //@} + + //@{ @name A set of wrappers for recursive mutex locks. + static int recursive_mutex_init (ACE_recursive_thread_mutex_t *m, + const ACE_TCHAR *name = 0, + ACE_mutexattr_t *arg = 0, + LPSECURITY_ATTRIBUTES sa = 0); + static int recursive_mutex_destroy (ACE_recursive_thread_mutex_t *m); + static int recursive_mutex_lock (ACE_recursive_thread_mutex_t *m); + static int recursive_mutex_trylock (ACE_recursive_thread_mutex_t *m); + static int recursive_mutex_unlock (ACE_recursive_thread_mutex_t *m); + //@} + + //@{ @name A set of wrappers for mutex locks. + static int mutex_init (ACE_mutex_t *m, + int type = ACE_DEFAULT_SYNCH_TYPE, + const char *name = 0, + ACE_mutexattr_t *arg = 0, + LPSECURITY_ATTRIBUTES sa = 0); +#if defined (ACE_HAS_WCHAR) + static int mutex_init (ACE_mutex_t *m, + int type, + const wchar_t *name, + ACE_mutexattr_t *arg = 0, + LPSECURITY_ATTRIBUTES sa = 0); +#endif /* ACE_HAS_WCHAR */ + static int mutex_destroy (ACE_mutex_t *m); + + /// Win32 note: Abandoned mutexes are not treated differently. 0 is + /// returned since the calling thread does get the ownership. + static int mutex_lock (ACE_mutex_t *m); + + /// This method is only implemented for Win32. For abandoned + /// mutexes, is set to 1 and 0 is returned. + static int mutex_lock (ACE_mutex_t *m, + int &abandoned); + + /** + * This method attempts to acquire a lock, but gives up if the lock + * has not been acquired by the given time. If the lock is not + * acquired within the given amount of time, then this method + * returns -1 with an errno on platforms that actually + * support timed mutexes. The timeout should be an absolute time. + * Note that the mutex should not be a recursive one, i.e., it + * should only be a standard mutex or an error checking mutex. + */ + static int mutex_lock (ACE_mutex_t *m, + const ACE_Time_Value &timeout); + + /** + * If == 0, calls . Otherwise, + * this method attempts to acquire a lock, but gives up if the lock + * has not been acquired by the given time, in which case it returns + * -1 with an errno on platforms that actually support timed + * mutexes. The timeout should be an absolute time. Note that the + * mutex should not be a recursive one, i.e., it should only be a + * standard mutex or an error checking mutex. + */ + static int mutex_lock (ACE_mutex_t *m, + const ACE_Time_Value *timeout); + + /// Win32 note: Abandoned mutexes are not treated differently. 0 is + /// returned since the calling thread does get the ownership. + static int mutex_trylock (ACE_mutex_t *m); + + /// This method is only implemented for Win32. For abandoned + /// mutexes, is set to 1 and 0 is returned. + static int mutex_trylock (ACE_mutex_t *m, + int &abandoned); + + static int mutex_unlock (ACE_mutex_t *m); + //@} + + //@{ @name A set of wrappers for mutex locks that only work within a single process. + static int thread_mutex_init (ACE_thread_mutex_t *m, + int type = ACE_DEFAULT_SYNCH_TYPE, + const char *name = 0, + ACE_mutexattr_t *arg = 0); +#if defined (ACE_HAS_WCHAR) + static int thread_mutex_init (ACE_thread_mutex_t *m, + int type, + const wchar_t *name, + ACE_mutexattr_t *arg = 0); +#endif /* ACE_HAS_WCHAR */ + static int thread_mutex_destroy (ACE_thread_mutex_t *m); + static int thread_mutex_lock (ACE_thread_mutex_t *m); + static int thread_mutex_lock (ACE_thread_mutex_t *m, + const ACE_Time_Value &timeout); + static int thread_mutex_lock (ACE_thread_mutex_t *m, + const ACE_Time_Value *timeout); + static int thread_mutex_trylock (ACE_thread_mutex_t *m); + static int thread_mutex_unlock (ACE_thread_mutex_t *m); + //@} + + //@{ @name A set of wrappers for low-level file operations. + static int access (const char *path, int amode); +#if defined (ACE_HAS_WCHAR) + static int access (const wchar_t *path, int amode); +#endif /* ACE_HAS_WCHAR */ + + static int close (ACE_HANDLE handle); + static ACE_HANDLE creat (const ACE_TCHAR *filename, + mode_t mode); + static ACE_HANDLE dup (ACE_HANDLE handle); + static int dup2 (ACE_HANDLE oldfd, + ACE_HANDLE newfd); + static int fattach (int handle, + const char *path); + static long filesize (ACE_HANDLE handle); + static long filesize (const ACE_TCHAR *handle); + static int getmsg (ACE_HANDLE handle, + struct strbuf *ctl, + struct strbuf + *data, int *flags); + static int getpmsg (ACE_HANDLE handle, + struct strbuf *ctl, + struct strbuf + *data, + int *band, + int *flags); + + /// UNIX-style . + static int ioctl (ACE_HANDLE handle, + int cmd, + void * = 0); + + /// QoS-enabled . + static int ioctl (ACE_HANDLE socket, + u_long io_control_code, + void *in_buffer_p, + u_long in_buffer, + void *out_buffer_p, + u_long out_buffer, + u_long *bytes_returned, + ACE_OVERLAPPED *overlapped, + ACE_OVERLAPPED_COMPLETION_FUNC func); + + /// QoS-enabled when the I/O control code is either + /// SIO_SET_QOS or SIO_GET_QOS. + static int ioctl (ACE_HANDLE socket, + u_long io_control_code, + ACE_QoS &ace_qos, + u_long *bytes_returned, + void *buffer_p = 0, + u_long buffer = 0, + ACE_OVERLAPPED *overlapped = 0, + ACE_OVERLAPPED_COMPLETION_FUNC func = 0); + + static int isastream (ACE_HANDLE handle); + static int isatty (int handle); +#if defined (ACE_WIN32) + static int isatty (ACE_HANDLE handle); +#endif /* ACE_WIN32 */ + static off_t lseek (ACE_HANDLE handle, + off_t offset, + int whence); +#if defined (ACE_HAS_LLSEEK) || defined (ACE_HAS_LSEEK64) + static ACE_LOFF_T llseek (ACE_HANDLE handle, ACE_LOFF_T offset, int whence); +#endif /* ACE_HAS_LLSEEK */ + + // It used to be that the argument default was 0 on all + // platforms. Further, the ACE_OS::open implementations ignored + // for Win32 and always supplied read|write|delete. To preserve + // backward compatibility and allow users to pass in values + // that are used as desired, the defaults are now what the default + // action used to be on Win32. The implementation now obeys what is passed. +#if defined (ACE_WIN32) +# if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 == 1) +# define ACE_DEFAULT_OPEN_PERMS (FILE_SHARE_READ | FILE_SHARE_WRITE | \ + FILE_SHARE_DELETE) +# else +# define ACE_DEFAULT_OPEN_PERMS (FILE_SHARE_READ | FILE_SHARE_WRITE) +# endif /* ACE_HAS_WINCE */ +#else +# define ACE_DEFAULT_OPEN_PERMS 0 +#endif /* ACE_WIN32 */ + + /// The O_APPEND flag is only partly supported on Win32. If you specify + /// O_APPEND, then the file pointer will be positioned at the end of + /// the file initially during open, but it is not re-positioned at + /// the end prior to each write, as specified by POSIX. This + /// is generally good enough for typical situations, but it is ``not + /// quite right'' in its semantics. + static ACE_HANDLE open (const char *filename, + int mode, + int perms = ACE_DEFAULT_OPEN_PERMS, + LPSECURITY_ATTRIBUTES sa = 0); +#if defined (ACE_HAS_WCHAR) + static ACE_HANDLE open (const wchar_t *filename, + int mode, + int perms = ACE_DEFAULT_OPEN_PERMS, + LPSECURITY_ATTRIBUTES sa = 0); +#endif /* ACE_HAS_WCHAR */ + static int putmsg (ACE_HANDLE handle, + const struct strbuf *ctl, + const struct strbuf *data, + int flags); + static int putpmsg (ACE_HANDLE handle, + const struct strbuf *ctl, + const struct strbuf *data, + int band, + int flags); + static ssize_t read (ACE_HANDLE handle, + void *buf, + size_t len); + static ssize_t read (ACE_HANDLE handle, + void *buf, + size_t len, + ACE_OVERLAPPED *); + /** + * Receive bytes into from (uses the + * call, which uses the system call on UNIX + * and the call on Win32). If errors occur, -1 is + * returned. If EOF occurs, 0 is returned. Whatever data has been + * transmitted will be returned to the caller through + * . + */ + static ssize_t read_n (ACE_HANDLE handle, + void *buf, + size_t len, + size_t *bytes_transferred = 0); + + static int readlink (const char *path, + char *buf, + size_t bufsiz); + static ssize_t pread (ACE_HANDLE handle, + void *buf, + size_t nbyte, + off_t offset); + static int recvmsg (ACE_HANDLE handle, + struct msghdr *msg, + int flags); + static int sendmsg (ACE_HANDLE handle, + const struct msghdr *msg, + int flags); + static ssize_t write (ACE_HANDLE handle, + const void *buf, + size_t nbyte); + static ssize_t write (ACE_HANDLE handle, + const void *buf, + size_t nbyte, + ACE_OVERLAPPED *); + + /** + * Send bytes from to (uses the + * calls, which is uses the system call on UNIX and the + * call on Win32). If errors occur, -1 is returned. If + * EOF occurs, 0 is returned. Whatever data has been transmitted + * will be returned to the caller through . + */ + static ssize_t write_n (ACE_HANDLE handle, + const void *buf, + size_t len, + size_t *bytes_transferred = 0); + + static ssize_t pwrite (ACE_HANDLE handle, + const void *buf, + size_t nbyte, + off_t offset); + static ssize_t readv (ACE_HANDLE handle, + iovec *iov, + int iovlen); + static ssize_t writev (ACE_HANDLE handle, + const iovec *iov, + int iovcnt); + static ssize_t recvv (ACE_HANDLE handle, + iovec *iov, + int iovlen); + static ssize_t sendv (ACE_HANDLE handle, + const iovec *iov, + int iovcnt); + //@} + + //@{ @name A set of wrappers for event demultiplexing and IPC. + static int select (int width, + fd_set *rfds, + fd_set *wfds = 0, + fd_set *efds = 0, + const ACE_Time_Value *tv = 0); + static int select (int width, + fd_set *rfds, + fd_set *wfds, + fd_set *efds, + const ACE_Time_Value &tv); + static int poll (struct pollfd *pollfds, + u_long len, + const ACE_Time_Value *tv = 0); + static int poll (struct pollfd *pollfds, + u_long len, + const ACE_Time_Value &tv); + static int pipe (ACE_HANDLE handles[]); + + static ACE_HANDLE shm_open (const ACE_TCHAR *filename, + int mode, + int perms = 0, + LPSECURITY_ATTRIBUTES sa = 0); + static int shm_unlink (const ACE_TCHAR *path); + //@} + + //@{ @name A set of wrappers for directory operations. + static mode_t umask (mode_t cmask); + +#if !defined (ACE_LACKS_CHDIR) + static int chdir (const char *path); + +#if defined (ACE_HAS_WCHAR) + static int chdir (const wchar_t *path); +#endif /* ACE_HAS_WCHAR */ +#endif /* ACE_LACKS_CHDIR */ + + static int mkdir (const ACE_TCHAR *path, + mode_t mode = ACE_DEFAULT_DIR_PERMS); + static int mkfifo (const ACE_TCHAR *file, + mode_t mode = ACE_DEFAULT_FILE_PERMS); + static ACE_TCHAR *mktemp (ACE_TCHAR *t); + static ACE_HANDLE mkstemp (ACE_TCHAR *t); + static ACE_TCHAR *getcwd (ACE_TCHAR *, size_t); + static int rename (const ACE_TCHAR *old_name, + const ACE_TCHAR *new_name, + int flags = -1); + static int unlink (const ACE_TCHAR *path); + static ACE_TCHAR *tempnam (const ACE_TCHAR *dir = 0, + const ACE_TCHAR *pfx = 0); + //@} + + //@{ @name A set of wrappers for random number operations. + static int rand (void); + static int rand_r (ACE_RANDR_TYPE &seed); + static void srand (u_int seed); + //@} + + //@{ @name A set of wrappers for readers/writer locks. + static int rwlock_init (ACE_rwlock_t *rw, + int type = ACE_DEFAULT_SYNCH_TYPE, + const ACE_TCHAR *name = 0, + void *arg = 0); + static int rwlock_destroy (ACE_rwlock_t *rw); + static int rw_rdlock (ACE_rwlock_t *rw); + static int rw_wrlock (ACE_rwlock_t *rw); + static int rw_tryrdlock (ACE_rwlock_t *rw); + static int rw_trywrlock (ACE_rwlock_t *rw); + static int rw_trywrlock_upgrade (ACE_rwlock_t *rw); + static int rw_unlock (ACE_rwlock_t *rw); + //@} + + //@{ @name A set of wrappers for auto-reset and manual events. + static int event_init (ACE_event_t *event, + int manual_reset = 0, + int initial_state = 0, + int type = ACE_DEFAULT_SYNCH_TYPE, + const char *name = 0, + void *arg = 0, + LPSECURITY_ATTRIBUTES sa = 0); +# if defined (ACE_HAS_WCHAR) + static int event_init (ACE_event_t *event, + int manual_reset, + int initial_state, + int type, + const wchar_t *name, + void *arg = 0, + LPSECURITY_ATTRIBUTES sa = 0); +# endif /* ACE_HAS_WCHAR */ + static int event_destroy (ACE_event_t *event); + static int event_wait (ACE_event_t *event); + static int event_timedwait (ACE_event_t *event, + ACE_Time_Value *timeout, + int use_absolute_time = 1); + static int event_signal (ACE_event_t *event); + static int event_pulse (ACE_event_t *event); + static int event_reset (ACE_event_t *event); + //@} + + //@{ @name A set of wrappers for semaphores. + static int sema_destroy (ACE_sema_t *s); + static int sema_init (ACE_sema_t *s, + u_int count, + int type = ACE_DEFAULT_SYNCH_TYPE, + const char *name = 0, + void *arg = 0, + int max = 0x7fffffff, + LPSECURITY_ATTRIBUTES sa = 0); +# if defined (ACE_HAS_WCHAR) + static int sema_init (ACE_sema_t *s, + u_int count, + int type, + const wchar_t *name, + void *arg = 0, + int max = 0x7fffffff, + LPSECURITY_ATTRIBUTES sa = 0); +# endif /* ACE_HAS_WCHAR */ + static int sema_post (ACE_sema_t *s); + static int sema_post (ACE_sema_t *s, + size_t release_count); + static int sema_trywait (ACE_sema_t *s); + static int sema_wait (ACE_sema_t *s); + static int sema_wait (ACE_sema_t *s, + ACE_Time_Value &tv); + static int sema_wait (ACE_sema_t *s, + ACE_Time_Value *tv); + //@} + + //@{ @name A set of wrappers for System V semaphores. + static int semctl (int int_id, + int semnum, + int cmd, + semun); + static int semget (key_t key, + int nsems, + int flags); + static int semop (int int_id, + struct sembuf *sops, + size_t nsops); + //@} + + //@{ @name Thread scheduler interface. + /// Set scheduling parameters. An id of ACE_SELF indicates, e.g., + /// set the parameters on the calling thread. + static int sched_params (const ACE_Sched_Params &, ACE_id_t id = ACE_SELF); + //@} + + //@{ @name A set of wrappers for System V shared memory. + static void *shmat (int int_id, + void *shmaddr, + int shmflg); + static int shmctl (int int_id, + int cmd, + struct shmid_ds *buf); + static int shmdt (void *shmaddr); + static int shmget (key_t key, + int size, + int flags); + ///@} + + //@{ @name A set of wrappers for Signals. + static int kill (pid_t pid, + int signum); + static int sigaction (int signum, + const struct sigaction *nsa, + struct sigaction *osa); + static int sigaddset (sigset_t *s, + int signum); + static int sigdelset (sigset_t *s, + int signum); + static int sigemptyset (sigset_t *s); + static int sigfillset (sigset_t *s); + static int sigismember (sigset_t *s, + int signum); + static ACE_SignalHandler signal (int signum, + ACE_SignalHandler); + static int sigsuspend (const sigset_t *set); + static int sigprocmask (int how, + const sigset_t *nsp, + sigset_t *osp); + + static int pthread_sigmask (int how, + const sigset_t *nsp, + sigset_t *osp); + //@} + + //@{ @name A set of wrappers for sockets. + /// BSD-style (no QoS). + static ACE_HANDLE accept (ACE_HANDLE handle, + struct sockaddr *addr, + int *addrlen); + + /** + * QoS-enabled , which passes to . If + * the OS platform doesn't support QoS-enabled then the + * are ignored and the BSD-style is called. + */ + static ACE_HANDLE accept (ACE_HANDLE handle, + struct sockaddr *addr, + int *addrlen, + const ACE_Accept_QoS_Params &qos_params); + /// BSD-style (no QoS). + static int connect (ACE_HANDLE handle, + struct sockaddr *addr, + int addrlen); + /** + * QoS-enabled , which passes to . + * If the OS platform doesn't support QoS-enabled then the + * are ignored and the BSD-style is called. + */ + static int connect (ACE_HANDLE handle, + const sockaddr *addr, + int addrlen, + const ACE_QoS_Params &qos_params); + + static int bind (ACE_HANDLE s, + struct sockaddr *name, + int namelen); + + static int closesocket (ACE_HANDLE s); + static struct hostent *gethostbyaddr (const char *addr, + int length, + int type); + static struct hostent *gethostbyname (const char *name); + static struct hostent *getipnodebyname (const char *name, int family, + int flags = 0); + static struct hostent *getipnodebyaddr (const void *src, size_t len, + int family); + static struct hostent *gethostbyaddr_r (const char *addr, + int length, + int type, + struct hostent *result, + ACE_HOSTENT_DATA buffer, + int *h_errnop); + static struct hostent *gethostbyname_r (const char *name, + struct hostent *result, + ACE_HOSTENT_DATA buffer, + int *h_errnop); + static int getpeername (ACE_HANDLE handle, + struct sockaddr *addr, + int *addrlen); + static struct protoent *getprotobyname (const char *name); + static struct protoent *getprotobyname_r (const char *name, + struct protoent *result, + ACE_PROTOENT_DATA buffer); + static struct protoent *getprotobynumber (int proto); + static struct protoent *getprotobynumber_r (int proto, + struct protoent *result, + ACE_PROTOENT_DATA buffer); + static struct servent *getservbyname (const char *svc, + const char *proto); + static struct servent *getservbyname_r (const char *svc, + const char *proto, + struct servent *result, + ACE_SERVENT_DATA buf); + static int getsockname (ACE_HANDLE handle, + struct sockaddr *addr, + int *addrlen); + static int getsockopt (ACE_HANDLE handle, + int level, + int optname, + char *optval, + int *optlen); + static unsigned long inet_addr (const char *name); + static char *inet_ntoa (const struct in_addr addr); + static int inet_aton (const char *strptr, + struct in_addr *addr); + static const char *inet_ntop (int family, + const void *addrptr, + char *strptr, + size_t len); + static int inet_pton (int family, + const char *strptr, + void *addrptr); + /// Retrieve information about available transport protocols + /// installed on the local machine. + static int enum_protocols (int *protocols, + ACE_Protocol_Info *protocol_buffer, + u_long *buffer_length); + /// Joins a leaf node into a QoS-enabled multi-point session. + static ACE_HANDLE join_leaf (ACE_HANDLE socket, + const sockaddr *name, + int namelen, + const ACE_QoS_Params &qos_params); + static int listen (ACE_HANDLE handle, + int backlog); + static int recv (ACE_HANDLE handle, + char *buf, + int len, + int flags = 0); + static int recvfrom (ACE_HANDLE handle, + char *buf, + int len, + int flags, + struct sockaddr *addr, + int *addrlen); + static int recvfrom (ACE_HANDLE handle, + iovec *buffers, + int buffer_count, + size_t &number_of_bytes_recvd, + int &flags, + struct sockaddr *addr, + int *addrlen, + ACE_OVERLAPPED *overlapped, + ACE_OVERLAPPED_COMPLETION_FUNC func); + static int send (ACE_HANDLE handle, + const char *buf, + int len, + int flags = 0); + static int sendto (ACE_HANDLE handle, + const char *buf, + int len, + int flags, + const struct sockaddr *addr, + int addrlen); + static int sendto (ACE_HANDLE handle, + const iovec *buffers, + int buffer_count, + size_t &number_of_bytes_sent, + int flags, + const struct sockaddr *addr, + int addrlen, + ACE_OVERLAPPED *overlapped, + ACE_OVERLAPPED_COMPLETION_FUNC func); + + /// Manipulate the options associated with a socket. + static int setsockopt (ACE_HANDLE handle, + int level, + int optname, + const char *optval, + int optlen); + static int shutdown (ACE_HANDLE handle, + int how); + + /// Create a BSD-style socket (no QoS). + static ACE_HANDLE socket (int protocol_family, + int type, + int proto); + + /// Create a QoS-enabled socket. If the OS platform doesn't support + /// QoS-enabled then the BSD-style is called. + static ACE_HANDLE socket (int protocol_family, + int type, + int proto, + ACE_Protocol_Info *protocolinfo, + ACE_SOCK_GROUP g, + u_long flags); + + static int socketpair (int domain, + int type, + int protocol, + ACE_HANDLE sv[2]); + + /// Initialize WinSock before first use (e.g., when a DLL is first + /// loaded or the first use of a socket() call. + static int socket_init (int version_high = 1, + int version_low = 1); + + /// Finalize WinSock after last use (e.g., when a DLL is unloaded). + static int socket_fini (void); + //@} + + //@{ @name A set of wrappers for password routines. + static void setpwent (void); + static void endpwent (void); + static struct passwd *getpwent (void); + static struct passwd *getpwnam (const char *user); + static struct passwd *getpwnam_r (const char *name, + struct passwd *pwent, + char *buffer, + int buflen); + //@} + + //@{ @name A set of wrappers for regular expressions. + static char *compile (const char *instring, + char *expbuf, + char *endbuf); + static int step (const char *str, + char *expbuf); + //@} + + //@{ @name Wide-character strings + // @@ UNICODE: (brunsch) Can this be handled better? + // The following WChar typedef and functions are used by TAO. TAO + // does not use wchar_t because the size of wchar_t is + // platform-dependent. These are to be used for all + // manipulate\ions of CORBA::WString. + typedef ACE_UINT16 WChar; + static u_int wslen (const WChar *); + static WChar *wscpy (WChar *, + const WChar *); + static int wscmp (const WChar *, + const WChar *); + static int wsncmp (const WChar *, + const WChar *, + size_t len); + //@} + +# if 0 + //@{ @name A set of wrappers for threads (these are portable since they use the ACE_Thread_ID). + static int thr_continue (const ACE_Thread_ID &thread); + static int thr_create (ACE_THR_FUNC, + void *args, + long flags, + ACE_Thread_ID *, + long priority = ACE_DEFAULT_THREAD_PRIORITY, + void *stack = 0, + size_t stacksize = 0); + static int thr_getprio (ACE_Thread_ID thr_id, + int &prio, + int *policy = 0); + static int thr_join (ACE_Thread_ID waiter_id, + void **status); + static int thr_kill (ACE_Thread_ID thr_id, + int signum); + static ACE_Thread_ID thr_self (void); + static int thr_setprio (ACE_Thread_ID thr_id, + int prio); + static int thr_setprio (const ACE_Sched_Priority prio); + static int thr_suspend (ACE_Thread_ID target_thread); + static int thr_cancel (ACE_Thread_ID t_id); + //@} +# endif /* 0 */ + + //@{ @name A set of wrappers for threads + + // These are non-portable since they use ACE_thread_t and + // ACE_hthread_t and will go away in a future release. + static int thr_continue (ACE_hthread_t target_thread); + + /* + * Creates a new thread having attributes and running + * with (if is non-0 then and + * are ignored and are obtained from ). + * and are set to the thread's ID and handle (?), + * respectively. The thread runs at priority (see + * below). + * + * The are a bitwise-OR of the following: + * = BEGIN + * THR_CANCEL_DISABLE, THR_CANCEL_ENABLE, THR_CANCEL_DEFERRED, + * THR_CANCEL_ASYNCHRONOUS, THR_BOUND, THR_NEW_LWP, THR_DETACHED, + * THR_SUSPENDED, THR_DAEMON, THR_JOINABLE, THR_SCHED_FIFO, + * THR_SCHED_RR, THR_SCHED_DEFAULT, THR_EXPLICIT_SCHED, + * THR_SCOPE_SYSTEM, THR_SCOPE_PROCESS + * = END + * + * By default, or if is set to + * ACE_DEFAULT_THREAD_PRIORITY, an "appropriate" priority value for + * the given scheduling policy (specified in , e.g., + * ) is used. This value is calculated + * dynamically, and is the median value between the minimum and + * maximum priority values for the given policy. If an explicit + * value is given, it is used. Note that actual priority values are + * EXTREMEMLY implementation-dependent, and are probably best + * avoided. + * + * Note that is always deleted by , + * therefore it must be allocated with global operator new. + */ + static int thr_create (ACE_THR_FUNC func, + void *args, + long flags, + ACE_thread_t *thr_id, + ACE_hthread_t *t_handle = 0, + long priority = ACE_DEFAULT_THREAD_PRIORITY, + void *stack = 0, + size_t stacksize = 0, + ACE_Base_Thread_Adapter *thread_adapter = 0); + + static int thr_getprio (ACE_hthread_t thr_id, + int &prio); + static int thr_join (ACE_hthread_t waiter_id, + void **status); + static int thr_join (ACE_thread_t waiter_id, + ACE_thread_t *thr_id, + void **status); + static int thr_kill (ACE_thread_t thr_id, + int signum); + static ACE_thread_t thr_self (void); + static void thr_self (ACE_hthread_t &); + static int thr_setprio (ACE_hthread_t thr_id, + int prio); + static int thr_setprio (const ACE_Sched_Priority prio); + static int thr_suspend (ACE_hthread_t target_thread); + static int thr_cancel (ACE_thread_t t_id); + + static int thr_cmp (ACE_hthread_t t1, + ACE_hthread_t t2); + static int thr_equal (ACE_thread_t t1, + ACE_thread_t t2); + static void thr_exit (void *status = 0); + static int thr_getconcurrency (void); + static int lwp_getparams (ACE_Sched_Params &); +# if defined (ACE_HAS_TSS_EMULATION) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + static int thr_getspecific (ACE_OS_thread_key_t key, + void **data); +# endif /* ACE_HAS_TSS_EMULATION && ACE_HAS_THREAD_SPECIFIC_STORAGE */ + static int thr_getspecific (ACE_thread_key_t key, + void **data); + static int thr_keyfree (ACE_thread_key_t key); + static int thr_key_detach (void *inst); +# if defined (ACE_HAS_THR_C_DEST) +# if defined (ACE_HAS_TSS_EMULATION) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + static int thr_keycreate (ACE_OS_thread_key_t *key, + ACE_THR_C_DEST, + void *inst = 0); +# endif /* ACE_HAS_TSS_EMULATION && ACE_HAS_THREAD_SPECIFIC_STORAGE */ + static int thr_keycreate (ACE_thread_key_t *key, + ACE_THR_C_DEST, + void *inst = 0); +# else +# if defined (ACE_HAS_TSS_EMULATION) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + static int thr_keycreate (ACE_OS_thread_key_t *key, + ACE_THR_DEST, + void *inst = 0); +# endif /* ACE_HAS_TSS_EMULATION && ACE_HAS_THREAD_SPECIFIC_STORAGE */ + static int thr_keycreate (ACE_thread_key_t *key, + ACE_THR_DEST, + void *inst = 0); +# endif /* ACE_HAS_THR_C_DEST */ + static int thr_key_used (ACE_thread_key_t key); + static size_t thr_min_stack (void); + static int thr_setconcurrency (int hint); + static int lwp_setparams (const ACE_Sched_Params &); +# if defined (ACE_HAS_TSS_EMULATION) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + static int thr_setspecific (ACE_OS_thread_key_t key, + void *data); +# endif /* ACE_HAS_TSS_EMULATION && ACE_HAS_THREAD_SPECIFIC_STORAGE */ + static int thr_setspecific (ACE_thread_key_t key, + void *data); + static int thr_sigsetmask (int how, + const sigset_t *nsm, + sigset_t *osm); + static int thr_setcancelstate (int new_state, + int *old_state); + static int thr_setcanceltype (int new_type, + int *old_type); + static int sigwait (sigset_t *set, + int *sig = 0); + static int sigtimedwait (const sigset_t *set, + siginfo_t *info, + const ACE_Time_Value *timeout); + static void thr_testcancel (void); + static void thr_yield (void); + + /** + * This method uses process id and object pointer to come up with a + * machine wide unique name. The process ID will provide uniqueness + * between processes on the same machine. The "this" pointer of the + * will provide uniqueness between other "live" objects in + * the same process. The uniqueness of this name is therefore only + * valid for the life of . + */ + static void unique_name (const void *object, + ACE_TCHAR *name, + size_t length); + + /// This is necessary to deal with POSIX pthreads and their use of + /// structures for thread ids. + static ACE_thread_t NULL_thread; + + /// This is necessary to deal with POSIX pthreads and their use of + /// structures for thread handles. + static ACE_hthread_t NULL_hthread; + + /// This is necessary to deal with POSIX pthreads and their use of + /// structures for TSS keys. + static ACE_thread_key_t NULL_key; + +# if defined (CHORUS) + /// This is used to map an actor's id into a KnCap for killing and + /// waiting actors. + static KnCap actorcaps_[ACE_CHORUS_MAX_ACTORS]; +# endif /* CHORUS */ + //@} + +# if defined (ACE_WIN32) + /// Keeps track of whether we've already initialized WinSock... + static int socket_initialized_; +# endif /* ACE_WIN32 */ + + /// Handle asynchronous thread cancellation cleanup. + static void mutex_lock_cleanup (void *mutex); + + /** + * Call TSS destructors for the current thread. If the current + * thread is the main thread, then the argument must be 1. + * For private use of ACE_Object_Manager and ACE_Thread_Adapter only. + */ + static void cleanup_tss (const u_int main_thread); + +# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) && defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) + static int netdb_acquire (void); + static int netdb_release (void); +# endif /* defined (ACE_MT_SAFE) && ACE_LACKS_NETDB_REENTRANT_FUNCTIONS */ + + /// Find the schedling class ID that corresponds to the class name. + static int scheduling_class (const char *class_name, ACE_id_t &); + + /// Friendly interface to (2). + static int set_scheduling_params (const ACE_Sched_Params &, + ACE_id_t id = ACE_SELF); + + /// Low-level interface to (2). + /** + * Can't call the following priocntl, because that's a macro on + * Solaris. + */ + static int priority_control (ACE_idtype_t, ACE_id_t, int, void *); + +#if defined (ACE_HAS_STRPTIME) + static char *strptime (char *buf, + const char *format, + struct tm *tm); + +# if defined (ACE_LACKS_NATIVE_STRPTIME) + static int strptime_getnum (char *buf, int *num, int *bi, + int *fi, int min, int max); +# endif /* ACE_LACKS_NATIVE_STRPTIME */ +#endif /* ACE_HAS_STRPTIME */ + +private: + +#if defined (ACE_LACKS_WRITEV) + static int writev_emulation (ACE_HANDLE handle, + ACE_WRITEV_TYPE *iov, + int iovcnt); +#endif /* ACE_LACKS_WRITEV */ + +#if defined (ACE_LACKS_READV) + static ssize_t readv_emulation (ACE_HANDLE handle, + ACE_READV_TYPE *iov, + int iovcnt); +#endif /* ACE_LACKS_READV */ + + /// Function that is called by , if non-null. + static ACE_EXIT_HOOK exit_hook_; + + /// For use by ACE_Object_Manager only, to register its exit hook.. + static ACE_EXIT_HOOK set_exit_hook (ACE_EXIT_HOOK hook); + + /// Allow the ACE_OS_Object_Manager to call set_exit_hook. + friend class ACE_OS_Object_Manager; + +# if defined (ACE_WIN32) +# if defined (ACE_HAS_WINCE) + /// Supporting data for ctime and ctime_r functions on WinCE. + static const wchar_t *day_of_week_name[7]; + static const wchar_t *month_name[12]; +# endif /* ACE_HAS_WINCE */ + + /// Translate fopen's mode char to open's mode. This helper function + /// is here to avoid maintaining several pieces of identical code. + static void fopen_mode_to_open_mode_converter (ACE_TCHAR x, int &hmode); + + static OSVERSIONINFO win32_versioninfo_; + + static HINSTANCE win32_resource_module_; + +# endif /* ACE_WIN32 */ + +#if defined (ACE_HAS_VIRTUAL_TIME) + static clock_t times (struct tms *buf); +#endif /* ACE_HAS_VIRTUAL_TIME */ + + //changed for ACE_HAS_VIRTUAL_TIME changes. + + static int cond_timedwait_i (ACE_cond_t *cv, + ACE_mutex_t *m, + ACE_Time_Value *); + + static u_int alarm_i (u_int secs); + + static u_int ualarm_i (u_int usecs, u_int interval = 0); + + static u_int ualarm_i (const ACE_Time_Value &tv, + const ACE_Time_Value &tv_interval = ACE_Time_Value::zero); + + static int sleep_i (u_int seconds); + + static int sleep_i (const ACE_Time_Value &tv); + + static int nanosleep_i (const struct timespec *requested, + struct timespec *remaining = 0); + + static int select_i (int width, + fd_set *rfds, + fd_set *wfds, + fd_set *efds, + const ACE_Time_Value *tv = 0); + + static int select_i (int width, + fd_set *rfds, + fd_set *wfds, + fd_set *efds, + const ACE_Time_Value &tv); + + static int poll_i (struct pollfd *pollfds, + u_long len, + const ACE_Time_Value *tv = 0); + + static int poll_i (struct pollfd *pollfds, + u_long len, + const ACE_Time_Value &tv); + + static int sema_wait_i (ACE_sema_t *s); + + static int sema_wait_i (ACE_sema_t *s, + ACE_Time_Value &tv); + + static int sigtimedwait_i (const sigset_t *set, + siginfo_t *info, + const ACE_Time_Value *timeout); + + static ACE_Time_Value gettimeofday_i (void); +}; + +/** + * @class ACE_Object_Manager_Base + * + * @brief Base class for ACE_Object_Manager(s). + * + * Encapsulates the most useful ACE_Object_Manager data structures. + */ +class ACE_OS_Export ACE_Object_Manager_Base +{ +# if (defined (ACE_PSOS) && defined (__DIAB)) || \ + (defined (__DECCXX_VER) && __DECCXX_VER < 60000000) + // The Diab compiler got confused and complained about access rights + // if this section was protected (changing this to public makes it happy). + // Similarly, DEC CXX 5.6 needs the methods to be public. +public: +# else /* ! (ACE_PSOS && __DIAB) || ! __DECCXX_VER < 60000000 */ +protected: +# endif /* ! (ACE_PSOS && __DIAB) || ! __DECCXX_VER < 60000000 */ + /// Default constructor. + ACE_Object_Manager_Base (void); + + /// Destructor. + virtual ~ACE_Object_Manager_Base (void); + +public: + /** + * Explicitly initialize. Returns 0 on success, -1 on failure due + * to dynamic allocation failure (in which case errno is set to + * ENOMEM), or 1 if it had already been called. + */ + virtual int init (void) = 0; + + /** + * Explicitly destroy. Returns 0 on success, -1 on failure because + * the number of fini () calls hasn't reached the number of init () + * calls, or 1 if it had already been called. + */ + virtual int fini (void) = 0; + + enum Object_Manager_State + { + OBJ_MAN_UNINITIALIZED = 0, + OBJ_MAN_INITIALIZING, + OBJ_MAN_INITIALIZED, + OBJ_MAN_SHUTTING_DOWN, + OBJ_MAN_SHUT_DOWN + }; + +protected: + /** + * Returns 1 before ACE_Object_Manager_Base has been constructed. + * This flag can be used to determine if the program is constructing + * static objects. If no static object spawns any threads, the + * program will be single-threaded when this flag returns 1. (Note + * that the program still might construct some static objects when + * this flag returns 0, if ACE_HAS_NONSTATIC_OBJECT_MANAGER is not + * defined.) + */ + int starting_up_i (void); + + /** + * Returns 1 after ACE_Object_Manager_Base has been destroyed. This + * flag can be used to determine if the program is in the midst of + * destroying static objects. (Note that the program might destroy + * some static objects before this flag can return 1, if + * ACE_HAS_NONSTATIC_OBJECT_MANAGER is not defined.) + */ + int shutting_down_i (void); + + /// State of the Object_Manager; + Object_Manager_State object_manager_state_; + + /** + * Flag indicating whether the ACE_Object_Manager was dynamically + * allocated by ACE. (If is was dynamically allocated by the + * application, then the application is responsible for destroying + * it.) + */ + u_int dynamically_allocated_; + + /// Link to next Object_Manager, for chaining. + ACE_Object_Manager_Base *next_; +private: + // Disallow copying by not implementing the following . . . + ACE_Object_Manager_Base (const ACE_Object_Manager_Base &); + ACE_Object_Manager_Base &operator= (const ACE_Object_Manager_Base &); +}; + +extern "C" +void +ACE_OS_Object_Manager_Internal_Exit_Hook (void); + + +// @@ This forward declaration should go away. +class ACE_Log_Msg; + +class ACE_OS_Export ACE_OS_Object_Manager : public ACE_Object_Manager_Base +{ +public: + /// Explicitly initialize. + virtual int init (void); + + /// Explicitly destroy. + virtual int fini (void); + + /** + * Returns 1 before the has been + * constructed. See for more + * information. + */ + static int starting_up (void); + + /// Returns 1 after the has been destroyed. + /// See for more information. + static int shutting_down (void); + + /// Unique identifiers for preallocated objects. + enum Preallocated_Object + { +# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) + ACE_OS_MONITOR_LOCK, + ACE_TSS_CLEANUP_LOCK, + ACE_LOG_MSG_INSTANCE_LOCK, +# if defined (ACE_HAS_TSS_EMULATION) + ACE_TSS_KEY_LOCK, +# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + ACE_TSS_BASE_LOCK, +# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ +# endif /* ACE_HAS_TSS_EMULATION */ +# else + // Without ACE_MT_SAFE, There are no preallocated objects. Make + // sure that the preallocated_array size is at least one by + // declaring this dummy . . . + ACE_OS_EMPTY_PREALLOCATED_OBJECT, +# endif /* ACE_MT_SAFE */ + + /// This enum value must be last! + ACE_OS_PREALLOCATED_OBJECTS + }; + + /// Accesses a default signal set used, for example, in + /// methods. + static sigset_t *default_mask (void); + + /// Returns the current thread hook for the process. + static ACE_Thread_Hook *thread_hook (void); + + /// Returns the existing thread hook and assign a . + static ACE_Thread_Hook *thread_hook (ACE_Thread_Hook *new_thread_hook); + +#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) + /// Get/Set TSS exception action. + static ACE_SEH_EXCEPT_HANDLER seh_except_selector (void); + static ACE_SEH_EXCEPT_HANDLER seh_except_selector (ACE_SEH_EXCEPT_HANDLER); + + static ACE_SEH_EXCEPT_HANDLER seh_except_handler (void); + static ACE_SEH_EXCEPT_HANDLER seh_except_handler (ACE_SEH_EXCEPT_HANDLER); +#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ + +public: + // = Applications shouldn't use these so they're hidden here. + + // They're public so that the can be + // constructed/destructed in
with + // . + /// Constructor. + ACE_OS_Object_Manager (void); + + /// Destructor. + ~ACE_OS_Object_Manager (void); + +private: + /// Accessor to singleton instance. + static ACE_OS_Object_Manager *instance (void); + + /// Singleton instance pointer. + static ACE_OS_Object_Manager *instance_; + + /// Table of preallocated objects. + static void *preallocated_object[ACE_OS_PREALLOCATED_OBJECTS]; + + /// Default signal set used, for example, in ACE_Sig_Guard. + sigset_t *default_mask_; + + /// Thread hook that's used by this process. + ACE_Thread_Hook *thread_hook_; + + /// For at_exit support. + ACE_OS_Exit_Info exit_info_; + +#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) + /// These handlers determine how a thread handles win32 structured + /// exception. + ACE_SEH_EXCEPT_HANDLER seh_except_selector_; + ACE_SEH_EXCEPT_HANDLER seh_except_handler_; +#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ + + /// For support. + int at_exit (ACE_EXIT_HOOK func); + + /// For use by init () and fini (), to consolidate error reporting. + static void print_error_message (u_int line_number, const ACE_TCHAR *message); + + /// This class is for internal use by ACE_OS, etc., only. + friend class ACE_OS; + friend class ACE_Object_Manager; + friend class ACE_OS_Object_Manager_Manager; + friend class ACE_TSS_Cleanup; + friend class ACE_TSS_Emulation; + friend class ACE_Log_Msg; + friend void ACE_OS_Object_Manager_Internal_Exit_Hook (); +}; + +# if defined (ACE_LACKS_TIMEDWAIT_PROTOTYPES) +extern "C" ssize_t recv_timedwait (ACE_HANDLE handle, + char *buf, + int len, + int flags, + struct timespec *timeout); +extern "C" ssize_t read_timedwait (ACE_HANDLE handle, + char *buf, + size_t n, + struct timespec *timeout); +extern "C" ssize_t recvmsg_timedwait (ACE_HANDLE handle, + struct msghdr *msg, + int flags, + struct timespec *timeout); +extern "C" ssize_t recvfrom_timedwait (ACE_HANDLE handle, + char *buf, + int len, + int flags, + struct sockaddr *addr, + int + *addrlen, + struct timespec *timeout); +extern "C" ssize_t readv_timedwait (ACE_HANDLE handle, + iovec *iov, + int iovcnt, + struct timespec* timeout); +extern "C" ssize_t send_timedwait (ACE_HANDLE handle, + const char *buf, + int len, + int flags, + struct timespec *timeout); +extern "C" ssize_t write_timedwait (ACE_HANDLE handle, + const void *buf, + size_t n, + struct timespec *timeout); +extern "C" ssize_t sendmsg_timedwait (ACE_HANDLE handle, + ACE_SENDMSG_TYPE *msg, + int flags, + struct timespec *timeout); +extern "C" ssize_t sendto_timedwait (ACE_HANDLE handle, + const char *buf, + int len, + int flags, + const struct sockaddr *addr, + int addrlen, + struct timespec *timeout); +extern "C" ssize_t writev_timedwait (ACE_HANDLE handle, + ACE_WRITEV_TYPE *iov, + int iovcnt, + struct timespec *timeout); +# endif /* ACE_LACKS_TIMEDWAIT_PROTOTYPES */ + +# if defined (ACE_HAS_TSS_EMULATION) + // Allow config.h to set the default number of thread keys. +# if !defined (ACE_DEFAULT_THREAD_KEYS) +# define ACE_DEFAULT_THREAD_KEYS 64 +# endif /* ! ACE_DEFAULT_THREAD_KEYS */ + +// forward declaration +class ACE_TSS_Keys; + +/** + * @class ACE_TSS_Emulation + * + * @brief Thread-specific storage emulation. + * + * This provides a thread-specific storage implementation. + * It is intended for use on platforms that don't have a + * native TSS, or have a TSS with limitations such as the + * number of keys or lack of support for removing keys. + */ +class ACE_OS_Export ACE_TSS_Emulation +{ +public: + typedef void (*ACE_TSS_DESTRUCTOR)(void *value) /* throw () */; + + /// Maximum number of TSS keys allowed over the life of the program. + enum { ACE_TSS_THREAD_KEYS_MAX = ACE_DEFAULT_THREAD_KEYS }; + + /// Returns the total number of keys allocated so far. + static u_int total_keys (); + + /// Sets the argument to the next available key. Returns 0 on success, + /// -1 if no keys are available. + static int next_key (ACE_thread_key_t &key); + + /// Release a key that was used. This way the key can be given out in a + /// new request. Returns 0 on success, 1 if the key was not reserved. + static int release_key (ACE_thread_key_t key); + + /// Returns the exit hook associated with the key. Does _not_ check + /// for a valid key. + static ACE_TSS_DESTRUCTOR tss_destructor (const ACE_thread_key_t key); + + /// Associates the TSS destructor with the key. Does _not_ check + /// for a valid key. + static void tss_destructor (const ACE_thread_key_t key, + ACE_TSS_DESTRUCTOR destructor); + + /// Accesses the object referenced by key in the current thread's TSS array. + /// Does _not_ check for a valid key. + static void *&ts_object (const ACE_thread_key_t key); + + /** + * Setup an array to be used for local TSS. Returns the array + * address on success. Returns 0 if local TSS had already been + * setup for this thread. There is no corresponding tss_close () + * because it is not needed. + * NOTE: tss_open () is called by ACE for threads that it spawns. + * If your application spawns threads without using ACE, and it uses + * ACE's TSS emulation, each of those threads should call tss_open + * (). See the ace_thread_adapter () implementaiton for an example. + */ + static void *tss_open (void *ts_storage[ACE_TSS_THREAD_KEYS_MAX]); + + /// Shutdown TSS emulation. For use only by ACE_OS::cleanup_tss (). + static void tss_close (); + +private: + // Global TSS structures. + /// Contains the possible value of the next key to be allocated. Which key + /// is actually allocated is based on the tss_keys_used + static u_int total_keys_; + + /// Array of thread exit hooks (TSS destructors) that are called for each + /// key (that has one) when the thread exits. + static ACE_TSS_DESTRUCTOR tss_destructor_ [ACE_TSS_THREAD_KEYS_MAX]; + + /// TSS_Keys instance to administrate whether a specific key is in used + /// or not + static ACE_TSS_Keys tss_keys_used_; + +# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + /// Location of current thread's TSS array. + static void **tss_base (void* ts_storage[] = 0, u_int *ts_created = 0); +# else /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */ + /// Location of current thread's TSS array. + static void **&tss_base (); +# endif /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */ + +# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) + // Rely on native thread specific storage for the implementation, + // but just use one key. + static ACE_OS_thread_key_t native_tss_key_; + + // Used to indicate if native tss key has been allocated + static int key_created_; +# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ +}; + +# else /* ! ACE_HAS_TSS_EMULATION */ +# if defined (TLS_MINIMUM_AVAILABLE) + // WIN32 platforms define TLS_MINIMUM_AVAILABLE natively. +# define ACE_DEFAULT_THREAD_KEYS TLS_MINIMUM_AVAILABLE +# endif /* TSL_MINIMUM_AVAILABLE */ + +# endif /* ACE_HAS_TSS_EMULATION */ + +// moved ACE_TSS_Ref, ACE_TSS_Info, and ACE_TSS_Keys class +// declarations from OS.cpp so they are visible to the single +// file of template instantiations. +# if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) +/** + * @class ACE_TSS_Ref + * + * @brief "Reference count" for thread-specific storage keys. + * + * Since the doesn't allow duplicates, the + * "reference count" is the identify of the thread_id. + */ +class ACE_TSS_Ref +{ +public: + /// Constructor + ACE_TSS_Ref (ACE_thread_t id); + + /// Default constructor + ACE_TSS_Ref (void); + + /// Check for equality. + int operator== (const ACE_TSS_Ref &) const; + + /// Check for inequality. + int operator!= (const ACE_TSS_Ref &) const; + +// private: + + /// ID of thread using a specific key. + ACE_thread_t tid_; +}; + +/** + * @class ACE_TSS_Info + * + * @brief Thread Specific Key management. + * + * This class maps a key to a "destructor." + */ +class ACE_TSS_Info +{ +public: + /// Constructor + ACE_TSS_Info (ACE_thread_key_t key, + void (*dest)(void *) = 0, + void *tss_inst = 0); + + /// Default constructor + ACE_TSS_Info (void); + + /// Returns 1 if the key is in use, 0 if not. + int key_in_use (void) const { return thread_count_ != -1; } + + /// Mark the key as being in use if the flag is non-zero, or + /// not in use if the flag is 0. + void key_in_use (int flag) { thread_count_ = flag == 0 ? -1 : 1; } + + /// Check for equality. + int operator== (const ACE_TSS_Info &) const; + + /// Check for inequality. + int operator!= (const ACE_TSS_Info &) const; + + /// Dump the state. + void dump (void); + +private: + /// Key to the thread-specific storage item. + ACE_thread_key_t key_; + + /// "Destructor" that gets called when the item is finally released. + void (*destructor_)(void *); + + /// Pointer to ACE_TSS instance that has/will allocate the key. + void *tss_obj_; + + /// Count of threads that are using this key. Contains -1 when the + /// key is not in use. + int thread_count_; + + friend class ACE_TSS_Cleanup; +}; + +/** + * @class ACE_TSS_Keys + * + * @brief Collection of in-use flags for a thread's TSS keys. + * For internal use only by ACE_TSS_Cleanup; it is public because + * some compilers can't use nested classes for template instantiation + * parameters. + * + * Wrapper around array of whether each key is in use. A simple + * typedef doesn't work with Sun C++ 4.2. + */ +class ACE_TSS_Keys +{ +public: + /// Default constructor, to initialize all bits to zero (unused). + ACE_TSS_Keys (void); + + /// Mark the specified key as being in use, if it was not already so marked. + /// Returns 1 if the had already been marked, 0 if not. + int test_and_set (const ACE_thread_key_t key); + + /// Mark the specified key as not being in use, if it was not already so + /// cleared. Returns 1 if the key had already been cleared, 0 if not. + int test_and_clear (const ACE_thread_key_t key); + + /// Return whether the specific key is marked as in use. + /// Returns 1 if the key is been marked, 0 if not. + int is_set (const ACE_thread_key_t key) const; + +private: + /// For a given key, find the word and bit number that represent it. + static void find (const u_int key, u_int &word, u_int &bit); + + enum + { +# if ACE_SIZEOF_LONG == 8 + ACE_BITS_PER_WORD = 64, +# elif ACE_SIZEOF_LONG == 4 + ACE_BITS_PER_WORD = 32, +# else +# error ACE_TSS_Keys only supports 32 or 64 bit longs. +# endif /* ACE_SIZEOF_LONG == 8 */ + ACE_WORDS = (ACE_DEFAULT_THREAD_KEYS - 1) / ACE_BITS_PER_WORD + 1 + }; + + /// Bit flag collection. A bit value of 1 indicates that the key is in + /// use by this thread. + u_long key_bit_words_[ACE_WORDS]; +}; + +# endif /* defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) */ + +// Support non-scalar thread keys, such as with some POSIX +// implementations, e.g., MVS. +# if defined (ACE_HAS_NONSCALAR_THREAD_KEY_T) +# define ACE_KEY_INDEX(OBJ,KEY) \ + u_int OBJ; \ + ACE_OS::memcpy (&OBJ, &KEY, sizeof (u_int)) +# else +# define ACE_KEY_INDEX(OBJ,KEY) u_int OBJ = KEY +# endif /* ACE_HAS_NONSCALAR_THREAD_KEY_T */ + +// Some useful abstrations for expressions involving +// ACE_Allocator.malloc (). The difference between ACE_NEW_MALLOC* +// with ACE_ALLOCATOR* is that they call constructors also. + +# define ACE_ALLOCATOR_RETURN(POINTER,ALLOCATOR,RET_VAL) \ + do { POINTER = ALLOCATOR; \ + if (POINTER == 0) { errno = ENOMEM; return RET_VAL; } \ + } while (0) +# define ACE_ALLOCATOR(POINTER,ALLOCATOR) \ + do { POINTER = ALLOCATOR; \ + if (POINTER == 0) { errno = ENOMEM; return; } \ + } while (0) + +# define ACE_NEW_MALLOC_RETURN(POINTER,ALLOCATOR,CONSTRUCTOR,RET_VAL) \ + do { POINTER = ALLOCATOR; \ + if (POINTER == 0) { errno = ENOMEM; return RET_VAL;} \ + else { new (POINTER) CONSTRUCTOR; } \ + } while (0) +# define ACE_NEW_MALLOC(POINTER,ALLOCATOR,CONSTRUCTOR) \ + do { POINTER = ALLOCATOR; \ + if (POINTER == 0) { errno = ENOMEM; return;} \ + else { new (POINTER) CONSTRUCTOR; } \ + } while (0) + +# define ACE_NOOP(x) + +# define ACE_DES_NOFREE(POINTER,CLASS) \ + do { \ + if (POINTER) \ + { \ + (POINTER)->~CLASS (); \ + } \ + } \ + while (0) + +# define ACE_DES_ARRAY_NOFREE(POINTER,SIZE,CLASS) \ + do { \ + if (POINTER) \ + { \ + for (size_t i = 0; \ + i < SIZE; \ + ++i) \ + { \ + (&(POINTER)[i])->~CLASS (); \ + } \ + } \ + } \ + while (0) + +# define ACE_DES_FREE(POINTER,DEALLOCATOR,CLASS) \ + do { \ + if (POINTER) \ + { \ + (POINTER)->~CLASS (); \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) + +# define ACE_DES_ARRAY_FREE(POINTER,SIZE,DEALLOCATOR,CLASS) \ + do { \ + if (POINTER) \ + { \ + for (size_t i = 0; \ + i < SIZE; \ + ++i) \ + { \ + (&(POINTER)[i])->~CLASS (); \ + } \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) + +# if defined (ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR) +# define ACE_DES_NOFREE_TEMPLATE(POINTER,T_CLASS,T_PARAMETER) \ + do { \ + if (POINTER) \ + { \ + (POINTER)->~T_CLASS (); \ + } \ + } \ + while (0) +# define ACE_DES_ARRAY_NOFREE_TEMPLATE(POINTER,SIZE,T_CLASS,T_PARAMETER) \ + do { \ + if (POINTER) \ + { \ + for (size_t i = 0; \ + i < SIZE; \ + ++i) \ + { \ + (&(POINTER)[i])->~T_CLASS (); \ + } \ + } \ + } \ + while (0) +#if defined(__IBMCPP__) && (__IBMCPP__ >= 400) +# define ACE_DES_FREE_TEMPLATE(POINTER,DEALLOCATOR,T_CLASS,T_PARAMETER) \ + do { \ + if (POINTER) \ + { \ + (POINTER)->~T_CLASS T_PARAMETER (); \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) +#else +# define ACE_DES_FREE_TEMPLATE(POINTER,DEALLOCATOR,T_CLASS,T_PARAMETER) \ + do { \ + if (POINTER) \ + { \ + (POINTER)->~T_CLASS (); \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) +#endif /* defined(__IBMCPP__) && (__IBMCPP__ >= 400) */ +# define ACE_DES_ARRAY_FREE_TEMPLATE(POINTER,SIZE,DEALLOCATOR,T_CLASS,T_PARAMETER) \ + do { \ + if (POINTER) \ + { \ + for (size_t i = 0; \ + i < SIZE; \ + ++i) \ + { \ + (&(POINTER)[i])->~T_CLASS (); \ + } \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) +#if defined(__IBMCPP__) && (__IBMCPP__ >= 400) +# define ACE_DES_FREE_TEMPLATE2(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2) \ + do { \ + if (POINTER) \ + { \ + (POINTER)->~T_CLASS (); \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) +#else +# define ACE_DES_FREE_TEMPLATE2(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2) \ + do { \ + if (POINTER) \ + { \ + (POINTER)->~T_CLASS (); \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) +#endif /* defined(__IBMCPP__) && (__IBMCPP__ >= 400) */ +# define ACE_DES_FREE_TEMPLATE3(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2,T_PARAM3) \ + do { \ + if (POINTER) \ + { \ + (POINTER)->~T_CLASS (); \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) +# define ACE_DES_FREE_TEMPLATE4(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2,T_PARAM3, T_PARAM4) \ + do { \ + if (POINTER) \ + { \ + (POINTER)->~T_CLASS (); \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) +# define ACE_DES_ARRAY_FREE_TEMPLATE2(POINTER,SIZE,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2) \ + do { \ + if (POINTER) \ + { \ + for (size_t i = 0; \ + i < SIZE; \ + ++i) \ + { \ + (&(POINTER)[i])->~T_CLASS (); \ + } \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) +# else /* ! ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR */ +# define ACE_DES_NOFREE_TEMPLATE(POINTER,T_CLASS,T_PARAMETER) \ + do { \ + if (POINTER) \ + { \ + (POINTER)->T_CLASS T_PARAMETER::~T_CLASS (); \ + } \ + } \ + while (0) +# define ACE_DES_ARRAY_NOFREE_TEMPLATE(POINTER,SIZE,T_CLASS,T_PARAMETER) \ + do { \ + if (POINTER) \ + { \ + for (size_t i = 0; \ + i < SIZE; \ + ++i) \ + { \ + (POINTER)[i].T_CLASS T_PARAMETER::~T_CLASS (); \ + } \ + } \ + } \ + while (0) +# if defined (__Lynx__) && __LYNXOS_SDK_VERSION == 199701L + // LynxOS 3.0.0's g++ has trouble with the real versions of these. +# define ACE_DES_FREE_TEMPLATE(POINTER,DEALLOCATOR,T_CLASS,T_PARAMETER) +# define ACE_DES_ARRAY_FREE_TEMPLATE(POINTER,DEALLOCATOR,T_CLASS,T_PARAMETER) +# define ACE_DES_FREE_TEMPLATE2(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2) +# define ACE_DES_FREE_TEMPLATE3(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2) +# define ACE_DES_FREE_TEMPLATE4(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2) +# define ACE_DES_ARRAY_FREE_TEMPLATE2(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2) +# else +# define ACE_DES_FREE_TEMPLATE(POINTER,DEALLOCATOR,T_CLASS,T_PARAMETER) \ + do { \ + if (POINTER) \ + { \ + POINTER->T_CLASS T_PARAMETER::~T_CLASS (); \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) +# define ACE_DES_ARRAY_FREE_TEMPLATE(POINTER,SIZE,DEALLOCATOR,T_CLASS,T_PARAMETER) \ + do { \ + if (POINTER) \ + { \ + for (size_t i = 0; \ + i < SIZE; \ + ++i) \ + { \ + POINTER[i].T_CLASS T_PARAMETER::~T_CLASS (); \ + } \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) +# define ACE_DES_FREE_TEMPLATE2(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2) \ + do { \ + if (POINTER) \ + { \ + POINTER->T_CLASS ::~T_CLASS (); \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) +# define ACE_DES_FREE_TEMPLATE3(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2,T_PARAM3) \ + do { \ + if (POINTER) \ + { \ + POINTER->T_CLASS ::~T_CLASS (); \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) +# define ACE_DES_FREE_TEMPLATE4(POINTER,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2,T_PARAM3,T_PARAM4) \ + do { \ + if (POINTER) \ + { \ + POINTER->T_CLASS ::~T_CLASS (); \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) +# define ACE_DES_ARRAY_FREE_TEMPLATE2(POINTER,SIZE,DEALLOCATOR,T_CLASS,T_PARAM1,T_PARAM2) \ + do { \ + if (POINTER) \ + { \ + for (size_t i = 0; \ + i < SIZE; \ + ++i) \ + { \ + POINTER[i].T_CLASS ::~T_CLASS (); \ + } \ + DEALLOCATOR (POINTER); \ + } \ + } \ + while (0) +# endif /* defined (__Lynx__) && __LYNXOS_SDK_VERSION == 199701L */ +# endif /* defined ! ACE_HAS_WORKING_EXPLICIT_TEMPLATE_DESTRUCTOR */ + +#if defined (ACE_HAS_PACE) +# define ACE_PTHREAD_CLEANUP_PUSH(A) pace_pthread_cleanup_push (ACE_OS::mutex_lock_cleanup, (void *) A); +# define ACE_PTHREAD_CLEANUP_POP(A) pace_pthread_cleanup_pop(A) +# elif defined (ACE_HAS_THR_C_FUNC) +// This is necessary to work around nasty problems with MVS C++. +extern "C" ACE_OS_Export void ace_mutex_lock_cleanup_adapter (void *args); +# define ACE_PTHREAD_CLEANUP_PUSH(A) pthread_cleanup_push (ace_mutex_lock_cleanup_adapter, (void *) A); +# define ACE_PTHREAD_CLEANUP_POP(A) pthread_cleanup_pop(A) +# elif defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CLEANUP) +// Though we are defining a extern "C" function to match the prototype of +// pthread_cleanup_push, it is undone by the Solaris header file +// /usr/include/pthread.h. So this macro generates a warning under Solaris +// with SunCC. This is a bug in the Solaris header file. +extern "C" ACE_OS_Export void ace_mutex_lock_cleanup_adapter (void *args); +# define ACE_PTHREAD_CLEANUP_PUSH(A) pthread_cleanup_push (ace_mutex_lock_cleanup_adapter, (void *) A); +# define ACE_PTHREAD_CLEANUP_POP(A) pthread_cleanup_pop(A) +# else +# define ACE_PTHREAD_CLEANUP_PUSH(A) +# define ACE_PTHREAD_CLEANUP_POP(A) +# endif /* ACE_HAS_PACE */ + +# if !defined (ACE_DEFAULT_MUTEX_A) +# define ACE_DEFAULT_MUTEX_A "ACE_MUTEX" +# endif /* ACE_DEFAULT_MUTEX_A */ + +# if defined (ACE_HAS_WCHAR) +# define ACE_DEFAULT_MUTEX_W ACE_TEXT_WIDE(ACE_DEFAULT_MUTEX_A) +# endif /* ACE_HAS_WCHAR */ + +# define ACE_DEFAULT_MUTEX ACE_LIB_TEXT (ACE_DEFAULT_MUTEX_A) + +# if !defined (ACE_MAIN) +# define ACE_MAIN main +# endif /* ! ACE_MAIN */ + +# if defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER) +# if !defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) +# define ACE_HAS_NONSTATIC_OBJECT_MANAGER +# endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER */ +# endif /* ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER */ + +# if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) && !defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER) + +# if !defined (ACE_HAS_MINIMAL_ACE_OS) +# include "ace/Object_Manager.h" +# endif /* ! ACE_HAS_MINIMAL_ACE_OS */ + +// Rename "main ()" on platforms that don't allow it to be called "main ()". + +// Also, create ACE_Object_Manager static instance(s) in "main ()". +// ACE_MAIN_OBJECT_MANAGER defines the ACE_Object_Manager(s) that will +// be instantiated on the stack of main (). Note that it is only used +// when compiling main (): its value does not affect the contents of +// ace/OS.o. +# if !defined (ACE_MAIN_OBJECT_MANAGER) +# define ACE_MAIN_OBJECT_MANAGER \ + ACE_OS_Object_Manager ace_os_object_manager; \ + ACE_Object_Manager ace_object_manager; +# endif /* ! ACE_MAIN_OBJECT_MANAGER */ + +# if defined (ACE_PSOSIM) +// PSOSIM root lacks the standard argc, argv command line parameters, +// create dummy argc and argv in the "real" main and pass to "user" main. +// NOTE: ACE_MAIN must be defined to give the return type as well as the +// name of the entry point. +# define main \ +ace_main_i (int, char *[]); /* forward declaration */ \ +ACE_MAIN () /* user's entry point, e.g., "main" w/out argc, argv */ \ +{ \ + int argc = 1; /* dummy arg count */ \ + char *argv[] = {"psosim"}; /* dummy arg list */ \ + ACE_MAIN_OBJECT_MANAGER \ + int ret_val = -1; /* assume the worst */ \ + if (ACE_PSOS_Time_t::init_simulator_time ()) /* init simulator time */ \ + { \ + ACE_ERROR((LM_ERROR, "init_simulator_time failed\n")); /* report */ \ + } \ + else \ + { \ + ret_val = ace_main_i (argc, argv); /* call user main, save result */ \ + } \ + ACE_OS::exit (ret_val); /* pass code to simulator exit */ \ +} \ +int \ +ace_main_i +# elif defined (ACE_PSOS) && defined (ACE_PSOS_LACKS_ARGC_ARGV) +// PSOS root lacks the standard argc, argv command line parameters, +// create dummy argc and argv in the "real" main and pass to "user" main. +// Ignore return value from user main as well. NOTE: ACE_MAIN must be +// defined to give the return type as well as the name of the entry point +# define main \ +ace_main_i (int, char *[]); /* forward declaration */ \ +ACE_MAIN () /* user's entry point, e.g., "main" w/out argc, argv */ \ +{ \ + int argc = 1; /* dummy arg count */ \ + char *argv[] = {"root"}; /* dummy arg list */ \ + ACE_MAIN_OBJECT_MANAGER \ + ace_main_i (argc, argv); /* call user main, ignore result */ \ +} \ +int \ +ace_main_i +# else +# define main \ +ace_main_i (int, ACE_TCHAR *[]); /* forward declaration */ \ +int \ +ACE_MAIN (int argc, ACE_TCHAR *argv[]) /* user's entry point, e.g., main */ \ +{ \ + ACE_MAIN_OBJECT_MANAGER \ + return ace_main_i (argc, argv); /* what the user calls "main" */ \ +} \ +int \ +ace_main_i +# if defined (ACE_WIN32) && defined (UNICODE) +# define wmain \ +ace_main_i (int, ACE_TCHAR *[]); /* forward declaration */ \ +int \ +wmain (int argc, ACE_TCHAR *argv[]) /* user's entry point, e.g., main */ \ +{ \ + ACE_MAIN_OBJECT_MANAGER \ + return ace_main_i (argc, argv); /* what the user calls "main" */ \ +} \ +int \ +ace_main_i +# endif /* ACE_WIN32 && UNICODE */ +# endif /* ACE_PSOSIM */ +# endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER && !ACE_HAS_WINCE && !ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER */ + +#if defined (ACE_HAS_WINCE) + +/** + * @class ACE_CE_Bridge + * + * @brief This class bridges between ACE's default text output windows + * and the original ACE program. + * + * As there is no such thing as text-based programs on Windows + * CE. We need to create a windows to read the command prompt + * and bridge the output windows with the original ACE program + * entry point. You'll need to link your program with + * "ace-windows.lib" for this to work. You can refer to + * $ACE_ROOT/WindowsCE/Main for how I use a dialog box to run + * the original ACE programs. This is certainly not the only + * way to use ACE in Windows programs. + */ +class ACE_OS_Export ACE_CE_Bridge + +{ +public: + /// Default ctor. + ACE_CE_Bridge (void); + + /// Construct and set the default windows. + ACE_CE_Bridge (HWND, int notification, int idc); + + /// Default dtor. + ~ACE_CE_Bridge (void); + + /// Specify which window to use. + void set_window (HWND, int notification, int idc); + + /// Set the default window. + void set_self_default (void); + + /// Access functions. + int notification (void); + int idc (void); + HWND window (void); + + /// Get the reference of default ACE_CE_BRIDGE. + static ACE_CE_Bridge *get_default_winbridge (void); + + /// Write a string to windows. + int write_msg (const ACE_TCHAR *str); + +#if 0 + /// Write a CString to windows. Notice that the CString object will + /// be freed by windows. + int write_msg (CString *cs); +#endif /* 0 */ +private: + // @@ We should use a allocator here. + + /// A pointer to the window that knows how to + /// handle ACE related messages. + HWND text_output_; + + /// Notification of the window that receives WM_COMMAND when + /// outputing strings. + int notification_; + + /// IDC code of the window that receives WM_COMMAND when + /// outputing strings. + int idc_; + + ACE_TCHAR *cmdline_; + + /// A pointer to the default ACE_CE_BRIDGE obj. + static ACE_CE_Bridge *default_text_bridge_; +}; + +# endif /* ACE_HAS_WINCE */ + +# if defined (ACE_WIN32) && ! defined (ACE_HAS_WINCE) \ + && ! defined (ACE_HAS_PHARLAP) +typedef TRANSMIT_FILE_BUFFERS ACE_TRANSMIT_FILE_BUFFERS; +typedef LPTRANSMIT_FILE_BUFFERS ACE_LPTRANSMIT_FILE_BUFFERS; +typedef PTRANSMIT_FILE_BUFFERS ACE_PTRANSMIT_FILE_BUFFERS; + +# define ACE_INFINITE INFINITE +# define ACE_STATUS_TIMEOUT STATUS_TIMEOUT +# define ACE_WAIT_FAILED WAIT_FAILED +# define ACE_WAIT_TIMEOUT WAIT_TIMEOUT +# else /* ACE_WIN32 */ +struct ACE_TRANSMIT_FILE_BUFFERS +{ + void *Head; + size_t HeadLength; + void *Tail; + size_t TailLength; +}; +typedef ACE_TRANSMIT_FILE_BUFFERS* ACE_PTRANSMIT_FILE_BUFFERS; +typedef ACE_TRANSMIT_FILE_BUFFERS* ACE_LPTRANSMIT_FILE_BUFFERS; + +# if !defined (ACE_INFINITE) +# define ACE_INFINITE LONG_MAX +# endif /* ACE_INFINITE */ +# define ACE_STATUS_TIMEOUT LONG_MAX +# define ACE_WAIT_FAILED LONG_MAX +# define ACE_WAIT_TIMEOUT LONG_MAX +# endif /* ACE_WIN32 */ + +# if 0 +# if !defined (ACE_HAS_MINIMAL_ACE_OS) +# include "ace/Trace.h" +# endif /* ! ACE_HAS_MINIMAL_ACE_OS */ +#endif + +# if defined (ACE_HAS_INLINED_OSCALLS) +# if defined (ACE_INLINE) +# undef ACE_INLINE +# endif /* ACE_INLINE */ +# define ACE_INLINE inline +# include "OS.i" +# endif /* ACE_HAS_INLINED_OSCALLS */ + +// Byte swapping macros to deal with differences between little endian +// and big endian machines. Note that "long" here refers to 32 bit +// quantities. +# define ACE_SWAP_LONG(L) ((ACE_SWAP_WORD ((L) & 0xFFFF) << 16) \ + | ACE_SWAP_WORD(((L) >> 16) & 0xFFFF)) +# define ACE_SWAP_WORD(L) ((((L) & 0x00FF) << 8) | (((L) & 0xFF00) >> 8)) + +# if defined (ACE_LITTLE_ENDIAN) +# define ACE_HTONL(X) ACE_SWAP_LONG (X) +# define ACE_NTOHL(X) ACE_SWAP_LONG (X) +# define ACE_IDL_NCTOHL(X) (X) +# define ACE_IDL_NSTOHL(X) (X) +# else +# define ACE_HTONL(X) X +# define ACE_NTOHL(X) X +# define ACE_IDL_NCTOHL(X) (X << 24) +# define ACE_IDL_NSTOHL(X) ((X) << 16) +# endif /* ACE_LITTLE_ENDIAN */ + +# if defined (ACE_LITTLE_ENDIAN) +# define ACE_HTONS(x) ACE_SWAP_WORD(x) +# define ACE_NTOHS(x) ACE_SWAP_WORD(x) +# else +# define ACE_HTONS(x) x +# define ACE_NTOHS(x) x +# endif /* ACE_LITTLE_ENDIAN */ + +# if defined (ACE_HAS_AIO_CALLS) + // = Giving unique ACE scoped names for some important + // RTSignal-Related constants. Becuase sometimes, different + // platforms use different names for these constants. + + // Number of realtime signals provided in the system. + // _POSIX_RTSIG_MAX is the upper limit on the number of real time + // signals supported in a posix-4 compliant system. +# if defined (_POSIX_RTSIG_MAX) +# define ACE_RTSIG_MAX _POSIX_RTSIG_MAX +# else /* not _POSIX_RTSIG_MAX */ + // POSIX-4 compilant system has to provide atleast 8 RT signals. + // @@ Make sure the platform does *not* define this constant with + // some other name. If yes, use that instead of 8. +# define ACE_RTSIG_MAX 8 +# endif /* _POSIX_RTSIG_MAX */ +# endif /* ACE_HAS_AIO_CALLS */ + + // Wrapping around wait status macros for platforms that + // lack them. + + // Evaluates to a non-zero value if status was returned for a child + // process that terminated normally. 0 means status wasn't + // returned. +#if !defined (WIFEXITED) +# define WIFEXITED(stat) 1 +#endif /* WIFEXITED */ + + // If the value of WIFEXITED(stat) is non-zero, this macro evaluates + // to the exit code that the child process exit(3C), or the value + // that the child process returned from main. Peaceful exit code is + // 0. +#if !defined (WEXITSTATUS) +# define WEXITSTATUS(stat) stat +#endif /* WEXITSTATUS */ + + // Evaluates to a non-zero value if status was returned for a child + // process that terminated due to the receipt of a signal. 0 means + // status wasnt returned. +#if !defined (WIFSIGNALED) +# define WIFSIGNALED(stat) 0 +#endif /* WIFSIGNALED */ + + // If the value of WIFSIGNALED(stat) is non-zero, this macro + // evaluates to the number of the signal that caused the + // termination of the child process. +#if !defined (WTERMSIG) +# define WTERMSIG(stat) 0 +#endif /* WTERMSIG */ + +#if !defined (WIFSTOPPED) +# define WIFSTOPPED(stat) 0 +#endif /* WIFSTOPPED */ + +#if !defined (WSTOPSIG) +# define WSTOPSIG(stat) 0 +#endif /* WSTOPSIG */ + +#if !defined (WIFCONTINUED) +# define WIFCONTINUED(stat) 0 +#endif /* WIFCONTINUED */ + +#if !defined (WCOREDUMP) +# define WCOREDUMP(stat) 0 +#endif /* WCOREDUMP */ + +// Stuff used by the ACE CDR classes. +#if defined ACE_LITTLE_ENDIAN +# define ACE_CDR_BYTE_ORDER 1 +// little endian encapsulation byte order has value = 1 +#else /* ! ACE_LITTLE_ENDIAN */ +# define ACE_CDR_BYTE_ORDER 0 +// big endian encapsulation byte order has value = 0 +#endif /* ! ACE_LITTLE_ENDIAN */ + +/** + * @name Default values to control CDR classes memory allocation + * strategies + */ +//@{ + +/// Control the initial size of all CDR buffers, application +/// developers may want to optimize this value to fit their request +/// size +#if !defined (ACE_DEFAULT_CDR_BUFSIZE) +# define ACE_DEFAULT_CDR_BUFSIZE 512 +#endif /* ACE_DEFAULT_CDR_BUFSIZE */ + +/// Stop exponential growth of CDR buffers to avoid overallocation +#if !defined (ACE_DEFAULT_CDR_EXP_GROWTH_MAX) +# define ACE_DEFAULT_CDR_EXP_GROWTH_MAX 65536 +#endif /* ACE_DEFAULT_CDR_EXP_GROWTH_MAX */ + +/// Control CDR buffer growth after maximum exponential growth is +/// reached +#if !defined (ACE_DEFAULT_CDR_LINEAR_GROWTH_CHUNK) +# define ACE_DEFAULT_CDR_LINEAR_GROWTH_CHUNK 65536 +#endif /* ACE_DEFAULT_CDR_LINEAR_GROWTH_CHUNK */ +//@} + +/// Control the zero-copy optimizations for octet sequences +/** + * Large octet sequences can be sent without any copies by chaining + * them in the list of message blocks that represent a single CDR + * stream. However, if the octet sequence is too small the zero copy + * optimizations actually hurt performance. Octet sequences smaller + * than this value will be copied. + */ +#if !defined (ACE_DEFAULT_CDR_MEMCPY_TRADEOFF) +#define ACE_DEFAULT_CDR_MEMCPY_TRADEOFF 256 +#endif /* ACE_DEFAULT_CDR_MEMCPY_TRADEOFF */ + +/** + * In some environments it is useful to swap the bytes on write, for + * instance: a fast server can be feeding a lot of slow clients that + * happen to have the wrong byte order. + * Because this is a rarely used feature we disable it by default to + * minimize footprint. + * This macro enables the functionality, but we still need a way to + * activate it on a per-connection basis. + */ +// #define ACE_ENABLE_SWAP_ON_WRITE + +/** + * In some environements we never need to swap bytes when reading, for + * instance embebbed systems (such as avionics) or homogenous + * networks. + * Setting this macro disables the capabilities to demarshall streams + * in the wrong byte order. + */ +// #define ACE_DISABLE_SWAP_ON_READ + + +//@{ +/** + * @name Efficiently compute aligned pointers to powers of 2 boundaries. + */ + +/** + * Efficiently align "value" up to "alignment", knowing that all such + * boundaries are binary powers and that we're using two's complement + * arithmetic. + * + * Since the alignment is a power of two its binary representation is: + * + * alignment = 0...010...0 + * + * hence + * + * alignment - 1 = 0...001...1 = T1 + * + * so the complement is: + * + * ~(alignment - 1) = 1...110...0 = T2 + * + * Notice that there is a multiple of in the range + * [, + T1], also notice that if + * + * X = ( + T1 ) & T2 + * + * then + * + * <= X <= + T1 + * + * because the & operator only changes the last bits, and since X is a + * multiple of (its last bits are zero) we have found the + * multiple we wanted. + */ +/// Return the next integer aligned to a required boundary +/** + * @param ptr the base pointer + * @param alignment the required alignment + */ +#define ACE_align_binary(ptr, alignment) \ + ((ptr + ((ptr_arith_t)((alignment)-1))) & (~((ptr_arith_t)((alignment)-1)))) + +/// Return the next address aligned to a required boundary +#define ACE_ptr_align_binary(ptr, alignment) \ + ((char *) ACE_align_binary (((ptr_arith_t) (ptr)), (alignment))) +//@} + +// Defining POSIX4 real-time signal range. +#if defined ACE_HAS_AIO_CALLS +#define ACE_SIGRTMIN SIGRTMIN +#define ACE_SIGRTMAX SIGRTMAX +#else /* !ACE_HAS_AIO_CALLS */ +#define ACE_SIGRTMIN 0 +#define ACE_SIGRTMAX 0 +#endif /* ACE_HAS_AIO_CALLS */ + +# if defined (ACE_LACKS_SYS_NERR) +extern ACE_OS_Export int sys_nerr; +# endif /* ACE_LACKS_SYS_NERR */ + +#if defined (ACE_LEGACY_MODE) +# include "ace/Log_Msg.h" +# include "ace/Thread_Hook.h" +# include "ace/Thread_Adapter.h" +# include "ace/Thread_Exit.h" +# include "ace/Thread_Control.h" +#endif /* ACE_LEGACY_MODE */ + +#include "ace/post.h" +#endif /* ACE_OS_H */ diff --git a/ace/OS/OS.i b/ace/OS/OS.i new file mode 100644 index 00000000000..1b4fa6c33b6 --- /dev/null +++ b/ace/OS/OS.i @@ -0,0 +1,11666 @@ +// -*- C++ -*- +// $Id$ + +#if defined (__CYGWIN32__) +# include /**/ +#endif + +#if !defined (ACE_HAS_INLINED_OSCALLS) +# undef ACE_INLINE +# define ACE_INLINE +#endif /* ACE_HAS_INLINED_OSCALLS */ + +#if defined (ACE_LACKS_RLIMIT_PROTOTYPE) +int getrlimit (int resource, struct rlimit *rlp); +int setrlimit (int resource, const struct rlimit *rlp); +#endif /* ACE_LACKS_RLIMIT_PROTOTYPE */ + +#if !defined (ACE_HAS_STRERROR) +# if defined (ACE_HAS_SYS_ERRLIST) +extern char *sys_errlist[]; +# define strerror(err) sys_errlist[err] +# else +# define strerror(err) "strerror is unsupported" +# endif /* ACE_HAS_SYS_ERRLIST */ +#endif /* !ACE_HAS_STERROR */ + +#if defined (ACE_HAS_SYS_SIGLIST) +# if !defined (_sys_siglist) +# define _sys_siglist sys_siglist +# endif /* !defined (sys_siglist) */ +//extern char **_sys_siglist; +#endif /* ACE_HAS_SYS_SIGLIST */ + +#if defined (ACE_HAS_SOCKLEN_T) +typedef socklen_t ACE_SOCKET_LEN; +#elif defined (ACE_HAS_SIZET_SOCKET_LEN) +typedef size_t ACE_SOCKET_LEN; +#else +typedef int ACE_SOCKET_LEN; +#endif /* ACE_HAS_SIZET_SOCKET_LEN */ + +#if defined (ACE_LACKS_CONST_STRBUF_PTR) +typedef struct strbuf *ACE_STRBUF_TYPE; +#else +typedef const struct strbuf *ACE_STRBUF_TYPE; +#endif /* ACE_LACKS_CONST_STRBUF_PTR */ + +#if defined (ACE_HAS_VOIDPTR_SOCKOPT) +typedef void *ACE_SOCKOPT_TYPE1; +#elif defined (ACE_HAS_CHARPTR_SOCKOPT) +typedef char *ACE_SOCKOPT_TYPE1; +#else +typedef const char *ACE_SOCKOPT_TYPE1; +#endif /* ACE_HAS_VOIDPTR_SOCKOPT */ + +#if !defined (_BSD_SOURCE) && \ + !defined (_XOPEN_SOURCE) && !defined (_XOPEN_SOURCE_EXTENDED) +# if defined (ACE_LACKS_SETREUID_PROTOTYPE) +extern "C" { +extern int setreuid (uid_t ruid, uid_t euid); +} +# endif /* ACE_LACKS_SETREUID_PROTOTYPE */ + +# if defined (ACE_LACKS_SETREGID_PROTOTYPE) +extern "C" { +extern int setregid (gid_t rgid, gid_t egid); +} +# endif /* ACE_LACKS_SETREGID_PROTOTYPE */ +#endif /* !_BSD_SOURCE && !_XOPEN_SOURCE && !_XOPEN_SOURCE_EXTENDED */ + +#if defined (ACE_NEEDS_FTRUNCATE) +extern "C" ACE_Export int ftruncate (ACE_HANDLE handle, long len); +#endif /* ACE_NEEDS_FTRUNCATE */ + +#if defined (ACE_HAS_VOIDPTR_MMAP) +// Needed for some odd OS's (e.g., SGI). +typedef void *ACE_MMAP_TYPE; +#else +typedef char *ACE_MMAP_TYPE; +#endif /* ACE_HAS_VOIDPTR_MMAP */ + +#if defined (ACE_HAS_XLI) +# include /**/ +#endif /* ACE_HAS_XLI */ + +#if defined (_M_UNIX) +extern "C" int _dlclose (void *); +extern "C" char *_dlerror (void); +extern "C" void *_dlopen (const char *, int); +extern "C" void * _dlsym (void *, const char *); +#endif /* _M_UNIX */ + +#if !defined (ACE_HAS_CPLUSPLUS_HEADERS) +# include /**/ +# include /**/ +#endif /* ACE_HAS_CPLUSPLUS_HEADERS */ + +#if defined (ACE_HAS_SYSENT_H) +# include /**/ +#endif /* ACE_HAS_SYSENT_H_*/ + +#if defined (ACE_USES_STD_NAMESPACE_FOR_STDC_LIB) && \ + (ACE_USES_STD_NAMESPACE_FOR_STDC_LIB != 0) +using std::bsearch; +using std::qsort; +# if defined (ACE_WIN32) +using std::_tzset; +# else +using std::tzset; +# endif +using std::ctime; +using std::localtime; +using std::gmtime; +using std::asctime; +using std::strftime; +#endif /* ACE_USES_STD_NAMESPACE_FOR_STDC_LIB */ + +#if defined (ACE_HAS_SVR4_GETTIMEOFDAY) +# if !defined (m88k) && !defined (SCO) +extern "C" int gettimeofday (struct timeval *tp, void * = 0); +# else +extern "C" int gettimeofday (struct timeval *tp); +# endif /* !m88k && !SCO */ +#elif defined (ACE_HAS_OSF1_GETTIMEOFDAY) +extern "C" int gettimeofday (struct timeval *tp, struct timezone * = 0); +#elif defined (ACE_HAS_SUNOS4_GETTIMEOFDAY) +# define ACE_HAS_SVR4_GETTIMEOFDAY +#endif /* ACE_HAS_SVR4_GETTIMEOFDAY */ + +#if defined (ACE_LACKS_CONST_TIMESPEC_PTR) +typedef struct timespec * ACE_TIMESPEC_PTR; +#else +typedef const struct timespec * ACE_TIMESPEC_PTR; +#endif /* HPUX */ + +#if !defined (ACE_LACKS_MALLOC_H) +# include /**/ +#endif /* ACE_LACKS_MALLOC_H */ + +// Returns the value of the object as a timeval. + +ACE_INLINE +ACE_Time_Value::operator timeval () const +{ + ACE_OS_TRACE ("ACE_Time_Value::operator timeval"); + return this->tv_; +} + +// Returns a pointer to the object as a timeval. + +ACE_INLINE +ACE_Time_Value::operator const timeval * () const +{ + ACE_OS_TRACE ("ACE_Time_Value::operator const timeval *"); + return (const timeval *) &this->tv_; +} + +ACE_INLINE void +ACE_Time_Value::set (long sec, long usec) +{ + // ACE_OS_TRACE ("ACE_Time_Value::set"); + this->tv_.tv_sec = sec; + this->tv_.tv_usec = usec; +} + +ACE_INLINE void +ACE_Time_Value::set (double d) +{ + // ACE_OS_TRACE ("ACE_Time_Value::set"); + long l = (long) d; + this->tv_.tv_sec = l; + this->tv_.tv_usec = (long) ((d - (double) l) * ACE_ONE_SECOND_IN_USECS); + this->normalize (); +} + +// Initializes a timespec_t. Note that this approach loses precision +// since it converts the nano-seconds into micro-seconds. But then +// again, do any real systems have nano-second timer precision?! + +ACE_INLINE void +ACE_Time_Value::set (const timespec_t &tv) +{ + // ACE_OS_TRACE ("ACE_Time_Value::set"); +#if ! defined(ACE_HAS_BROKEN_TIMESPEC_MEMBERS) + this->tv_.tv_sec = tv.tv_sec; + // Convert nanoseconds into microseconds. + this->tv_.tv_usec = tv.tv_nsec / 1000; +#else + this->tv_.tv_sec = tv.ts_sec; + // Convert nanoseconds into microseconds. + this->tv_.tv_usec = tv.ts_nsec / 1000; +#endif /* ACE_HAS_BROKEN_TIMESPEC_MEMBERS */ + + this->normalize (); +} + +ACE_INLINE void +ACE_Time_Value::set (const timeval &tv) +{ + // ACE_OS_TRACE ("ACE_Time_Value::set"); + this->tv_.tv_sec = tv.tv_sec; + this->tv_.tv_usec = tv.tv_usec; + + this->normalize (); +} + +ACE_INLINE +ACE_Time_Value::ACE_Time_Value (const timeval &tv) + // : tv_ () +{ + // ACE_OS_TRACE ("ACE_Time_Value::ACE_Time_Value"); + this->set (tv); +} + +ACE_INLINE +ACE_Time_Value::ACE_Time_Value (void) + // : tv_ () +{ + // ACE_OS_TRACE ("ACE_Time_Value::ACE_Time_Value"); + this->set (0, 0); + + // Don't need to normalize time value of (0, 0). +} + +ACE_INLINE +ACE_Time_Value::ACE_Time_Value (long sec, long usec) +{ + // ACE_OS_TRACE ("ACE_Time_Value::ACE_Time_Value"); + this->set (sec, usec); + this->normalize (); +} + +// Returns number of seconds. + +ACE_INLINE long +ACE_Time_Value::sec (void) const +{ + ACE_OS_TRACE ("ACE_Time_Value::sec"); + return this->tv_.tv_sec; +} + +// Sets the number of seconds. + +ACE_INLINE void +ACE_Time_Value::sec (long sec) +{ + ACE_OS_TRACE ("ACE_Time_Value::sec"); + this->tv_.tv_sec = sec; +} + +// Converts from Time_Value format into milli-seconds format. + +ACE_INLINE long +ACE_Time_Value::msec (void) const +{ + ACE_OS_TRACE ("ACE_Time_Value::msec"); + return this->tv_.tv_sec * 1000 + this->tv_.tv_usec / 1000; +} + +// Converts from milli-seconds format into Time_Value format. + +ACE_INLINE void +ACE_Time_Value::msec (long milliseconds) +{ + ACE_OS_TRACE ("ACE_Time_Value::msec"); + // Convert millisecond units to seconds; + this->tv_.tv_sec = milliseconds / 1000; + // Convert remainder to microseconds; + this->tv_.tv_usec = (milliseconds - (this->tv_.tv_sec * 1000)) * 1000; +} + +// Returns number of micro-seconds. + +ACE_INLINE long +ACE_Time_Value::usec (void) const +{ + ACE_OS_TRACE ("ACE_Time_Value::usec"); + return this->tv_.tv_usec; +} + +// Sets the number of micro-seconds. + +ACE_INLINE void +ACE_Time_Value::usec (long usec) +{ + ACE_OS_TRACE ("ACE_Time_Value::usec"); + this->tv_.tv_usec = usec; +} + +// Initializes the ACE_Time_Value object from another ACE_Time_Value + +ACE_INLINE +ACE_Time_Value::ACE_Time_Value (const ACE_Time_Value &tv) + : tv_ (tv.tv_) +{ + // ACE_OS_TRACE ("ACE_Time_Value::ACE_Time_Value"); +} + +ACE_INLINE ACE_Time_Value & +ACE_Time_Value::operator *= (double d) +{ + double time = this->sec () * ACE_ONE_SECOND_IN_USECS + this->usec (); + time *= d; + this->sec ((long)(time / ACE_ONE_SECOND_IN_USECS)); + this->usec (((long)time) % ACE_ONE_SECOND_IN_USECS); + + return *this; +} + +ACE_INLINE ACE_Time_Value +operator * (double d, const ACE_Time_Value &tv) +{ + return ACE_Time_Value (tv) *= d; +} + +ACE_INLINE ACE_Time_Value +operator * (const ACE_Time_Value &tv, double d) +{ + return ACE_Time_Value (tv) *= d; +} + +// True if tv1 > tv2. + +ACE_INLINE int +operator > (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2) +{ + ACE_OS_TRACE ("operator >"); + if (tv1.sec () > tv2.sec ()) + return 1; + else if (tv1.sec () == tv2.sec () + && tv1.usec () > tv2.usec ()) + return 1; + else + return 0; +} + +// True if tv1 >= tv2. + +ACE_INLINE int +operator >= (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2) +{ + ACE_OS_TRACE ("operator >="); + if (tv1.sec () > tv2.sec ()) + return 1; + else if (tv1.sec () == tv2.sec () + && tv1.usec () >= tv2.usec ()) + return 1; + else + return 0; +} + +// Returns the value of the object as a timespec_t. + +ACE_INLINE +ACE_Time_Value::operator timespec_t () const +{ + ACE_OS_TRACE ("ACE_Time_Value::operator timespec_t"); + timespec_t tv; +#if ! defined(ACE_HAS_BROKEN_TIMESPEC_MEMBERS) + tv.tv_sec = this->sec (); + // Convert microseconds into nanoseconds. + tv.tv_nsec = this->tv_.tv_usec * 1000; +#else + tv.ts_sec = this->sec (); + // Convert microseconds into nanoseconds. + tv.ts_nsec = this->tv_.tv_usec * 1000; +#endif /* ACE_HAS_BROKEN_TIMESPEC_MEMBERS */ + return tv; +} + +// Initializes the ACE_Time_Value object from a timespec_t. + +ACE_INLINE +ACE_Time_Value::ACE_Time_Value (const timespec_t &tv) + // : tv_ () +{ + // ACE_OS_TRACE ("ACE_Time_Value::ACE_Time_Value"); + this->set (tv); +} + +// True if tv1 < tv2. + +ACE_INLINE int +operator < (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2) +{ + ACE_OS_TRACE ("operator <"); + return tv2 > tv1; +} + +// True if tv1 >= tv2. + +ACE_INLINE int +operator <= (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2) +{ + ACE_OS_TRACE ("operator <="); + return tv2 >= tv1; +} + +// True if tv1 == tv2. + +ACE_INLINE int +operator == (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2) +{ + // ACE_OS_TRACE ("operator =="); + return tv1.sec () == tv2.sec () + && tv1.usec () == tv2.usec (); +} + +// True if tv1 != tv2. + +ACE_INLINE int +operator != (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2) +{ + // ACE_OS_TRACE ("operator !="); + return !(tv1 == tv2); +} + +// Add TV to this. + +ACE_INLINE ACE_Time_Value & +ACE_Time_Value::operator+= (const ACE_Time_Value &tv) +{ + ACE_OS_TRACE ("ACE_Time_Value::operator+="); + this->sec (this->sec () + tv.sec ()); + this->usec (this->usec () + tv.usec ()); + this->normalize (); + return *this; +} + +// Subtract TV to this. + +ACE_INLINE ACE_Time_Value & +ACE_Time_Value::operator-= (const ACE_Time_Value &tv) +{ + ACE_OS_TRACE ("ACE_Time_Value::operator-="); + this->sec (this->sec () - tv.sec ()); + this->usec (this->usec () - tv.usec ()); + this->normalize (); + return *this; +} + +// Adds two ACE_Time_Value objects together, returns the sum. + +ACE_INLINE ACE_Time_Value +operator + (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2) +{ + ACE_OS_TRACE ("operator +"); + ACE_Time_Value sum (tv1.sec () + tv2.sec (), + tv1.usec () + tv2.usec ()); + + sum.normalize (); + return sum; +} + +// Subtracts two ACE_Time_Value objects, returns the difference. + +ACE_INLINE ACE_Time_Value +operator - (const ACE_Time_Value &tv1, + const ACE_Time_Value &tv2) +{ + ACE_OS_TRACE ("operator -"); + ACE_Time_Value delta (tv1.sec () - tv2.sec (), + tv1.usec () - tv2.usec ()); + delta.normalize (); + return delta; +} + +ACE_INLINE int +ACE_OS::fcntl (ACE_HANDLE handle, int cmd, long arg) +{ + ACE_OS_TRACE ("ACE_OS::fcntl"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_fcntl (handle, cmd, arg), int, -1); +# elif defined (ACE_LACKS_FCNTL) + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (cmd); + ACE_UNUSED_ARG (arg); + ACE_NOTSUP_RETURN (-1); +# else + ACE_OSCALL_RETURN (::fcntl (handle, cmd, arg), int, -1); +# endif /* ACE_HAS_PACE */ +} + +#if !defined (ACE_LACKS_CHDIR) +ACE_INLINE int +ACE_OS::chdir (const char *path) +{ + ACE_OS_TRACE ("ACE_OS::chdir"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_chdir (path), int, -1); +#elif defined (VXWORKS) + ACE_OSCALL_RETURN (::chdir (ACE_const_cast (char *, path)), int, -1); + +#elif defined (ACE_PSOS_LACKS_PHILE) + ACE_UNUSED_ARG (path); + ACE_NOTSUP_RETURN (-1); + +#elif defined (ACE_PSOS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::change_dir ((char *) path), ace_result_), + int, -1); + +// This #elif seems weird... is Visual Age on NT not setting ACE_WIN32? +#elif !defined (ACE_WIN32) && !defined (AIX) && defined (__IBMCPP__) && (__IBMCPP__ >= 400) + ACE_OSCALL_RETURN (::_chdir (path), int, -1); + +#elif defined (ACE_HAS_WINCE) + ACE_UNUSED_ARG (path); + ACE_NOTSUP_RETURN (-1); + +#else + ACE_OSCALL_RETURN (::chdir (path), int, -1); + +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE int +ACE_OS::chdir (const wchar_t *path) +{ +#if defined (ACE_WIN32) + ACE_OSCALL_RETURN (::_wchdir (path), int, -1); +#else /* ACE_WIN32 */ + return ACE_OS::chdir (ACE_Wide_To_Ascii (path).char_rep ()); +#endif /* ACE_WIN32 */ +} +#endif /* ACE_HAS_WCHAR */ +#endif /* ACE_LACKS_CHDIR */ + +#if !defined (ACE_LACKS_MKTEMP) +ACE_INLINE ACE_TCHAR * +ACE_OS::mktemp (ACE_TCHAR *s) +{ +# if defined (ACE_WIN32) && defined (ACE_USES_WCHAR) + return ::_wmktemp (s); +# elif defined (ACE_WIN32) + return ::_mktemp (s); +# else /* ACE_WIN32 */ + return ::mktemp (s); +# endif /* ACE_WIN32 */ +} +#endif /* !ACE_LACKS_MKTEMP */ + +#if !defined (ACE_LACKS_MKSTEMP) +ACE_INLINE ACE_HANDLE +ACE_OS::mkstemp (ACE_TCHAR *s) +{ + return ::mkstemp (s); +} +#endif /* !ACE_LACKS_MKSTEMP */ + +ACE_INLINE int +ACE_OS::mkfifo (const ACE_TCHAR *file, mode_t mode) +{ + ACE_OS_TRACE ("ACE_OS::mkfifo"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_mkfifo (file, mode), int, -1); +#elif defined (ACE_LACKS_MKFIFO) + ACE_UNUSED_ARG (file); + ACE_UNUSED_ARG (mode); + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::mkfifo (file, mode), int, -1); +# endif /* ACE_HAS_PACE */ +} + +#if !defined (ACE_WIN32) + +// Matthew Stevens 7-10-95 Fix GNU GCC 2.7 for memchr() problem. +# if defined (ACE_HAS_GNU_CSTRING_H) +// Define this file to keep /usr/include/memory.h from being included. +# include /**/ +# else +# if defined (ACE_LACKS_MEMORY_H) +# if !defined (ACE_PSOS_DIAB_MIPS) +# include /**/ +# endif /* ACE_PSOS_DIAB_MIPS */ +# else +# include /**/ +# endif /* VXWORKS */ +# endif /* ACE_HAS_GNU_CSTRING_H */ + +// These prototypes are chronically lacking from many versions of +// UNIX. +extern "C" int isastream (int); +# if !defined (ACE_HAS_GETRUSAGE_PROTO) +extern "C" int getrusage (int who, struct rusage *rusage); +# endif /* ! ACE_HAS_GETRUSAGE_PROTO */ + +# if defined (ACE_LACKS_SYSCALL) +extern "C" int syscall (int, ACE_HANDLE, struct rusage *); +# endif /* ACE_LACKS_SYSCALL */ + +# if defined (ACE_LACKS_MKTEMP) +extern "C" char *mktemp (char *); +# endif /* ACE_LACKS_MKTEMP */ + +// The following are #defines and #includes that must be visible for +// ACE to compile it's OS wrapper class implementation correctly. We +// put them inside of here to reduce compiler overhead if we're not +// inlining... + +# if defined (ACE_HAS_REGEX) +# include /**/ +# endif /* ACE_HAS_REGEX */ + +# if defined (ACE_HAS_SYSINFO) +# include /**/ +# endif /* ACE_HAS_SYS_INFO */ + +# if defined (ACE_HAS_SYSCALL_H) +# include /**/ +# endif /* ACE_HAS_SYSCALL_H */ + +# if defined (UNIXWARE) /* See strcasecmp, below */ +# include /**/ +# endif /* UNIXWARE */ + +// Adapt the weird threading and synchronization routines (which +// return errno rather than -1) so that they return -1 and set errno. +// This is more consistent with the rest of ACE_OS and enables use to +// use the ACE_OSCALL* macros. +# if defined (VXWORKS) +# define ACE_ADAPT_RETVAL(OP,RESULT) ((RESULT = (OP)) != OK ? (errno = RESULT, -1) : 0) +# else +# define ACE_ADAPT_RETVAL(OP,RESULT) ((RESULT = (OP)) != 0 ? (errno = RESULT, -1) : 0) +# endif /* VXWORKS */ + +ACE_INLINE int +ACE_OS::fstat (ACE_HANDLE handle, ACE_stat *stp) +{ + ACE_OS_TRACE ("ACE_OS::fstat"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_fstat (handle, stp), int, -1); +#elif defined (ACE_PSOS_LACKS_PHILE) + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (stp); + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_PSOS) + ACE_OSCALL_RETURN (::fstat_f (handle, stp), int, -1); +#else +# if defined (ACE_HAS_X86_STAT_MACROS) + // Solaris for intel uses an macro for fstat(), this is a wrapper + // for _fxstat() use of the macro. + // causes compile and runtime problems. + ACE_OSCALL_RETURN (::_fxstat (_STAT_VER, handle, stp), int, -1); +# elif defined (ACE_WIN32) + ACE_OSCALL_RETURN (::_fstat (handle, stp), int, -1); +# else + ACE_OSCALL_RETURN (::fstat (handle, stp), int, -1); +# endif /* !ACE_HAS_X86_STAT_MACROS */ +#endif /* defined (ACE_HAS_PACE) */ +} + +ACE_INLINE int +ACE_OS::lstat (const char *file, ACE_stat *stp) +{ + ACE_OS_TRACE ("ACE_OS::lstat"); +# if defined (ACE_LACKS_LSTAT) || \ + defined (ACE_HAS_WINCE) || defined (ACE_WIN32) + ACE_UNUSED_ARG (file); + ACE_UNUSED_ARG (stp); + ACE_NOTSUP_RETURN (-1); +#else +# if defined (ACE_HAS_X86_STAT_MACROS) + // Solaris for intel uses an macro for lstat(), this macro is a + // wrapper for _lxstat(). + ACE_OSCALL_RETURN (::_lxstat (_STAT_VER, file, stp), int, -1); +# elif defined (ACE_WIN32) + ACE_OSCALL_RETURN (::_lstat (file, stp), int, -1); +# else /* !ACE_HAS_X86_STAT_MACROS */ + ACE_OSCALL_RETURN (::lstat (file, stp), int, -1); +#endif /* !ACE_HAS_X86_STAT_MACROS */ +# endif /* VXWORKS */ +} + +ACE_INLINE int +ACE_OS::fsync (ACE_HANDLE handle) +{ + ACE_OS_TRACE ("ACE_OS::fsync"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_fsync (handle), int, -1); +# elif defined (ACE_LACKS_FSYNC) + ACE_UNUSED_ARG (handle); + ACE_NOTSUP_RETURN (-1); +# else + ACE_OSCALL_RETURN (::fsync (handle), int, -1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::getopt (int argc, char *const *argv, const char *optstring) +{ + ACE_OS_TRACE ("ACE_OS::getopt"); +#if defined (VXWORKS) || defined (ACE_PSOS) + ACE_UNUSED_ARG (argc); + ACE_UNUSED_ARG (argv); + ACE_UNUSED_ARG (optstring); + ACE_NOTSUP_RETURN (-1); +# elif defined (ACE_LACKS_GETOPT_PROTO) + ACE_OSCALL_RETURN (::getopt (argc, (char**) argv, optstring), int, -1); +# elif defined (ACE_LACKS_POSIX_PROTOTYPES) + ACE_OSCALL_RETURN (::getopt (argc, (const char* const *) argv, optstring), int, -1); +# else + ACE_OSCALL_RETURN (::getopt (argc, argv, optstring), int, -1); +# endif /* VXWORKS */ +} + +ACE_INLINE int +ACE_OS::pipe (ACE_HANDLE fds[]) +{ + ACE_OS_TRACE ("ACE_OS::pipe"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_pipe (fds), int, -1); +#elif defined (VXWORKS) || defined (ACE_PSOS) + ACE_UNUSED_ARG (fds); + ACE_NOTSUP_RETURN (-1); +# else + ACE_OSCALL_RETURN (::pipe (fds), int, -1); +# endif /* ACE_HAS_PACE */ +} + +# if defined (DIGITAL_UNIX) +extern "C" { + extern char *_Pctime_r (const time_t *, char *); + extern struct tm *_Plocaltime_r (const time_t *, struct tm *); + extern struct tm *_Pgmtime_r (const time_t *, struct tm *); + extern char *_Pasctime_r (const struct tm *, char *); + extern int _Prand_r (unsigned int *seedptr); + extern int _Pgetpwnam_r (const char *, struct passwd *, + char *, size_t, struct passwd **); +} +# endif /* DIGITAL_UNIX */ + +// VAC++ doesn't correctly grok the ::getpwnam_r - the function is redefined +// in pwd.h, and that redefinition is used here +# if defined (_AIX) && defined (__IBMCPP__) && (__IBMCPP__ >= 400) +extern "C" { + extern int _posix_getpwnam_r(const char *, struct passwd *, char *, + int, struct passwd **); + } +#endif /* AIX and VAC++ 4 */ + +ACE_INLINE int +ACE_OS::rand_r (ACE_RANDR_TYPE &seed) +{ + ACE_OS_TRACE ("ACE_OS::rand_r"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_rand_r (&seed), int, -1); +# elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && \ + !defined (ACE_LACKS_RAND_REENTRANT_FUNCTIONS) +# if defined (DIGITAL_UNIX) + ACE_OSCALL_RETURN (::_Prand_r (&seed), int, -1); +# elif defined (HPUX_10) + // rand() is thread-safe on HP-UX 10. rand_r's signature is not consistent + // with latest POSIX and will change in a future HP-UX release so that it + // is consistent. At that point, this #elif section can be changed or + // removed, and just call rand_r. + ACE_UNUSED_ARG (seed); + ACE_OSCALL_RETURN (::rand(), int, -1); +# elif defined (ACE_HAS_BROKEN_RANDR) + ACE_OSCALL_RETURN (::rand_r (seed), int, -1); +# else + ACE_OSCALL_RETURN (::rand_r (&seed), int, -1); +# endif /* DIGITAL_UNIX */ +# else + ACE_UNUSED_ARG (seed); + ACE_OSCALL_RETURN (::rand (), int, -1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE pid_t +ACE_OS::setsid (void) +{ + ACE_OS_TRACE ("ACE_OS::setsid"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_setsid (), int , -1); +#elif defined (VXWORKS) || defined (CHORUS) || defined (ACE_PSOS) + ACE_NOTSUP_RETURN (-1); +# else + ACE_OSCALL_RETURN (::setsid (), int, -1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE mode_t +ACE_OS::umask (mode_t cmask) +{ + ACE_OS_TRACE ("ACE_OS::umask"); +#if defined (ACE_HAS_PACE) + return ::pace_umask (cmask); +#elif defined (VXWORKS) || defined (ACE_PSOS) + ACE_UNUSED_ARG (cmask); + ACE_NOTSUP_RETURN (-1); +# else + return ::umask (cmask); // This call shouldn't fail... +# endif /* ACE_HAS_PACE */ +} + +#else /* ACE_WIN32 */ + +// Adapt the Win32 System Calls (which return BOOLEAN values of TRUE +// and FALSE) into int values expected by the ACE_OSCALL macros. +# define ACE_ADAPT_RETVAL(OP,RESULT) ((RESULT = (OP)) == FALSE ? -1 : 0) + +// Perform a mapping of Win32 error numbers into POSIX errnos. +# define ACE_FAIL_RETURN(RESULT) do { \ + switch (ACE_OS::set_errno_to_last_error ()) { \ + case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break; \ + case ERROR_FILE_EXISTS: errno = EEXIST; break; \ + case ERROR_SHARING_VIOLATION: errno = EACCES; break; \ + case ERROR_PATH_NOT_FOUND: errno = ENOENT; break; \ + } \ + return RESULT; } while (0) + +ACE_INLINE LPSECURITY_ATTRIBUTES +ACE_OS::default_win32_security_attributes (LPSECURITY_ATTRIBUTES sa) +{ +#if defined (ACE_DEFINES_DEFAULT_WIN32_SECURITY_ATTRIBUTES) + if (sa == 0) + { + // @@ This is a good place to use pthread_once. + static SECURITY_ATTRIBUTES default_sa; + static SECURITY_DESCRIPTOR sd; + InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); + default_sa.nLength = sizeof(SECURITY_ATTRIBUTES); + default_sa.lpSecurityDescriptor = &sd; + default_sa.bInheritHandle = TRUE; + sa = &default_sa; + } + return sa; +#else /* !ACE_DEFINES_DEFAULT_WIN32_SECURITY_ATTRIBUTES */ + return sa; +#endif /* ACE_DEFINES_DEFAULT_WIN32_SECURITY_ATTRIBUTES */ +} + +ACE_INLINE int +ACE_OS::getopt (int argc, char *const *argv, const char *optstring) +{ + ACE_UNUSED_ARG (argc); + ACE_UNUSED_ARG (argv); + ACE_UNUSED_ARG (optstring); + + ACE_OS_TRACE ("ACE_OS::getopt"); + ACE_NOTSUP_RETURN (-1); +} + +ACE_INLINE int +ACE_OS::pipe (ACE_HANDLE fds[]) +{ +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_pipe (fds), int, -1); +# elif !defined (ACE_HAS_WINCE) && !defined (__IBMCPP__) + ACE_OS_TRACE ("ACE_OS::pipe"); + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL + (::CreatePipe (&fds[0], &fds[1], 0, 0), + ace_result_), int, -1); +# else + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::rand_r (ACE_RANDR_TYPE& seed) +{ + ACE_UNUSED_ARG (seed); + + ACE_OS_TRACE ("ACE_OS::rand_r"); + ACE_NOTSUP_RETURN (-1); +} + +ACE_INLINE pid_t +ACE_OS::setsid (void) +{ + ACE_OS_TRACE ("ACE_OS::setsid"); + ACE_NOTSUP_RETURN (-1); +} + +ACE_INLINE mode_t +ACE_OS::umask (mode_t cmask) +{ +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_umask (cmask), mode_t, -1); +# elif !defined (ACE_HAS_WINCE) + ACE_OS_TRACE ("ACE_OS::umask"); + ACE_OSCALL_RETURN (::_umask (cmask), mode_t, -1); +# else + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::fstat (ACE_HANDLE handle, ACE_stat *stp) +{ + ACE_OS_TRACE ("ACE_OS::fstat"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_fstat (handle, stp), int, -1); +# elif 1 + BY_HANDLE_FILE_INFORMATION fdata; + + if (::GetFileInformationByHandle (handle, &fdata) == FALSE) + { + ACE_OS::set_errno_to_last_error (); + return -1; + } + else if (fdata.nFileSizeHigh != 0) + { + errno = EINVAL; + return -1; + } + else + { + stp->st_size = fdata.nFileSizeLow; + stp->st_atime = ACE_Time_Value (fdata.ftLastAccessTime).sec (); + stp->st_mtime = ACE_Time_Value (fdata.ftLastWriteTime).sec (); +#if !defined (ACE_HAS_WINCE) + stp->st_ctime = ACE_Time_Value (fdata.ftCreationTime).sec (); + stp->st_nlink = ACE_static_cast (short, fdata.nNumberOfLinks); + stp->st_dev = stp->st_rdev = 0; // No equivalent conversion. + stp->st_mode = S_IXOTH | S_IROTH | + (fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? 0 : S_IWOTH); +#endif /* !ACE_HAS_WINCE */ + } + return 0; +# else /* 1 */ + // This implementation close the handle. + int retval = -1; + int fd = ::_open_osfhandle ((long) handle, 0); + if (fd != -1) + retval = ::_fstat (fd, stp); + + ::_close (fd); + // Remember to close the file handle. + return retval; +# endif /* ACE_HAS_PACE */ +} + +#endif /* WIN32 */ + +ACE_INLINE int +ACE_OS::clock_gettime (clockid_t clockid, struct timespec *ts) +{ + ACE_OS_TRACE ("ACE_OS::clock_gettime"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_clock_gettime (clockid, ts), int, -1); +#elif defined (ACE_HAS_CLOCK_GETTIME) + ACE_OSCALL_RETURN (::clock_gettime (clockid, ts), int, -1); +# elif defined (ACE_PSOS) && ! defined (ACE_PSOS_DIAB_MIPS) + ACE_UNUSED_ARG (clockid); + ACE_PSOS_Time_t pt; + int result = ACE_PSOS_Time_t::get_system_time (pt); + *ts = ACE_static_cast (struct timespec, pt); + return result; +#else + ACE_UNUSED_ARG (clockid); + ACE_UNUSED_ARG (ts); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE ACE_Time_Value +ACE_OS::gettimeofday (void) +{ + // ACE_OS_TRACE ("ACE_OS::gettimeofday"); + +#if !defined (ACE_HAS_WINCE)&& !defined (ACE_WIN32) + timeval tv; + int result = 0; +#endif // !defined (ACE_HAS_WINCE)&& !defined (ACE_WIN32) + +#if (0) + struct timespec ts; + + ACE_OSCALL (ACE_OS::clock_gettime (CLOCK_REALTIME, &ts), int, -1, result); + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000L; // timespec has nsec, but timeval has usec + +#elif defined (ACE_HAS_WINCE) + SYSTEMTIME tsys; + FILETIME tfile; + ::GetSystemTime (&tsys); + ::SystemTimeToFileTime (&tsys, &tfile); + return ACE_Time_Value (tfile); +#elif defined (ACE_WIN32) + FILETIME tfile; + ::GetSystemTimeAsFileTime (&tfile); + return ACE_Time_Value (tfile); +#if 0 + // From Todd Montgomery... + struct _timeb tb; + ::_ftime (&tb); + tv.tv_sec = tb.time; + tv.tv_usec = 1000 * tb.millitm; +#endif /* 0 */ +#elif defined (ACE_HAS_AIX_HI_RES_TIMER) + timebasestruct_t tb; + + ::read_real_time (&tb, TIMEBASE_SZ); + ::time_base_to_time (&tb, TIMEBASE_SZ); + + tv.tv_sec = tb.tb_high; + tv.tv_usec = tb.tb_low / 1000L; +#else +# if defined (ACE_HAS_TIMEZONE_GETTIMEOFDAY) || \ + (defined (ACE_HAS_SVR4_GETTIMEOFDAY) && !defined (m88k) && !defined (SCO)) + ACE_OSCALL (::gettimeofday (&tv, 0), int, -1, result); +# elif defined (VXWORKS) || defined (CHORUS) || defined (ACE_PSOS) + // Assumes that struct timespec is same size as struct timeval, + // which assumes that time_t is a long: it currently (VxWorks + // 5.2/5.3) is. + struct timespec ts; + + ACE_OSCALL (ACE_OS::clock_gettime (CLOCK_REALTIME, &ts), int, -1, result); + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000L; // timespec has nsec, but timeval has usec +# else + ACE_OSCALL (::gettimeofday (&tv), int, -1, result); +# endif /* ACE_HAS_SVR4_GETTIMEOFDAY */ +#endif /* 0 */ +#if !defined (ACE_HAS_WINCE)&& !defined (ACE_WIN32) + if (result == -1) + return -1; + else + return ACE_Time_Value (tv); +#endif // !defined (ACE_HAS_WINCE)&& !defined (ACE_WIN32) +} + +ACE_INLINE int +ACE_OS::stat (const ACE_TCHAR *file, ACE_stat *stp) +{ + ACE_OS_TRACE ("ACE_OS::stat"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_stat (file, stp), int, -1); +#elif defined (VXWORKS) + ACE_OSCALL_RETURN (::stat ((char *) file, stp), int, -1); +#elif defined (ACE_PSOS_LACKS_PHILE) + ACE_UNUSED_ARG (file); + ACE_UNUSED_ARG (stp); + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_PSOS) + ACE_OSCALL_RETURN (::stat_f ((char *) file, stp), int, -1); +#elif defined (ACE_HAS_WINCE) + ACE_TEXT_WIN32_FIND_DATA fdata; + + HANDLE fhandle; + + fhandle = ::FindFirstFile (file, &fdata); + if (fhandle == INVALID_HANDLE_VALUE) + { + ACE_OS::set_errno_to_last_error (); + return -1; + } + else if (fdata.nFileSizeHigh != 0) + { + errno = EINVAL; + return -1; + } + else + { + stp->st_size = fdata.nFileSizeLow; + stp->st_atime = ACE_Time_Value (fdata.ftLastAccessTime); + stp->st_mtime = ACE_Time_Value (fdata.ftLastWriteTime); + } + return 0; +#elif defined (ACE_HAS_X86_STAT_MACROS) + // Solaris for intel uses an macro for stat(), this macro is a + // wrapper for _xstat(). + ACE_OSCALL_RETURN (::_xstat (_STAT_VER, file, stp), int, -1); +#elif defined (__BORLANDC__) && (__BORLANDC__ <= 0x540) && defined (ACE_USES_WCHAR) + ACE_OSCALL_RETURN (::_wstat (file, stp), int, -1); +#elif defined (ACE_WIN32) +# if defined (ACE_USES_WCHAR) + ACE_OSCALL_RETURN (::_wstat (file, (struct _stat *) stp), int, -1); +# else + ACE_OSCALL_RETURN (::_stat (file, (struct _stat *) stp), int, -1); +# endif /* ACE_USES_WCHAR */ +#else /* VXWORKS */ + ACE_OSCALL_RETURN (::stat (file, stp), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE time_t +ACE_OS::time (time_t *tloc) +{ +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_time (tloc), time_t, (time_t) -1); +#elif !defined (ACE_HAS_WINCE) + ACE_OS_TRACE ("ACE_OS::time"); +# if defined (ACE_PSOS) && ! defined (ACE_PSOS_HAS_TIME) + unsigned long d_date, d_time, d_tick; + tm_get(&d_date, &d_time, &d_tick); // get current time + if (tloc) + *tloc = d_time; // set time as time_t + return d_time; +# else + ACE_OSCALL_RETURN (::time (tloc), time_t, (time_t) -1); +# endif /* ACE_PSOS && ! ACE_PSOS_HAS_TIME */ +#else + time_t retv = ACE_OS::gettimeofday ().sec (); + if (tloc) + *tloc = retv; + return retv; +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE void +ACE_OS::srand (u_int seed) +{ + ACE_OS_TRACE ("ACE_OS::srand"); +#if defined (ACE_HAS_PACE) + ::pace_srand (seed); +#else + ::srand (seed); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::rand (void) +{ + ACE_OS_TRACE ("ACE_OS::rand"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_rand (), int, -1); +#else + ACE_OSCALL_RETURN (::rand (), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::unlink (const ACE_TCHAR *path) +{ + ACE_OS_TRACE ("ACE_OS::unlink"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_unlink (path), int, -1); +# elif defined (VXWORKS) + ACE_OSCALL_RETURN (::unlink (ACE_const_cast (char *, path)), int, -1); +# elif defined (ACE_PSOS) && ! defined (ACE_PSOS_LACKS_PHILE) + ACE_OSCALL_RETURN (::remove_f ((char *) path), int , -1); +# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_C_LIBRARY) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::remove ((char *) path), + ace_result_), + int, -1); +# elif defined (ACE_HAS_WINCE) + // @@ The problem is, DeleteFile is not actually equals to unlink. ;( + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::DeleteFile (path), ace_result_), + int, -1); +# elif defined (ACE_LACKS_UNLINK) + ACE_UNUSED_ARG (path); + ACE_NOTSUP_RETURN (-1); +# elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR) + ACE_OSCALL_RETURN (::_wunlink (path), int, -1); +# else + ACE_OSCALL_RETURN (::unlink (path), int, -1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::rename (const ACE_TCHAR *old_name, + const ACE_TCHAR *new_name, + int flags) +{ +#if defined (ACE_HAS_PACE) + ACE_UNUSED_ARG (flags); + ACE_OSCALL_RETURN (::pace_rename (old_name, new_name), int, -1); +# elif (ACE_LACKS_RENAME) + ACE_UNUSED_ARG (old_name); + ACE_UNUSED_ARG (new_name); + ACE_UNUSED_ARG (flags); + ACE_NOTSUP_RETURN (-1); +# elif defined (ACE_HAS_WINCE) + ACE_UNUSED_ARG (flags); + if (MoveFile (old_name, new_name) != 0) + ACE_FAIL_RETURN (-1); + return 0; +# elif defined (ACE_WIN32) && defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 == 1) + // NT4 (and up) provides a way to rename/move a file with similar semantics + // to what's usually done on UNIX - if there's an existing file with + // it is removed before the file is renamed/moved. The + // MOVEFILE_COPY_ALLOWED is specified to allow such a rename across drives. + if (flags == -1) + flags = MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING; + if (ACE_TEXT_MoveFileEx(old_name, new_name, flags) == 0) + ACE_FAIL_RETURN (-1); + return 0; +# elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR) + ACE_UNUSED_ARG (flags); + ACE_OSCALL_RETURN (::_wrename (old_name, new_name), int, -1); +# else /* ACE_LACKS_RENAME */ + ACE_UNUSED_ARG (flags); + ACE_OSCALL_RETURN (::rename (old_name, new_name), int, -1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE ACE_TCHAR * +ACE_OS::tempnam (const ACE_TCHAR *dir, const ACE_TCHAR *pfx) +{ + ACE_OS_TRACE ("ACE_OS::tempnam"); +#if defined (VXWORKS) || defined (ACE_HAS_WINCE) || defined (ACE_LACKS_TEMPNAM) + ACE_UNUSED_ARG (dir); + ACE_UNUSED_ARG (pfx); + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_PSOS) + // pSOS only considers the directory prefix + ACE_UNUSED_ARG (pfx); + ACE_OSCALL_RETURN (::tmpnam ((char *) dir), char *, 0); +#elif (defined (__BORLANDC__) && !defined(ACE_USES_WCHAR)) || (defined (ACE_WIN32) && defined (__IBMCPP__)) + ACE_OSCALL_RETURN (::_tempnam ((char *) dir, (char *) pfx), char *, 0); +#elif defined (__BORLANDC__) && defined (ACE_USES_WCHAR) + ACE_OSCALL_RETURN (::_wtempnam ((wchar_t*) dir, (wchar_t*) pfx), wchar_t *, 0); +#elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR) + ACE_OSCALL_RETURN (::_wtempnam (dir, pfx), wchar_t *, 0); +#else /* VXWORKS */ + ACE_OSCALL_RETURN (::tempnam (dir, pfx), char *, 0); +#endif /* VXWORKS */ +} + +ACE_INLINE ACE_HANDLE +ACE_OS::shm_open (const ACE_TCHAR *filename, + int mode, + int perms, + LPSECURITY_ATTRIBUTES sa) +{ + ACE_OS_TRACE ("ACE_OS::shm_open"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_UNUSED_ARG (sa); + ACE_OSCALL_RETURN (::pace_shm_open (filename, mode, perms), ACE_HANDLE, -1); +# elif defined (ACE_HAS_SHM_OPEN) + ACE_UNUSED_ARG (sa); + ACE_OSCALL_RETURN (::shm_open (filename, mode, perms), ACE_HANDLE, -1); +# else /* ! ACE_HAS_SHM_OPEN */ + // Just use ::open. + return ACE_OS::open (filename, mode, perms, sa); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::shm_unlink (const ACE_TCHAR *path) +{ + ACE_OS_TRACE ("ACE_OS::shm_unlink"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_shm_unlink (path), int, -1); +# elif defined (ACE_HAS_SHM_OPEN) + ACE_OSCALL_RETURN (::shm_unlink (path), int, -1); +# else /* ! ACE_HAS_SHM_OPEN */ + // Just use ::unlink. + return ACE_OS::unlink (path); +# endif /* ACE_HAS_PACE */ +} + +#if !defined (ACE_LACKS_CUSERID) +ACE_INLINE char * +ACE_OS::cuserid (char *user, size_t maxlen) +{ + ACE_OS_TRACE ("ACE_OS::cuserid"); +#if defined (VXWORKS) + ACE_UNUSED_ARG (maxlen); + if (user == 0) + { + // Require that the user field be non-null, i.e., don't + // allocate or use static storage. + ACE_NOTSUP_RETURN (0); + } + else + { + ::remCurIdGet (user, 0); + return user; + } +#elif defined (CHORUS) || defined (ACE_PSOS) || defined (__QNXNTO__) + ACE_UNUSED_ARG (user); + ACE_UNUSED_ARG (maxlen); + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_WIN32) + BOOL result = GetUserNameA (user, (u_long *) &maxlen); + if (result == FALSE) + ACE_FAIL_RETURN (0); + else + return user; +#elif defined (ACE_HAS_ALT_CUSERID) +# if defined (ACE_LACKS_PWD_FUNCTIONS) +# error Cannot use alternate cuserid() without POSIX password functions! +# endif /* ACE_LACKS_PWD_FUNCTIONS */ + + // POSIX.1 dropped the cuserid() function. + // GNU GLIBC and other platforms correctly deprecate the cuserid() + // function. + + if (maxlen == 0) + { + // It doesn't make sense to have a zero length user ID. + errno = EINVAL; + return 0; + } + + struct passwd *pw = 0; + + // Make sure the file pointer is at the beginning of the password file + ::setpwent (); + // Should use ACE_OS::setpwent() but I didn't want to move this + // method after it. + + // Use the effective user ID to determine the user name. + pw = ::getpwuid (::geteuid ()); + + // Make sure the password file is closed. + ::endpwent (); + + size_t max_length = 0; + char *userid = 0; + + if (user == 0) + { + // Not reentrant/thread-safe, but nothing else can be done if a + // zero pointer was passed in as the destination. + +#if defined (_POSIX_SOURCE) + const size_t ACE_L_cuserid = L_cuserid; +#else + const size_t ACE_L_cuserid = 9; // 8 character user ID + NULL +#endif /* _POSIX_SOURCE */ + + static ACE_TCHAR tmp[ACE_L_cuserid] = { 0 }; + max_length = ACE_L_cuserid - 1; // Do not include NULL in length + + userid = tmp; + } + else + { + max_length = maxlen; + userid = user; + } + + // Extract the user name from the passwd structure. + if (ACE_OS_String::strlen (pw->pw_name) <= max_length) + { + return ACE_OS_String::strcpy (userid, pw->pw_name); + } + else + { + errno = ENOSPC; // Buffer is not large enough. + return 0; + } +#else + // Hackish because of missing buffer size! + ACE_UNUSED_ARG (maxlen); + ACE_OSCALL_RETURN (::ace_cuserid(user), char*, 0); +#endif /* VXWORKS */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE wchar_t * +ACE_OS::cuserid (wchar_t *user, size_t maxlen) +{ +# if defined (ACE_WIN32) + BOOL result = GetUserNameW (user, (u_long *) &maxlen); + if (result == FALSE) + ACE_FAIL_RETURN (0); + else + return user; +# else /* ACE_WIN32 */ + char *char_user; + wchar_t *result = 0; + + ACE_NEW_RETURN (char_user, char[maxlen + 1], 0); + + if (ACE_OS::cuserid (char_user, maxlen)) + { + ACE_OS::strcpy (user, ACE_Ascii_To_Wide (char_user).wchar_rep ()); + result = user; + } + + delete [] char_user; + + return result; +# endif /* ACE_WIN32 */ +} +#endif /* ACE_HAS_WCHAR */ +#endif /* ACE_LACKS_CUSERID */ + +ACE_INLINE int +ACE_OS::atexit (ACE_EXIT_HOOK func) +{ + return ACE_OS_Object_Manager::instance ()->at_exit (func); +} + +// Doesn't need a macro since it *never* returns! + +ACE_INLINE void +ACE_OS::_exit (int status) +{ + ACE_OS_TRACE ("ACE_OS::_exit"); +#if defined (ACE_HAS_PACE) + ::pace_exit (status); +#elif defined (VXWORKS) + ::exit (status); +#elif defined (ACE_PSOSIM) + ::u_exit (status); +#elif defined (ACE_PSOS) +# if defined (ACE_PSOS_LACKS_PREPC) /* pSoS TM does not support exit. */ + ACE_UNUSED_ARG (status); + return; +# else + ::exit (status); +# endif /* defined (ACE_PSOS_LACKS_PREPC) */ +#elif !defined (ACE_HAS_WINCE) + ::_exit (status); +#else + ::TerminateProcess (::GetCurrentProcess (), + status); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE void +ACE_OS::abort (void) +{ +#if defined (ACE_HAS_PACE) + ::pace_abort (); +#elif !defined (ACE_HAS_WINCE) + ::abort (); +#else + // @@ CE doesn't support abort? + exit (1); +#endif /* ACE_HAS_PACE */ +} + +#if !defined (ACE_HAS_WINCE) +ACE_INLINE int +ACE_OS::vsprintf (char *buffer, const char *format, va_list argptr) +{ +# if defined (ACE_HAS_PACE) + return ACE_SPRINTF_ADAPTER (::pace_vsprintf (buffer, format, argptr)); +# else + return ACE_SPRINTF_ADAPTER (::vsprintf (buffer, format, argptr)); +# endif /* ACE_HAS_PACE */ +} +#endif /* ACE_HAS_WINCE */ + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE int +ACE_OS::vsprintf (wchar_t *buffer, const wchar_t *format, va_list argptr) +{ +# if defined (ACE_HAS_VSWPRINTF) + return ::vswprintf (buffer, format, argptr); + +# else + ACE_UNUSED_ARG (buffer); + ACE_UNUSED_ARG (format); + ACE_UNUSED_ARG (argptr); + ACE_NOTSUP_RETURN (-1); + +# endif /* ACE_HAS_VSWPRINTF */ +} +#endif /* ACE_HAS_WCHAR */ + + +ACE_INLINE long +ACE_OS::sysconf (int name) +{ + ACE_OS_TRACE ("ACE_OS::sysconf"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_sysconf (name), long, -1); +#elif defined (ACE_WIN32) || defined (VXWORKS) || defined (ACE_PSOS) + ACE_UNUSED_ARG (name); + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::sysconf (name), long, -1); +#endif /* ACE_HAS_PACE*/ +} + +ACE_INLINE int +ACE_OS::mutex_init (ACE_mutex_t *m, + int type, + const char *name, + ACE_mutexattr_t *attributes, + LPSECURITY_ATTRIBUTES sa) +{ + // ACE_OS_TRACE ("ACE_OS::mutex_init"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + pace_pthread_mutexattr_t l_attributes; + if (attributes == 0) + attributes = &l_attributes; + int result = 0; + + // Only do these initializations if the parameter + // wasn't originally set. + if (attributes == &l_attributes) + { + if (::pace_pthread_mutexattr_init (attributes) == 0) + result = 0; + else + result = -1; // ACE_ADAPT_RETVAL used it for intermediate status + } + + if (result == 0) + { + if ( +# if defined (_POSIX_THREAD_PROCESS_SHARED) + ::pace_pthread_mutexattr_setpshared (attributes, type) == 0 && +# endif /* _POSIX_THREAD_PROCESS_SHARED */ + ::pace_pthread_mutex_init (m, attributes) == 0) + result = 0; + else + result = -1; // ACE_ADAPT_RETVAL used it for intermediate status + + // Only do the deletions if the parameter wasn't + // originally set and we successfully created the attributes. + if (attributes == &l_attributes) + ::pace_pthread_mutexattr_destroy (&l_attributes); + } + + ACE_UNUSED_ARG (sa); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (type); + + return result; + +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (attributes); + ACE_UNUSED_ARG (sa); + + pthread_mutexattr_t l_attributes; + if (attributes == 0) + attributes = &l_attributes; + int result = 0; + int attr_init = 0; // have we initialized the local attributes. + + // Only do these initializations if the parameter + // wasn't originally set. + if (attributes == &l_attributes) + { +# if defined (ACE_HAS_PTHREADS_DRAFT4) + if (::pthread_mutexattr_create (attributes) == 0) +# elif defined (ACE_HAS_PTHREADS_DRAFT7) || defined (ACE_HAS_PTHREADS_STD) + if (ACE_ADAPT_RETVAL (::pthread_mutexattr_init (attributes), result) == 0) +# else /* draft 6 */ + if (::pthread_mutexattr_init (attributes) == 0) +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + { + result = 0; + attr_init = 1; // we have initialized these attributes + } + else + result = -1; // ACE_ADAPT_RETVAL used it for intermediate status + } + + if (result == 0) + { +# if defined (ACE_HAS_PTHREADS_DRAFT4) + if ( +# if defined (ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP) + ::pthread_mutexattr_setkind_np (attributes, type) == 0 && +# endif /* ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP */ + ::pthread_mutex_init (m, *attributes) == 0) +# elif defined (ACE_HAS_PTHREADS_DRAFT7) || defined (ACE_HAS_PTHREADS_STD) + if ( +# if defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED) + ACE_ADAPT_RETVAL (::pthread_mutexattr_setpshared (attributes, type), + result) == 0 && +# endif /* _POSIX_THREAD_PROCESS_SHARED && ! ACE_LACKS_MUTEXATTR_PSHARED */ + ACE_ADAPT_RETVAL (::pthread_mutex_init (m, attributes), result) == 0) +# else + if ( +# if !defined (ACE_LACKS_MUTEXATTR_PSHARED) + ::pthread_mutexattr_setpshared (attributes, type) == 0 && +# endif /* ACE_LACKS_MUTEXATTR_PSHARED */ +# if defined (ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP) + ::pthread_mutexattr_setkind_np (attributes, type) == 0 && +# endif /* ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP */ + ::pthread_mutex_init (m, attributes) == 0) +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + result = 0; + else + result = -1; // ACE_ADAPT_RETVAL used it for intermediate status + } + +# if (!defined (ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP) && !defined (_POSIX_THREAD_PROCESS_SHARED) || defined (ACE_LACKS_MUTEXATTR_PSHARED)) \ + || ((defined (ACE_HAS_PTHREADS_DRAFT7) || defined (ACE_HAS_PTHREADS_STD)) && !defined (_POSIX_THREAD_PROCESS_SHARED)) + ACE_UNUSED_ARG (type); +# endif /* ! ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP */ + + // Only do the deletions if the parameter wasn't + // originally set. + if (attributes == &l_attributes && attr_init) +# if defined (ACE_HAS_PTHREADS_DRAFT4) + ::pthread_mutexattr_delete (&l_attributes); +# else + ::pthread_mutexattr_destroy (&l_attributes); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + + return result; +# elif defined (ACE_HAS_STHREADS) + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (sa); + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_init (m, type, attributes), + ace_result_), + int, -1); +# elif defined (ACE_HAS_WTHREADS) + m->type_ = type; + + switch (type) + { + case USYNC_PROCESS: +# if defined (ACE_HAS_WINCE) + // @@todo (brunsch) This idea should be moved into ACE_OS_Win32. + m->proc_mutex_ = ::CreateMutexW (ACE_OS::default_win32_security_attributes (sa), + FALSE, + ACE_Ascii_To_Wide (name).wchar_rep ()); +# else /* ACE_HAS_WINCE */ + m->proc_mutex_ = ::CreateMutexA (ACE_OS::default_win32_security_attributes (sa), + FALSE, + name); +# endif /* ACE_HAS_WINCE */ + if (m->proc_mutex_ == 0) + ACE_FAIL_RETURN (-1); + else + { + // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary. + ACE_OS::set_errno_to_last_error (); + return 0; + } + case USYNC_THREAD: + return ACE_OS::thread_mutex_init (&m->thr_mutex_, + type, + name, + attributes); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ + +# elif defined (ACE_PSOS) + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (attributes); + ACE_UNUSED_ARG (sa); +# if defined (ACE_PSOS_HAS_MUTEX) + + u_long flags = MU_LOCAL; + u_long ceiling = 0; + +# if defined (ACE_HAS_RECURSIVE_MUTEXES) + flags |= MU_RECURSIVE; +# else /* ! ACE_HAS_RECURSIVE_MUTEXES */ + flags |= MU_NONRECURSIVE; +# endif /* ACE_HAS_RECURSIVE_MUTEXES */ + +# if defined (ACE_PSOS_HAS_PRIO_MUTEX) + + flags |= MU_PRIOR; + +# if defined (ACE_PSOS_HAS_PRIO_INHERIT_MUTEX) + flags |= MU_PRIO_INHERIT; +# elif defined (ACE_PSOS_HAS_PRIO_PROTECT_MUTEX) + ceiling = PSOS_TASK_MAX_PRIORITY; + flags |= MU_PRIO_PROTECT; +# else + flags |= MU_PRIO_NONE; +# endif /* ACE_PSOS_HAS_PRIO_INHERIT_MUTEX */ + +# else /* ! ACE_PSOS_HAS_PRIO_MUTEX */ + + flags |= MU_FIFO | MU_PRIO_NONE; + +# endif + + // Fake a pSOS name - it can be any 4-byte value, not necessarily needing + // to be ASCII. So use the mutex pointer passed in. That should identify + // each one uniquely. + union { ACE_mutex_t *p; char n[4]; } m_name; + m_name.p = m; + + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mu_create (m_name.n, + flags, + ceiling, + m), + ace_result_), + int, -1); + +# else /* ! ACE_PSOS_HAS_MUTEX */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sm_create ((char *) name, + 1, + SM_LOCAL | SM_PRIOR, + m), + ace_result_), + int, -1); +# endif /* ACE_PSOS_HAS_MUTEX */ +# elif defined (VXWORKS) + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (attributes); + ACE_UNUSED_ARG (sa); + + return (*m = ::semMCreate (type)) == 0 ? -1 : 0; +# endif /* ACE_HAS_PTHREADS */ +#else + ACE_UNUSED_ARG (m); + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (attributes); + ACE_UNUSED_ARG (sa); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE int +ACE_OS::mutex_init (ACE_mutex_t *m, + int type, + const wchar_t *name, + ACE_mutexattr_t *attributes, + LPSECURITY_ATTRIBUTES sa) +{ +#if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS) + m->type_ = type; + + switch (type) + { + case USYNC_PROCESS: + m->proc_mutex_ = ::CreateMutexW (ACE_OS::default_win32_security_attributes (sa), + FALSE, + name); + if (m->proc_mutex_ == 0) + ACE_FAIL_RETURN (-1); + else + return 0; + case USYNC_THREAD: + return ACE_OS::thread_mutex_init (&m->thr_mutex_, + type, + name, + attributes); + } + + errno = EINVAL; + return -1; +#else /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */ + return ACE_OS::mutex_init (m, + type, ACE_Wide_To_Ascii (name).char_rep (), + attributes, + sa); +#endif /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE int +ACE_OS::mutex_destroy (ACE_mutex_t *m) +{ + ACE_OS_TRACE ("ACE_OS::mutex_destroy"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + int dummy_retval = 0; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_mutex_destroy (m), + dummy_retval), int, -1); +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) +# if (defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)) + ACE_OSCALL_RETURN (::pthread_mutex_destroy (m), int, -1); +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_mutex_destroy (m), + ace_result_), int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6*/ +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_destroy (m), ace_result_), int, -1); +# elif defined (ACE_HAS_WTHREADS) + switch (m->type_) + { + case USYNC_PROCESS: + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (m->proc_mutex_), + ace_result_), + int, -1); + case USYNC_THREAD: + return ACE_OS::thread_mutex_destroy (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ +# elif defined (ACE_PSOS) +# if defined (ACE_PSOS_HAS_MUTEX) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mu_delete (*m), ace_result_), + int, -1); +# else /* ! ACE_PSOS_HAS_MUTEX */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sm_delete (*m), ace_result_), + int, -1); +# endif /* ACE_PSOS_HAS_MUTEX */ +# elif defined (VXWORKS) + return ::semDelete (*m) == OK ? 0 : -1; +# endif /* Threads variety case */ +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::mutex_lock (ACE_mutex_t *m) +{ + // ACE_OS_TRACE ("ACE_OS::mutex_lock"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + int dummy_retval = 0; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_mutex_lock (m), + dummy_retval), int, -1); +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) + // Note, don't use "::" here since the following call is often a macro. +# if (defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)) + ACE_OSCALL_RETURN (pthread_mutex_lock (m), int, -1); +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_lock (m), ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6 */ +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_lock (m), ace_result_), int, -1); +# elif defined (ACE_HAS_WTHREADS) + switch (m->type_) + { + case USYNC_PROCESS: + switch (::WaitForSingleObject (m->proc_mutex_, INFINITE)) + { + // + // Timeout can't occur, so don't bother checking... + // + case WAIT_OBJECT_0: + case WAIT_ABANDONED: + // We will ignore abandonments in this method + // Note that we still hold the lock + return 0; + default: + // This is a hack, we need to find an appropriate mapping... + ACE_OS::set_errno_to_last_error (); + return -1; + } + case USYNC_THREAD: + return ACE_OS::thread_mutex_lock (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ +# elif defined (ACE_PSOS) +# if defined (ACE_PSOS_HAS_MUTEX) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mu_lock (*m, MU_WAIT, 0), + ace_result_), + int, -1); +# else /* ACE_PSOS_HAS_MUTEX */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sm_p (*m, SM_WAIT, 0), + ace_result_), + int, -1); +# endif /* ACE_PSOS_HAS_MUTEX */ +# elif defined (VXWORKS) + return ::semTake (*m, WAIT_FOREVER) == OK ? 0 : -1; +# endif /* Threads variety case */ +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::mutex_lock (ACE_mutex_t *m, + int &abandoned) +{ + ACE_OS_TRACE ("ACE_OS::mutex_lock"); +#if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS) + abandoned = 0; + switch (m->type_) + { + case USYNC_PROCESS: + switch (::WaitForSingleObject (m->proc_mutex_, INFINITE)) + { + // + // Timeout can't occur, so don't bother checking... + // + case WAIT_OBJECT_0: + return 0; + case WAIT_ABANDONED: + abandoned = 1; + return 0; // something goofed, but we hold the lock ... + default: + // This is a hack, we need to find an appropriate mapping... + ACE_OS::set_errno_to_last_error (); + return -1; + } + case USYNC_THREAD: + return ACE_OS::thread_mutex_lock (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ +#else + ACE_UNUSED_ARG (m); + ACE_UNUSED_ARG (abandoned); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */ +} + +ACE_INLINE int +ACE_OS::mutex_trylock (ACE_mutex_t *m) +{ + ACE_OS_TRACE ("ACE_OS::mutex_trylock"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + int dummy_retval = 0; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_mutex_trylock (m), + dummy_retval), int, -1); +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) + // Note, don't use "::" here since the following call is often a macro. +# if (defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)) + int status = pthread_mutex_trylock (m); + if (status == 1) + status = 0; + else if (status == 0) { + status = -1; + errno = EBUSY; + } + return status; +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_trylock (m), ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6 */ +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_trylock (m), ace_result_), int, -1); +# elif defined (ACE_HAS_WTHREADS) + switch (m->type_) + { + case USYNC_PROCESS: + { + // Try for 0 milliseconds - i.e. nonblocking. + switch (::WaitForSingleObject (m->proc_mutex_, 0)) + { + case WAIT_OBJECT_0: + return 0; + case WAIT_ABANDONED: + // We will ignore abandonments in this method. Note that + // we still hold the lock. + return 0; + case WAIT_TIMEOUT: + errno = EBUSY; + return -1; + default: + ACE_OS::set_errno_to_last_error (); + return -1; + } + } + case USYNC_THREAD: + return ACE_OS::thread_mutex_trylock (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ +# elif defined (ACE_PSOS) +# if defined (ACE_PSOS_HAS_MUTEX) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mu_lock (*m, MU_NOWAIT, 0), + ace_result_), + int, -1); +# else /* ! ACE_PSOS_HAS_MUTEX */ + switch (::sm_p (*m, SM_NOWAIT, 0)) + { + case 0: + return 0; + case ERR_NOSEM: + errno = EBUSY; + // intentional fall through + default: + return -1; + } +# endif /* ACE_PSOS_HAS_MUTEX */ + +# elif defined (VXWORKS) + if (::semTake (*m, NO_WAIT) == ERROR) + if (errno == S_objLib_OBJ_UNAVAILABLE) + { + // couldn't get the semaphore + errno = EBUSY; + return -1; + } + else + // error + return -1; + else + // got the semaphore + return 0; +# endif /* Threads variety case */ +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::mutex_trylock (ACE_mutex_t *m, int &abandoned) +{ +#if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS) + abandoned = 0; + switch (m->type_) + { + case USYNC_PROCESS: + { + // Try for 0 milliseconds - i.e. nonblocking. + switch (::WaitForSingleObject (m->proc_mutex_, 0)) + { + case WAIT_OBJECT_0: + return 0; + case WAIT_ABANDONED: + abandoned = 1; + return 0; // something goofed, but we hold the lock ... + case WAIT_TIMEOUT: + errno = EBUSY; + return -1; + default: + ACE_OS::set_errno_to_last_error (); + return -1; + } + } + case USYNC_THREAD: + return ACE_OS::thread_mutex_trylock (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ +#else + ACE_UNUSED_ARG (m); + ACE_UNUSED_ARG (abandoned); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */ +} + +ACE_INLINE int +ACE_OS::mutex_lock (ACE_mutex_t *m, + const ACE_Time_Value &timeout) +{ +#if defined (ACE_HAS_THREADS) && defined (ACE_HAS_MUTEX_TIMEOUTS) + +# if defined (ACE_HAS_PTHREADS) + int result; + + // "timeout" should be an absolute time. + + timespec_t ts = timeout; // Calls ACE_Time_Value::operator timespec_t(). + + // Note that the mutex should not be a recursive one, i.e., it + // should only be a standard mutex or an error checking mutex. + + ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_mutex_timedlock (m, &ts), result), int, -1, result); + + // We need to adjust this to make the errno values consistent. + if (result == -1 && errno == ETIMEDOUT) + errno = ETIME; + return result; + +# elif defined (ACE_HAS_WTHREADS) + // Note that we must convert between absolute time (which is passed + // as a parameter) and relative time (which is what the system call + // expects). + ACE_Time_Value relative_time (timeout - ACE_OS::gettimeofday ()); + + switch (m->type_) + { + case USYNC_PROCESS: + switch (::WaitForSingleObject (m->proc_mutex_, + relative_time.msec ())) + { + case WAIT_OBJECT_0: + case WAIT_ABANDONED: + // We will ignore abandonments in this method + // Note that we still hold the lock + return 0; + case WAIT_TIMEOUT: + errno = ETIME; + return -1; + default: + // This is a hack, we need to find an appropriate mapping... + ACE_OS::set_errno_to_last_error (); + return -1; + } + case USYNC_THREAD: + ACE_NOTSUP_RETURN (-1); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ + +# elif defined (ACE_PSOS) + + // Note that we must convert between absolute time (which is + // passed as a parameter) and relative time (which is what + // the system call expects). + ACE_Time_Value relative_time (timeout - ACE_OS::gettimeofday ()); + + u_long ticks = relative_time.sec() * KC_TICKS2SEC + + relative_time.usec () * KC_TICKS2SEC / + ACE_ONE_SECOND_IN_USECS; + if (ticks == 0) + ACE_OSCALL_RETURN (::sm_p (*m, SM_NOWAIT, 0), int, -1); // no timeout + else + ACE_OSCALL_RETURN (::sm_p (*m, SM_WAIT, ticks), int, -1); + +# elif defined (VXWORKS) + + // Note that we must convert between absolute time (which is passed + // as a parameter) and relative time (which is what the system call + // expects). + ACE_Time_Value relative_time (timeout - ACE_OS::gettimeofday ()); + + int ticks_per_sec = ::sysClkRateGet (); + + int ticks = relative_time.sec() * ticks_per_sec + + relative_time.usec () * ticks_per_sec / ACE_ONE_SECOND_IN_USECS; + if (::semTake (*m, ticks) == ERROR) + { + if (errno == S_objLib_OBJ_TIMEOUT) + // Convert the VxWorks errno to one that's common for to ACE + // platforms. + errno = ETIME; + else if (errno == S_objLib_OBJ_UNAVAILABLE) + errno = EBUSY; + return -1; + } + else + return 0; +# endif /* ACE_HAS_PTHREADS */ + +#else + ACE_UNUSED_ARG (m); + ACE_UNUSED_ARG (timeout); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS && ACE_HAS_MUTEX_TIMEOUTS */ +} + +ACE_INLINE int +ACE_OS::mutex_lock (ACE_mutex_t *m, + const ACE_Time_Value *timeout) +{ + return timeout == 0 ? ACE_OS::mutex_lock (m) : ACE_OS::mutex_lock (m, *timeout); +} + +ACE_INLINE int +ACE_OS::mutex_unlock (ACE_mutex_t *m) +{ + ACE_OS_TRACE ("ACE_OS::mutex_unlock"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + int dummy_retval = 0; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_mutex_unlock (m), + dummy_retval), int, -1); +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) + // Note, don't use "::" here since the following call is often a macro. +# if (defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)) + ACE_OSCALL_RETURN (pthread_mutex_unlock (m), int, -1); +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_unlock (m), ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6 */ +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_unlock (m), ace_result_), int, -1); +# elif defined (ACE_HAS_WTHREADS) + switch (m->type_) + { + case USYNC_PROCESS: + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseMutex (m->proc_mutex_), + ace_result_), + int, -1); + case USYNC_THREAD: + return ACE_OS::thread_mutex_unlock (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ +# elif defined (ACE_PSOS) +# if defined (ACE_PSOS_HAS_MUTEX) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mu_unlock (*m), ace_result_), + int, -1); +# else /* ! ACE_PSOS_HAS_MUTEX */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sm_v (*m), ace_result_), + int, -1); +# endif /* ACE_PSOS_HAS_MUTEX */ +# elif defined (VXWORKS) + return ::semGive (*m) == OK ? 0 : -1; +# endif /* Threads variety case */ +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::thread_mutex_init (ACE_thread_mutex_t *m, + int type, + const char *name, + ACE_mutexattr_t *arg) +{ + // ACE_OS_TRACE ("ACE_OS::thread_mutex_init"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_WTHREADS) + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (arg); + ::InitializeCriticalSection (m); + return 0; + +# elif defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS) || defined (ACE_HAS_PACE) + ACE_UNUSED_ARG (type); + // Force the use of USYNC_THREAD! + return ACE_OS::mutex_init (m, USYNC_THREAD, name, arg); + +# elif defined (VXWORKS) || defined (ACE_PSOS) + return mutex_init (m, type, name, arg); + +# endif /* ACE_HAS_STHREADS || ACE_HAS_PTHREADS */ + +#else + ACE_UNUSED_ARG (m); + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (arg); + ACE_NOTSUP_RETURN (-1); + +#endif /* ACE_HAS_THREADS */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE int +ACE_OS::thread_mutex_init (ACE_thread_mutex_t *m, + int type, + const wchar_t *name, + ACE_mutexattr_t *arg) +{ + // ACE_OS_TRACE ("ACE_OS::thread_mutex_init"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_WTHREADS) + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (arg); + ::InitializeCriticalSection (m); + return 0; + +# elif defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS) || defined (ACE_HAS_PACE) + ACE_UNUSED_ARG (type); + // Force the use of USYNC_THREAD! + return ACE_OS::mutex_init (m, USYNC_THREAD, name, arg); + +# elif defined (VXWORKS) || defined (ACE_PSOS) + return mutex_init (m, type, name, arg); + +# endif /* ACE_HAS_STHREADS || ACE_HAS_PTHREADS */ + +#else + ACE_UNUSED_ARG (m); + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (arg); + ACE_NOTSUP_RETURN (-1); + +#endif /* ACE_HAS_THREADS */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE int +ACE_OS::thread_mutex_destroy (ACE_thread_mutex_t *m) +{ + ACE_OS_TRACE ("ACE_OS::thread_mutex_destroy"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_WTHREADS) + ::DeleteCriticalSection (m); + return 0; + +# elif defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS) || defined (ACE_HAS_PACE) + return ACE_OS::mutex_destroy (m); + +# elif defined (VXWORKS) || defined (ACE_PSOS) + return mutex_destroy (m); + +# endif /* ACE_HAS_STHREADS || ACE_HAS_PTHREADS */ + +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); + +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m) +{ + // ACE_OS_TRACE ("ACE_OS::thread_mutex_lock"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_WTHREADS) + ::EnterCriticalSection (m); + return 0; +# elif defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS) || defined (ACE_HAS_PACE) + return ACE_OS::mutex_lock (m); +#elif defined (VXWORKS) || defined (ACE_PSOS) + return mutex_lock (m); +#endif /* ACE_HAS_STHREADS || ACE_HAS_PTHREADS || ACE_HAS_PACE */ +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m, + const ACE_Time_Value &timeout) +{ + // ACE_OS_TRACE ("ACE_OS::thread_mutex_lock"); + + // For all platforms, except MS Windows, this method is equivalent + // to calling ACE_OS::mutex_lock() since ACE_thread_mutex_t and + // ACE_mutex_t are the same type. However, those typedefs evaluate + // to different types on MS Windows. The "thread mutex" + // implementation in ACE for MS Windows cannot readily support + // timeouts due to a lack of timeout features for this type of MS + // Windows synchronization mechanism. + +#if defined (ACE_HAS_THREADS) && !defined (ACE_HAS_WTHREADS) +# if defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS) || defined (ACE_HAS_PACE) + return ACE_OS::mutex_lock (m, timeout); +#elif defined (VXWORKS) || defined (ACE_PSOS) + return mutex_lock (m, timeout); +#endif /* ACE_HAS_STHREADS || ACE_HAS_PTHREADS || ACE_HAS_PACE */ +#else + ACE_UNUSED_ARG (m); + ACE_UNUSED_ARG (timeout); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m, + const ACE_Time_Value *timeout) +{ + return timeout == 0 + ? ACE_OS::thread_mutex_lock (m) + : ACE_OS::thread_mutex_lock (m, *timeout); +} + +ACE_INLINE int +ACE_OS::thread_mutex_trylock (ACE_thread_mutex_t *m) +{ + ACE_OS_TRACE ("ACE_OS::thread_mutex_trylock"); + +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_WTHREADS) +# if defined (ACE_HAS_WIN32_TRYLOCK) + BOOL result = ::TryEnterCriticalSection (m); + if (result == TRUE) + return 0; + else + { + errno = EBUSY; + return -1; + } +# else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_WIN32_TRYLOCK */ +# elif defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS) || defined (ACE_HAS_PACE) + return ACE_OS::mutex_trylock (m); +# elif defined (VXWORKS) || defined (ACE_PSOS) + return ACE_OS::mutex_trylock (m); +#endif /* Threads variety case */ + +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thread_mutex_unlock (ACE_thread_mutex_t *m) +{ + ACE_OS_TRACE ("ACE_OS::thread_mutex_unlock"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_WTHREADS) + ::LeaveCriticalSection (m); + return 0; +# elif defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS) || defined (ACE_HAS_PACE) + return ACE_OS::mutex_unlock (m); +# elif defined (VXWORKS) || defined (ACE_PSOS) + return ACE_OS::mutex_unlock (m); +# endif /* Threads variety case */ +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +// If we're using PACE then we want this method unless we're on Windows. +// Win32 mutexes, semaphores, and condition variables are not yet +// supported in PACE. +#if !defined (ACE_LACKS_COND_T) || (defined (ACE_HAS_PACE) && !defined (ACE_WIN32)) +// NOTE: The ACE_OS::cond_* functions for Unix platforms are defined +// here because the ACE_OS::sema_* functions below need them. +// However, ACE_WIN32 and VXWORKS define the ACE_OS::cond_* functions +// using the ACE_OS::sema_* functions. So, they are defined in OS.cpp. + +ACE_INLINE int +ACE_OS::cond_destroy (ACE_cond_t *cv) +{ + ACE_OS_TRACE ("ACE_OS::cond_destroy"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_cond_destroy (cv), + ace_result_), int, -1); +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) +# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) + ACE_OSCALL_RETURN (::pthread_cond_destroy (cv), int, -1); +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_cond_destroy (cv), ace_result_), int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6 */ +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_destroy (cv), ace_result_), int, -1); +# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_COND_T) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cv_delete (*cv), ace_result_), + int, -1); +# endif /* ACE_HAS_STHREADS */ +# else + ACE_UNUSED_ARG (cv); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::condattr_init (ACE_condattr_t &attributes, + int type) +{ + ACE_UNUSED_ARG (type); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + int result = -1; + + if (::pace_pthread_condattr_init (&attributes) == 0 +# if defined (_POSIX_THREAD_PROCESS_SHARED) + && ::pace_pthread_condattr_setpshared(&attributes, type) == 0 +# endif /* _POSIX_THREAD_PROCESS_SHARED */ + ) + result = 0; + else + result = -1; // ACE_ADAPT_RETVAL used it for intermediate status + + return result; + +# elif defined (ACE_HAS_THREADS) && ! defined (__MACOSX__) +# if defined (ACE_HAS_PTHREADS) + int result = -1; + + if ( +# if defined (ACE_HAS_PTHREADS_DRAFT4) + ::pthread_condattr_create (&attributes) == 0 +# elif defined (ACE_HAS_PTHREADS_STD) || defined (ACE_HAS_PTHREADS_DRAFT7) + ACE_ADAPT_RETVAL(::pthread_condattr_init (&attributes), result) == 0 +# if defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED) + && ACE_ADAPT_RETVAL(::pthread_condattr_setpshared(&attributes, type), + result) == 0 +# endif /* _POSIX_THREAD_PROCESS_SHARED && ! ACE_LACKS_MUTEXATTR_PSHARED */ +# else /* this is draft 6 */ + ::pthread_condattr_init (&attributes) == 0 +# if !defined (ACE_LACKS_CONDATTR_PSHARED) + && ::pthread_condattr_setpshared (&attributes, type) == 0 +# endif /* ACE_LACKS_CONDATTR_PSHARED */ +# if defined (ACE_HAS_PTHREAD_CONDATTR_SETKIND_NP) + && ::pthread_condattr_setkind_np (&attributes, type) == 0 +# endif /* ACE_HAS_PTHREAD_CONDATTR_SETKIND_NP */ +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + ) + result = 0; + else + result = -1; // ACE_ADAPT_RETVAL used it for intermediate status + + return result; +# elif defined (ACE_HAS_STHREADS) + attributes.type = type; + + return 0; + +# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_COND_T) +# if defined (ACE_PSOS_HAS_PRIO_MUTEX) + attributes = CV_LOCAL | CV_PRIOR; +# else /* ACE_PSOS_HAS_PRIO_MUTEX */ + attributes = CV_LOCAL | CV_FIFO; +# endif /* ACE_PSOS_HAS_PRIO_MUTEX */ + return 0; + +# else + ACE_UNUSED_ARG (attributes); + ACE_UNUSED_ARG (type); + ACE_NOTSUP_RETURN (-1); + +# endif /* ACE_HAS_PTHREADS vs. ACE_HAS_STHREADS vs. pSOS */ + +# elif defined (__MACOSX__) + ACE_UNUSED_ARG (attributes); + ACE_UNUSED_ARG (type); + return 0; + +#else + ACE_UNUSED_ARG (attributes); + ACE_UNUSED_ARG (type); + ACE_NOTSUP_RETURN (-1); +# endif /* */ +} + +ACE_INLINE int +ACE_OS::condattr_destroy (ACE_condattr_t &attributes) +{ +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + return ::pace_pthread_condattr_destroy (&attributes); +# elif defined (ACE_HAS_THREADS) && ! defined (__MACOSX__) +# if defined (ACE_HAS_PTHREADS) + +# if defined (ACE_HAS_PTHREADS_DRAFT4) + ::pthread_condattr_delete (&attributes); +# else + ::pthread_condattr_destroy (&attributes); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + +# elif defined (ACE_HAS_STHREADS) + attributes.type = 0; + +# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_COND_T) + attributes = 0; + +# endif /* ACE_HAS_PTHREADS vs. ACE_HAS_STHREADS vs. ACE_PSOS */ + return 0; +# else + ACE_UNUSED_ARG (attributes); + return 0; +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::cond_init (ACE_cond_t *cv, + ACE_condattr_t &attributes, + const char *name, + void *arg) +{ + // ACE_OS_TRACE ("ACE_OS::cond_init"); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (arg); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_cond_init (cv, &attributes), + ace_result_), int, -1); +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) + int result = -1; + + if ( +# if defined (ACE_HAS_PTHREADS_DRAFT4) + ::pthread_cond_init (cv, attributes) == 0 +# elif defined (ACE_HAS_PTHREADS_STD) || defined (ACE_HAS_PTHREADS_DRAFT7) + ACE_ADAPT_RETVAL(::pthread_cond_init (cv, &attributes), result) == 0 +# else /* this is draft 6 */ + ::pthread_cond_init (cv, &attributes) == 0 +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + ) + result = 0; + else + result = -1; // ACE_ADAPT_RETVAL used it for intermediate status + + return result; +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_init (cv, + attributes.type, + arg), + ace_result_), + int, -1); +# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_COND_T) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cv_create (ACE_const_cast (char *, name), + attributes, + cv), + ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS vs. ACE_HAS_STHREADS vs. ACE_PSOS */ +# else + ACE_UNUSED_ARG (cv); + ACE_UNUSED_ARG (attributes); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (arg); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE int +ACE_OS::cond_init (ACE_cond_t *cv, + ACE_condattr_t &attributes, + const wchar_t *name, + void *arg) +{ + return ACE_OS::cond_init (cv, attributes, ACE_Wide_To_Ascii (name).char_rep (), arg); +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE int +ACE_OS::cond_init (ACE_cond_t *cv, short type, const char *name, void *arg) +{ + ACE_condattr_t attributes; + if (ACE_OS::condattr_init (attributes, type) == 0 + && ACE_OS::cond_init (cv, attributes, name, arg) == 0) + { + (void) ACE_OS::condattr_destroy (attributes); + return 0; + } + return -1; +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE int +ACE_OS::cond_init (ACE_cond_t *cv, short type, const wchar_t *name, void *arg) +{ + return ACE_OS::cond_init (cv, type, ACE_Wide_To_Ascii (name).char_rep (), arg); +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE int +ACE_OS::cond_signal (ACE_cond_t *cv) +{ + ACE_OS_TRACE ("ACE_OS::cond_signal"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_pthread_cond_signal (cv), int, -1); +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) +# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) + ACE_OSCALL_RETURN (::pthread_cond_signal (cv), int, -1); +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_cond_signal (cv),ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6 */ +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_signal (cv), ace_result_), int, -1); +# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_COND_T) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cv_signal (*cv), ace_result_), + int, -1); +# endif /* ACE_HAS_STHREADS */ +# else + ACE_UNUSED_ARG (cv); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::cond_broadcast (ACE_cond_t *cv) +{ + ACE_OS_TRACE ("ACE_OS::cond_broadcast"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_pthread_cond_broadcast (cv), int, -1); +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) +# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) + ACE_OSCALL_RETURN (::pthread_cond_broadcast (cv), int, -1); +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_cond_broadcast (cv), + ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6 */ +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_broadcast (cv), + ace_result_), + int, -1); +# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_COND_T) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cv_broadcast (*cv), ace_result_), + int, -1); +# endif /* ACE_HAS_STHREADS */ +# else + ACE_UNUSED_ARG (cv); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::cond_wait (ACE_cond_t *cv, + ACE_mutex_t *external_mutex) +{ + ACE_OS_TRACE ("ACE_OS::cond_wait"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_pthread_cond_wait (cv, external_mutex), int, -1); +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) +# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) + ACE_OSCALL_RETURN (::pthread_cond_wait (cv, external_mutex), int, -1); +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_cond_wait (cv, external_mutex), ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6 */ +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_wait (cv, external_mutex), ace_result_), + int, -1); +# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_COND_T) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cv_wait (*cv, *external_mutex, 0), + ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS */ +# else + ACE_UNUSED_ARG (cv); + ACE_UNUSED_ARG (external_mutex); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::cond_timedwait (ACE_cond_t *cv, + ACE_mutex_t *external_mutex, + ACE_Time_Value *timeout) +{ + ACE_OS_TRACE ("ACE_OS::cond_timedwait"); + //#if defined (ACE_HAS_PACE) +#if 0 + int result; + timespec_t ts; + + if (timeout != 0) + ts = *timeout; // Calls ACE_Time_Value::operator timespec_t(). + ACE_OSCALL (ACE_ADAPT_RETVAL (timeout == 0 + ? (::pace_pthread_cond_wait (cv, external_mutex)) + : (::pace_pthread_cond_timedwait (cv, external_mutex, (ACE_TIMESPEC_PTR) &ts), + int, -1, result))); + + // We need to adjust this to make the POSIX and Solaris return + // values consistent. EAGAIN is from Pthreads DRAFT4 (HP-UX 10.20 and + // down); EINTR is from LynxOS. + if (result == -1 && + (errno == ETIMEDOUT || errno == EAGAIN || errno == EINTR)) + errno = ETIME; + + if (timeout != 0) + timeout->set (ts); // Update the time value before returning. + + return result; + +# elif defined (ACE_HAS_THREADS) + int result; + timespec_t ts; + + if (timeout != 0) + ts = *timeout; // Calls ACE_Time_Value::operator timespec_t(). + +# if defined (ACE_HAS_PTHREADS) + +# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) + if (timeout == 0) + ACE_OSCALL (::pthread_cond_wait (cv, external_mutex), + int, -1, result); + else + { + +# if defined (__Lynx__) + // Note that we must convert between absolute time (which is + // passed as a parameter) and relative time (which is what the + // LynxOS pthread_cond_timedwait expects). This differs from 1003.4a + // draft 4. + + timespec_t relative_time = *timeout - ACE_OS::gettimeofday (); + + ACE_OSCALL (::pthread_cond_timedwait (cv, external_mutex, + &relative_time), + int, -1, result); +# else + ACE_OSCALL (::pthread_cond_timedwait (cv, external_mutex, + (ACE_TIMESPEC_PTR) &ts), + int, -1, result); +# endif /* __Lynx__ */ + } + +# else + ACE_OSCALL (ACE_ADAPT_RETVAL (timeout == 0 + ? ::pthread_cond_wait (cv, external_mutex) + : ::pthread_cond_timedwait (cv, external_mutex, + (ACE_TIMESPEC_PTR) &ts), + result), + int, -1, result); +# endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6*/ + // We need to adjust this to make the POSIX and Solaris return + // values consistent. EAGAIN is from Pthreads DRAFT4 (HP-UX 10.20 and + // down); EINTR is from LynxOS. + if (result == -1 && + (errno == ETIMEDOUT || errno == EAGAIN || errno == EINTR)) + errno = ETIME; + +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL (ACE_ADAPT_RETVAL (timeout == 0 + ? ::cond_wait (cv, external_mutex) + : ::cond_timedwait (cv, + external_mutex, + (timestruc_t*)&ts), + result), + int, -1, result); +# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_COND_T) + // pSOS condition value timeout is expressed in ticks. If the + // cv_wait times out, the mutex is unlocked upon return. + if (timeout == 0) + { + ACE_OSCALL (ACE_ADAPT_RETVAL (::cv_wait (*cv, *external_mutex, 0), + result), + int, -1, result); + } + else + { + // Need to convert the passed absolute time to relative time + // expressed in ticks. + ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ()); + int ticks = (relative_time.sec () * KC_TICKS2SEC) + + (relative_time.usec () * KC_TICKS2SEC / + ACE_ONE_SECOND_IN_USECS); + if (ticks <= 0) + ticks = 1; // Don't wait forever + ACE_OSCALL (ACE_ADAPT_RETVAL (::cv_wait (*cv, *external_mutex, ticks), + result), + int, -1, result); + if (result == -1 && errno == 1) + { + // cv timed out and returned pSOS timeout error 0x01, which + // ACE_ADAPT_RETVAL stored in errno. + ::mu_lock (*external_mutex, MU_WAIT, 0); + errno = ETIME; + } + } + + return result; + +# endif /* ACE_HAS_STHREADS */ + if (timeout != 0) + timeout->set (ts); // Update the time value before returning. + + return result; +# else + ACE_UNUSED_ARG (cv); + ACE_UNUSED_ARG (external_mutex); + ACE_UNUSED_ARG (timeout); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE */ +} +#endif /* !ACE_LACKS_COND_T */ + +ACE_INLINE int +ACE_OS::thr_equal (ACE_thread_t t1, ACE_thread_t t2) +{ +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + return ::pace_pthread_equal (t1, t2); +#elif defined (ACE_HAS_PTHREADS) +# if defined (pthread_equal) + // If it's a macro we can't say "::pthread_equal"... + return pthread_equal (t1, t2); +# else + return ::pthread_equal (t1, t2); +# endif /* pthread_equal */ +#elif defined (VXWORKS) + return ! ACE_OS::strcmp (t1, t2); +#else /* For both STHREADS and WTHREADS... */ + // Hum, Do we need to treat WTHREAD differently? + // levine 13 oct 98 % I don't think so, ACE_thread_t is a DWORD. + return t1 == t2; +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE void +ACE_OS::thr_self (ACE_hthread_t &self) +{ + ACE_OS_TRACE ("ACE_OS::thr_self"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + self = ::pace_pthread_self (); +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) + // Note, don't use "::" here since the following call is often a macro. + self = pthread_self (); +# elif defined (ACE_HAS_THREAD_SELF) + self = ::thread_self (); +# elif defined (ACE_HAS_STHREADS) + self = ::thr_self (); +# elif defined (ACE_HAS_WTHREADS) + self = ::GetCurrentThread (); +# elif defined (ACE_PSOS) + t_ident ((char *) 0, 0, &self); +# elif defined (VXWORKS) + self = ::taskIdSelf (); +# endif /* ACE_HAS_STHREADS */ +#else + self = 1; // Might as well make it the main thread ;-) +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE ACE_thread_t +ACE_OS::thr_self (void) +{ + // ACE_OS_TRACE ("ACE_OS::thr_self"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + return ::pace_pthread_self (); +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) + // Note, don't use "::" here since the following call is often a macro. + ACE_OSCALL_RETURN (pthread_self (), int, -1); +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (::thr_self (), int, -1); +# elif defined (ACE_HAS_WTHREADS) + return ::GetCurrentThreadId (); +# elif defined (ACE_PSOS) + // there does not appear to be a way to get + // a task's name other than at creation + return 0; +# elif defined (VXWORKS) + return ::taskName (::taskIdSelf ()); +# endif /* ACE_HAS_STHREADS */ +#else + return 1; // Might as well make it the first thread ;-) +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::recursive_mutex_init (ACE_recursive_thread_mutex_t *m, + const ACE_TCHAR *name, + ACE_mutexattr_t *arg, + LPSECURITY_ATTRIBUTES sa) +{ + ACE_UNUSED_ARG (sa); +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_RECURSIVE_MUTEXES) + return ACE_OS::thread_mutex_init (m, 0, name, arg); +#else + if (ACE_OS::thread_mutex_init (&m->nesting_mutex_, 0, name, arg) == -1) + return -1; + else if (ACE_OS::cond_init (&m->lock_available_, + (short) USYNC_THREAD, + name, + 0) == -1) + return -1; + else + { + m->nesting_level_ = 0; + m->owner_id_ = ACE_OS::NULL_thread; + return 0; + } +#endif /* ACE_HAS_RECURSIVE_MUTEXES */ +#else + ACE_UNUSED_ARG (m); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (arg); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::recursive_mutex_destroy (ACE_recursive_thread_mutex_t *m) +{ +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_RECURSIVE_MUTEXES) + return ACE_OS::thread_mutex_destroy (m); +#else + if (ACE_OS::thread_mutex_destroy (&m->nesting_mutex_) == -1) + return -1; + else if (ACE_OS::cond_destroy (&m->lock_available_) == -1) + return -1; + else + return 0; +#endif /* ACE_HAS_RECURSIVE_MUTEXES */ +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::recursive_mutex_lock (ACE_recursive_thread_mutex_t *m) +{ +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_RECURSIVE_MUTEXES) + return ACE_OS::thread_mutex_lock (m); +#else + ACE_thread_t t_id = ACE_OS::thr_self (); + int result = 0; + + // Acquire the guard. + if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1) + result = -1; + else + { + // If there's no contention, just grab the lock immediately + // (since this is the common case we'll optimize for it). + if (m->nesting_level_ == 0) + m->owner_id_ = t_id; + // If we already own the lock, then increment the nesting level + // and return. + else if (ACE_OS::thr_equal (t_id, m->owner_id_) == 0) + { + // Wait until the nesting level has dropped to zero, at + // which point we can acquire the lock. + while (m->nesting_level_ > 0) + ACE_OS::cond_wait (&m->lock_available_, + &m->nesting_mutex_); + + // At this point the nesting_mutex_ is held... + m->owner_id_ = t_id; + } + + // At this point, we can safely increment the nesting_level_ no + // matter how we got here! + m->nesting_level_++; + } + + { + // Save/restore errno. + ACE_Errno_Guard error (errno); + ACE_OS::thread_mutex_unlock (&m->nesting_mutex_); + } + return result; +#endif /* ACE_HAS_RECURSIVE_MUTEXES */ +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::recursive_mutex_trylock (ACE_recursive_thread_mutex_t *m) +{ +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_RECURSIVE_MUTEXES) + return ACE_OS::thread_mutex_trylock (m); +#else + ACE_thread_t t_id = ACE_OS::thr_self (); + int result = 0; + + // Acquire the guard. + if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1) + result = -1; + else + { + // If there's no contention, just grab the lock immediately. + if (m->nesting_level_ == 0) + { + m->owner_id_ = t_id; + m->nesting_level_ = 1; + } + // If we already own the lock, then increment the nesting level + // and proceed. + else if (ACE_OS::thr_equal (t_id, m->owner_id_)) + m->nesting_level_++; + else + { + errno = EBUSY; + result = -1; + } + } + + { + // Save/restore errno. + ACE_Errno_Guard error (errno); + ACE_OS::thread_mutex_unlock (&m->nesting_mutex_); + } + return result; +#endif /* ACE_HAS_RECURSIVE_MUTEXES */ +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::recursive_mutex_unlock (ACE_recursive_thread_mutex_t *m) +{ +#if defined (ACE_HAS_THREADS) +#if defined (ACE_HAS_RECURSIVE_MUTEXES) + return ACE_OS::thread_mutex_unlock (m); +#else + ACE_OS_TRACE ("ACE_OS::recursive_mutex_unlock"); +#if !defined (ACE_NDEBUG) + ACE_thread_t t_id = ACE_OS::thr_self (); +#endif /* ACE_NDEBUG */ + int result = 0; + + if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1) + result = -1; + else + { +#if !defined (ACE_NDEBUG) + if (m->nesting_level_ == 0 + || ACE_OS::thr_equal (t_id, m->owner_id_) == 0) + { + errno = EINVAL; + result = -1; + } + else +#endif /* ACE_NDEBUG */ + { + m->nesting_level_--; + if (m->nesting_level_ == 0) + { + // This may not be strictly necessary, but it does put + // the mutex into a known state... + m->owner_id_ = ACE_OS::NULL_thread; + + // Inform a waiter that the lock is free. + if (ACE_OS::cond_signal (&m->lock_available_) == -1) + result = -1; + } + } + } + + { + // Save/restore errno. + ACE_Errno_Guard error (errno); + ACE_OS::thread_mutex_unlock (&m->nesting_mutex_); + } + return result; +#endif /* ACE_HAS_RECURSIVE_MUTEXES */ +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::sema_destroy (ACE_sema_t *s) +{ + ACE_OS_TRACE ("ACE_OS::sema_destroy"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + int result; + if (s->name_) + { + result = ::pace_sem_unlink (s->name_); + pace_free ((void *) s->name_); + return pace_sem_close (s->sema_); + } + else + { + result = ::pace_sem_destroy (s->sema_); + delete s->sema_; + s->sema_ = 0; + return result; + } +# elif defined (ACE_HAS_POSIX_SEM) + int result; +# if defined (ACE_LACKS_NAMED_POSIX_SEM) + if (s->name_) + { + // Only destroy the semaphore if we're the ones who + // initialized it. + ACE_OSCALL (::sem_destroy (s->sema_),int, -1, result); + ACE_OS::shm_unlink (s->name_); + delete s->name_; + return result; + } +# else + if (s->name_) + { + ACE_OSCALL (::sem_unlink (s->name_), int, -1, result); + ACE_OS::free ((void *) s->name_); + ACE_OSCALL_RETURN (::sem_close (s->sema_), int, -1); + } +# endif /* ACE_LACKS_NAMED_POSIX_SEM */ + else + { + ACE_OSCALL (::sem_destroy (s->sema_), int, -1, result); +# if defined (ACE_LACKS_NAMED_POSIX_SEM) + if (s->new_sema_ != 0) +# endif /* ACE_LACKS_NAMED_POSIX_SEM */ + delete s->sema_; + s->sema_ = 0; + return result; + } +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_destroy (s), ace_result_), int, -1); +# elif defined (ACE_HAS_PTHREADS) + int r1 = ACE_OS::mutex_destroy (&s->lock_); + int r2 = ACE_OS::cond_destroy (&s->count_nonzero_); + return r1 != 0 || r2 != 0 ? -1 : 0; +# elif defined (ACE_HAS_WTHREADS) +# if !defined (ACE_USES_WINCE_SEMA_SIMULATION) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*s), ace_result_), int, -1); +# else /* ACE_USES_WINCE_SEMA_SIMULATION */ + // Free up underlying objects of the simulated semaphore. + int r1 = ACE_OS::thread_mutex_destroy (&s->lock_); + int r2 = ACE_OS::event_destroy (&s->count_nonzero_); + return r1 != 0 || r2 != 0 ? -1 : 0; +# endif /* ACE_USES_WINCE_SEMA_SIMULATION */ +# elif defined (ACE_PSOS) + int result; + ACE_OSCALL (ACE_ADAPT_RETVAL (::sm_delete (s->sema_), result), int, -1, result); + s->sema_ = 0; + return result; +# elif defined (VXWORKS) + int result; + ACE_OSCALL (::semDelete (s->sema_), int, -1, result); + s->sema_ = 0; + return result; +# endif /* ACE_HAS_STHREADS */ +# else + ACE_UNUSED_ARG (s); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE */ +} + +// NOTE: The following four function definitions must appear before +// ACE_OS::sema_init (). + +ACE_INLINE int +ACE_OS::close (ACE_HANDLE handle) +{ + ACE_OS_TRACE ("ACE_OS::close"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_close (handle), int, -1); +#elif defined (ACE_WIN32) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (handle), ace_result_), int, -1); +#elif defined (ACE_PSOS) && ! defined (ACE_PSOS_LACKS_PHILE) + u_long result = ::close_f (handle); + if (result != 0) + { + errno = result; + return ACE_static_cast (int, -1); + } + return ACE_static_cast (int, 0); +#else + ACE_OSCALL_RETURN (::close (handle), int, -1); +#endif /* ACE_HAS_PACE */ +} + +// This function returns the number of bytes in the file referenced by +// FD. + +ACE_INLINE long +ACE_OS::filesize (ACE_HANDLE handle) +{ + ACE_OS_TRACE ("ACE_OS::filesize"); +#if defined (ACE_WIN32) + ACE_WIN32CALL_RETURN (::GetFileSize (handle, NULL), long, -1); +#else /* !ACE_WIN32 */ + struct stat sb; + return ACE_OS::fstat (handle, &sb) == -1 ? -1 : (long) sb.st_size; +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::ftruncate (ACE_HANDLE handle, off_t offset) +{ + ACE_OS_TRACE ("ACE_OS::ftruncate"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_ftruncate (handle, offset), int, -1); +#elif defined (ACE_WIN32) + if (::SetFilePointer (handle, offset, NULL, FILE_BEGIN) != (unsigned) -1) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetEndOfFile (handle), ace_result_), int, -1); + else + ACE_FAIL_RETURN (-1); + /* NOTREACHED */ +#elif defined (ACE_PSOS_LACKS_PHILE) + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (offset); + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_PSOS) + ACE_OSCALL_RETURN (::ftruncate_f (handle, offset), int, -1); +#else + ACE_OSCALL_RETURN (::ftruncate (handle, offset), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE void * +ACE_OS::mmap (void *addr, + size_t len, + int prot, + int flags, + ACE_HANDLE file_handle, + off_t off, + ACE_HANDLE *file_mapping, + LPSECURITY_ATTRIBUTES sa, + const ACE_TCHAR *file_mapping_name) +{ + ACE_OS_TRACE ("ACE_OS::mmap"); +#if !defined (ACE_WIN32) || defined (ACE_HAS_PHARLAP) + ACE_UNUSED_ARG (file_mapping_name); +#endif /* !defined (ACE_WIN32) || defined (ACE_HAS_PHARLAP) */ + +#if defined (ACE_HAS_PACE) && !defined (__Lynx__) && !defined (ACE_WIN32) + ACE_UNUSED_ARG (file_mapping); + ACE_UNUSED_ARG (sa); + ACE_OSCALL_RETURN ((void *) ::pace_mmap (addr, + len, + prot, + flags, + file_handle, + off), + void *, MAP_FAILED); + +#elif defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP) + int nt_flags = 0; + ACE_HANDLE local_handle = ACE_INVALID_HANDLE; + + // Ensure that file_mapping is non-zero. + if (file_mapping == 0) + file_mapping = &local_handle; + + if (ACE_BIT_ENABLED (flags, MAP_PRIVATE)) + { + prot = PAGE_WRITECOPY; + nt_flags = FILE_MAP_COPY; + } + else if (ACE_BIT_ENABLED (flags, MAP_SHARED)) + { + if (ACE_BIT_ENABLED (prot, PAGE_READONLY)) + nt_flags = FILE_MAP_READ; + if (ACE_BIT_ENABLED (prot, PAGE_READWRITE)) + nt_flags = FILE_MAP_WRITE; + } + + // Only create a new handle if we didn't have a valid one passed in. + if (*file_mapping == ACE_INVALID_HANDLE) + { +#if !defined(ACE_HAS_WINCE) && (!defined (ACE_HAS_WINNT4) || (ACE_HAS_WINNT4 == 0)) + int try_create = 1; + if ((file_mapping_name != 0) && (*file_mapping_name != 0)) + { + // On Win9x, we first try to OpenFileMapping to + // file_mapping_name. Only if there is no mapping object + // with that name we try CreateFileMapping. + + *file_mapping = ACE_TEXT_OpenFileMapping (nt_flags, + 0, + file_mapping_name); + if (*file_mapping != 0 + || ::GetLastError () != ERROR_INVALID_NAME) + try_create = 0; + } + + if (try_create) +#endif /* !ACE_HAS_WINCE && (ACE_HAS_WINNT4 || ACE_HAS_WINNT4 == 0) */ + { + const LPSECURITY_ATTRIBUTES attr = + ACE_OS::default_win32_security_attributes (sa); + + *file_mapping = ACE_TEXT_CreateFileMapping (file_handle, + attr, + prot, + 0, + 0, + file_mapping_name); + } + } + + if (*file_mapping == 0) + ACE_FAIL_RETURN (MAP_FAILED); + +# if defined (ACE_OS_EXTRA_MMAP_FLAGS) + nt_flags |= ACE_OS_EXTRA_MMAP_FLAGS; +# endif /* ACE_OS_EXTRA_MMAP_FLAGS */ + +# if !defined (ACE_HAS_WINCE) + void *addr_mapping = ::MapViewOfFileEx (*file_mapping, + nt_flags, + 0, + off, + len, + addr); +# else + ACE_UNUSED_ARG (addr); // WinCE doesn't allow specifying . + void *addr_mapping = ::MapViewOfFile (*file_mapping, + nt_flags, + 0, + off, + len); +# endif /* ! ACE_HAS_WINCE */ + + // Only close this down if we used the temporary. + if (file_mapping == &local_handle) + ::CloseHandle (*file_mapping); + + if (addr_mapping == 0) + ACE_FAIL_RETURN (MAP_FAILED); + + else if (ACE_BIT_ENABLED (flags, MAP_FIXED) + && addr_mapping != addr) + { + errno = EINVAL; + return MAP_FAILED; + } + else + return addr_mapping; +#elif defined (__Lynx__) + // The LynxOS 2.5.0 mmap doesn't allow operations on plain + // file descriptors. So, create a shm object and use that. + ACE_UNUSED_ARG (sa); + + char name [128]; + sprintf (name, "%d", file_handle); + + // Assumes that this was called by ACE_Mem_Map, so &file_mapping != 0. + // Otherwise, we don't support the incomplete LynxOS mmap implementation. + // We do support it by creating a hidden shared memory object, and using + // that for the mapping. + int shm_handle; + if (! file_mapping) + file_mapping = &shm_handle; + if ((*file_mapping = ::shm_open (name, + O_RDWR | O_CREAT | O_TRUNC, + ACE_DEFAULT_FILE_PERMS)) == -1) + return MAP_FAILED; + else + { + // The size of the shared memory object must be explicitly set on LynxOS. + const off_t filesize = ACE_OS::filesize (file_handle); + if (::ftruncate (*file_mapping, filesize) == -1) + return MAP_FAILED; + else + { +# if defined (ACE_OS_EXTRA_MMAP_FLAGS) + flags |= ACE_OS_EXTRA_MMAP_FLAGS; +# endif /* ACE_OS_EXTRA_MMAP_FLAGS */ + char *map = (char *) ::mmap ((ACE_MMAP_TYPE) addr, + len, + prot, + flags, + *file_mapping, + off); + if (map == MAP_FAILED) + return MAP_FAILED; + else + // Finally, copy the file contents to the shared memory object. + return ::read (file_handle, map, (int) filesize) == filesize + ? map + : MAP_FAILED; + } + } +#elif !defined (ACE_LACKS_MMAP) + ACE_UNUSED_ARG (sa); + +# if defined (ACE_OS_EXTRA_MMAP_FLAGS) + flags |= ACE_OS_EXTRA_MMAP_FLAGS; +# endif /* ACE_OS_EXTRA_MMAP_FLAGS */ + ACE_UNUSED_ARG (file_mapping); + ACE_OSCALL_RETURN ((void *) ::mmap ((ACE_MMAP_TYPE) addr, + len, + prot, + flags, + file_handle, + off), + void *, MAP_FAILED); +#else + ACE_UNUSED_ARG (addr); + ACE_UNUSED_ARG (len); + ACE_UNUSED_ARG (prot); + ACE_UNUSED_ARG (flags); + ACE_UNUSED_ARG (file_handle); + ACE_UNUSED_ARG (off); + ACE_UNUSED_ARG (file_mapping); + ACE_UNUSED_ARG (sa); + ACE_NOTSUP_RETURN (MAP_FAILED); +#endif /*ACE_HAS_PACE */ +} + +// NOTE: The previous four function definitions must appear before +// ACE_OS::sema_init (). + +ACE_INLINE int +ACE_OS::sema_init (ACE_sema_t *s, + u_int count, + int type, + const char *name, + void *arg, + int max, + LPSECURITY_ATTRIBUTES sa) +{ + ACE_OS_TRACE ("ACE_OS::sema_init"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_UNUSED_ARG (arg); + ACE_UNUSED_ARG (max); + ACE_UNUSED_ARG (sa); + s->name_ = 0; + if (name) + { + ACE_ALLOCATOR_RETURN (s->name_, + ACE_OS::strdup (name), + -1); + s->sema_ = ::pace_sem_open (s->name_, + O_CREAT, + ACE_DEFAULT_FILE_PERMS, + count); + if (s->sema_ == (pace_sem_t *) SEM_FAILED) + return -1; + else + return 0; + } + else + { + ACE_NEW_RETURN (s->sema_, pace_sem_t, -1); + ACE_OSCALL_RETURN (::pace_sem_init (s->sema_, + type != USYNC_THREAD, + count), int, -1); + } +# elif defined (ACE_HAS_POSIX_SEM) + ACE_UNUSED_ARG (arg); + ACE_UNUSED_ARG (max); + ACE_UNUSED_ARG (sa); + + s->name_ = 0; + +# if defined (ACE_LACKS_NAMED_POSIX_SEM) + s->new_sema_ = 0; + if (type == USYNC_PROCESS) + { + // Let's see if it already exists. + ACE_HANDLE fd = ACE_OS::shm_open (name, + O_RDWR | O_CREAT | O_EXCL, + ACE_DEFAULT_FILE_PERMS); + if (fd == ACE_INVALID_HANDLE) + { + if (errno == EEXIST) + fd = ACE_OS::shm_open (name, + O_RDWR | O_CREAT, + ACE_DEFAULT_FILE_PERMS); + else + return -1; + } + else + { + // We own this shared memory object! Let's set its + // size. + if (ACE_OS::ftruncate (fd, + sizeof (ACE_sema_t)) == -1) + return -1; + s->name_ = ACE_OS::strdup (name); + if (s->name_ == 0) + return -1; + } + if (fd == -1) + return -1; + + s->sema_ = (sem_t *) + ACE_OS::mmap (0, + sizeof (ACE_sema_t), + PROT_RDWR, + MAP_SHARED, + fd, + 0); + ACE_OS::close (fd); + if (s->sema_ == (sem_t *) MAP_FAILED) + return -1; + if (s->name_ + // @@ According UNIX Network Programming V2 by Stevens, + // sem_init() is currently not required to return zero on + // success, but it *does* return -1 upon failure. For + // this reason, check for failure by comparing to -1, + // instead of checking for success by comparing to zero. + // -Ossama + // Only initialize it if we're the one who created it. + && ::sem_init (s->sema_, type == USYNC_PROCESS, count) == -1) + return -1; + return 0; + } +#else + if (name) + { +#if defined (sun) || defined (HPUX) + // Solaris and HP-UX require the name to start with a slash. Solaris + // further requires that there be no other slashes than the first. + const char *last_slash = ACE_OS::strrchr (name, '/'); + char name2[MAXPATHLEN]; + if (0 == last_slash) + { + ACE_OS::strcpy (name2, "/"); + ACE_OS::strcat (name2, name); + name = name2; + } +# if defined (sun) + else + name = last_slash; // Chop off chars preceding last slash +# endif /* sun */ +#endif /* sun || HPUX */ + + ACE_ALLOCATOR_RETURN (s->name_, + ACE_OS::strdup (name), + -1); + s->sema_ = ::sem_open (s->name_, + O_CREAT, + ACE_DEFAULT_FILE_PERMS, + count); + if (s->sema_ == (sem_t *) SEM_FAILED) + return -1; + else + return 0; + } +# endif /* ACE_LACKS_NAMED_POSIX_SEM */ + else + { + ACE_NEW_RETURN (s->sema_, + sem_t, + -1); +# if defined (ACE_LACKS_NAMED_POSIX_SEM) + s->new_sema_ = 1; +# endif /* ACE_LACKS_NAMED_POSIX_SEM */ + ACE_OSCALL_RETURN (::sem_init (s->sema_, + type != USYNC_THREAD, + count), int, -1); + } +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_STHREADS) + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (max); + ACE_UNUSED_ARG (sa); + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_init (s, count, type, arg), ace_result_), + int, -1); +# elif defined (ACE_HAS_PTHREADS) + ACE_UNUSED_ARG (max); + ACE_UNUSED_ARG (sa); + int result = -1; + + if (ACE_OS::mutex_init (&s->lock_, type, name, + (ACE_mutexattr_t *) arg) == 0 + && ACE_OS::cond_init (&s->count_nonzero_, type, name, arg) == 0 + && ACE_OS::mutex_lock (&s->lock_) == 0) + { + s->count_ = count; + s->waiters_ = 0; + + if (ACE_OS::mutex_unlock (&s->lock_) == 0) + result = 0; + } + + if (result == -1) + { + ACE_OS::mutex_destroy (&s->lock_); + ACE_OS::cond_destroy (&s->count_nonzero_); + } + return result; +# elif defined (ACE_HAS_WTHREADS) +# if ! defined (ACE_USES_WINCE_SEMA_SIMULATION) + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (arg); + // Create the semaphore with its value initialized to and + // its maximum value initialized to . + *s = + ::CreateSemaphoreA (ACE_OS::default_win32_security_attributes (sa), + count, + max, + name); + + if (*s == 0) + ACE_FAIL_RETURN (-1); + /* NOTREACHED */ + else + return 0; +# else /* ACE_USES_WINCE_SEMA_SIMULATION */ + int result = -1; + + // Initialize internal object for semaphore simulation. + // Grab the lock as soon as possible when we initializing + // the semaphore count. Notice that we initialize the + // event object as "manually reset" so we can amortize the + // cost for singling/reseting the event. + // @@ I changed the mutex type to thread_mutex. Notice that this + // is basically a CriticalSection object and doesn't not has + // any security attribute whatsoever. However, since this + // semaphore implementation only works within a process, there + // shouldn't any security issue at all. + if (ACE_OS::thread_mutex_init (&s->lock_, type, name, (ACE_mutexattr_t *)arg) == 0 + && ACE_OS::event_init (&s->count_nonzero_, 1, + count > 0, type, name, arg, sa) == 0 + && ACE_OS::thread_mutex_lock (&s->lock_) == 0) + { + s->count_ = count; + + if (ACE_OS::thread_mutex_unlock (&s->lock_) == 0) + result = 0; + } + + // Destroy the internal objects if we didn't initialize + // either of them successfully. Don't bother to check + // for errors. + if (result == -1) + { + ACE_OS::thread_mutex_destroy (&s->lock_); + ACE_OS::event_destroy (&s->count_nonzero_); + } + return result; +# endif /* ACE_USES_WINCE_SEMA_SIMULATION */ +# elif defined (ACE_PSOS) + u_long result; + ACE_OS::memcpy (s->name_, name, sizeof (s->name_)); + // default semaphore creation flags to priority based, global across nodes + u_long flags = 0; + flags |= (type & SM_LOCAL) ? SM_LOCAL : SM_GLOBAL; + flags |= (type & SM_FIFO) ? SM_FIFO : SM_PRIOR; + result = ::sm_create (s->name_, count, flags, &(s->sema_)); + return (result == 0) ? 0 : -1; +# elif defined (VXWORKS) + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (arg); + ACE_UNUSED_ARG (max); + ACE_UNUSED_ARG (sa); + s->name_ = 0; + s->sema_ = ::semCCreate (type, count); + return s->sema_ ? 0 : -1; +# endif /* ACE_HAS_STHREADS */ +# else + ACE_UNUSED_ARG (s); + ACE_UNUSED_ARG (count); + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (arg); + ACE_UNUSED_ARG (max); + ACE_UNUSED_ARG (sa); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE int +ACE_OS::sema_init (ACE_sema_t *s, + u_int count, + int type, + const wchar_t *name, + void *arg, + int max, + LPSECURITY_ATTRIBUTES sa) +{ +# if defined (ACE_HAS_WTHREADS) +# if ! defined (ACE_USES_WINCE_SEMA_SIMULATION) + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (arg); + // Create the semaphore with its value initialized to and + // its maximum value initialized to . + *s = + ::CreateSemaphoreW (ACE_OS::default_win32_security_attributes (sa), + count, + max, + name); + + if (*s == 0) + ACE_FAIL_RETURN (-1); + /* NOTREACHED */ + else + return 0; +# else /* ACE_USES_WINCE_SEMA_SIMULATION */ + int result = -1; + + // Initialize internal object for semaphore simulation. + // Grab the lock as soon as possible when we initializing + // the semaphore count. Notice that we initialize the + // event object as "manually reset" so we can amortize the + // cost for singling/reseting the event. + // @@ I changed the mutex type to thread_mutex. Notice that this + // is basically a CriticalSection object and doesn't not has + // any security attribute whatsoever. However, since this + // semaphore implementation only works within a process, there + // shouldn't any security issue at all. + if (ACE_OS::thread_mutex_init (&s->lock_, type, name, (ACE_mutexattr_t *)arg) == 0 + && ACE_OS::event_init (&s->count_nonzero_, 1, + count > 0, type, name, arg, sa) == 0 + && ACE_OS::thread_mutex_lock (&s->lock_) == 0) + { + s->count_ = count; + + if (ACE_OS::thread_mutex_unlock (&s->lock_) == 0) + result = 0; + } + + // Destroy the internal objects if we didn't initialize + // either of them successfully. Don't bother to check + // for errors. + if (result == -1) + { + ACE_OS::thread_mutex_destroy (&s->lock_); + ACE_OS::event_destroy (&s->count_nonzero_); + } + return result; +# endif /* ACE_USES_WINCE_SEMA_SIMULATION */ +# else /* ACE_HAS_WTHREADS */ + // Just call the normal char version. + return ACE_OS::sema_init (s, count, type, ACE_Wide_To_Ascii (name).char_rep (), arg, max, sa); +# endif /* ACE_HAS_PACE && ACE_HAS_WTHREADS */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE int +ACE_OS::sema_post (ACE_sema_t *s) +{ + ACE_OS_TRACE ("ACE_OS::sema_post"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_sem_post (s->sema_), int, -1); +# elif defined (ACE_HAS_POSIX_SEM) + ACE_OSCALL_RETURN (::sem_post (s->sema_), int, -1); +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_post (s), ace_result_), int, -1); +# elif defined (ACE_HAS_PTHREADS) + int result = -1; + + if (ACE_OS::mutex_lock (&s->lock_) == 0) + { + // Always allow a waiter to continue if there is one. + if (s->waiters_ > 0) + result = ACE_OS::cond_signal (&s->count_nonzero_); + else + result = 0; + + s->count_++; + ACE_OS::mutex_unlock (&s->lock_); + } + return result; +# elif defined (ACE_HAS_WTHREADS) +# if !defined (ACE_USES_WINCE_SEMA_SIMULATION) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseSemaphore (*s, 1, 0), + ace_result_), + int, -1); +# else /* ACE_USES_WINCE_SEMA_SIMULATION */ + int result = -1; + + // Since we are simulating semaphores, we need to update semaphore + // count manually. Grab the lock to prevent race condition first. + if (ACE_OS::thread_mutex_lock (&s->lock_) == 0) + { + // Check the original state of event object. Single the event + // object in transition from semaphore not available to + // semaphore available. + if (s->count_++ <= 0) + result = ACE_OS::event_signal (&s->count_nonzero_); + else + result = 0; + + ACE_OS::thread_mutex_unlock (&s->lock_); + } + return result; +# endif /* ACE_USES_WINCE_SEMA_SIMULATION */ +# elif defined (ACE_PSOS) + int result; + ACE_OSCALL (ACE_ADAPT_RETVAL (::sm_v (s->sema_), result), int, -1, result); + return result; +# elif defined (VXWORKS) + ACE_OSCALL_RETURN (::semGive (s->sema_), int, -1); +# endif /* ACE_HAS_STHREADS */ +# else + ACE_UNUSED_ARG (s); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::sema_post (ACE_sema_t *s, size_t release_count) +{ +#if defined (ACE_WIN32) && !defined (ACE_USES_WINCE_SEMA_SIMULATION) + // Win32 supports this natively. +# if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseSemaphore (*(s->sema_), + release_count, 0), ace_result_), + int, -1); +# else + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseSemaphore (*s, release_count, 0), + ace_result_), int, -1); +# endif /* ACE_HAS_PACE */ +#else + // On POSIX platforms we need to emulate this ourselves. + // @@ We can optimize on this implementation. However, + // the semaphore promitive on Win32 doesn't allow one + // to increase a semaphore to more than the count it was + // first initialized. Posix and solaris don't seem to have + // this restriction. Should we impose the restriction in + // our semaphore simulation? + for (size_t i = 0; i < release_count; i++) + if (ACE_OS::sema_post (s) == -1) + return -1; + + return 0; +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::sema_trywait (ACE_sema_t *s) +{ + ACE_OS_TRACE ("ACE_OS::sema_trywait"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_sem_trywait (s->sema_), int, -1); +# elif defined (ACE_HAS_POSIX_SEM) + // POSIX semaphores set errno to EAGAIN if trywait fails + ACE_OSCALL_RETURN (::sem_trywait (s->sema_), int, -1); +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_STHREADS) + // STHREADS semaphores set errno to EBUSY if trywait fails. + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_trywait (s), + ace_result_), + int, -1); +# elif defined (ACE_HAS_PTHREADS) + + int result = -1; + + if (ACE_OS::mutex_lock (&s->lock_) == 0) + { + if (s->count_ > 0) + { + --s->count_; + result = 0; + } + else + errno = EBUSY; + + ACE_OS::mutex_unlock (&s->lock_); + } + return result; +# elif defined (ACE_HAS_WTHREADS) +# if !defined (ACE_USES_WINCE_SEMA_SIMULATION) + int result = ::WaitForSingleObject (*s, 0); + + if (result == WAIT_OBJECT_0) + return 0; + else + { + if (result == WAIT_TIMEOUT) + errno = EBUSY; + else + ACE_OS::set_errno_to_last_error (); + // This is a hack, we need to find an appropriate mapping... + return -1; + } +# else /* ACE_USES_WINCE_SEMA_SIMULATION */ + // Check the status of semaphore first. Return immediately + // if the semaphore is not available and avoid grabing the + // lock. + int result = ::WaitForSingleObject (s->count_nonzero_, 0); + + if (result == WAIT_OBJECT_0) // Proceed when it is available. + { + ACE_OS::thread_mutex_lock (&s->lock_); + + // Need to double check if the semaphore is still available. + // The double checking scheme will slightly affect the + // efficiency if most of the time semaphores are not blocked. + result = ::WaitForSingleObject (s->count_nonzero_, 0); + if (result == WAIT_OBJECT_0) + { + // Adjust the semaphore count. Only update the event + // object status when the state changed. + s->count_--; + if (s->count_ <= 0) + ACE_OS::event_reset (&s->count_nonzero_); + result = 0; + } + + ACE_OS::thread_mutex_unlock (&s->lock_); + } + + // Translate error message to errno used by ACE. + if (result == WAIT_TIMEOUT) + errno = EBUSY; + else + ACE_OS::set_errno_to_last_error (); + // This is taken from the hack above. ;) + return -1; +# endif /* ACE_USES_WINCE_SEMA_SIMULATION */ +# elif defined (ACE_PSOS) + switch (::sm_p (s->sema_, SM_NOWAIT, 0)) + { + case 0: + return 0; + case ERR_NOSEM: + errno = EBUSY; + // intentional fall through + default: + return -1; + } +# elif defined (VXWORKS) + if (::semTake (s->sema_, NO_WAIT) == ERROR) + if (errno == S_objLib_OBJ_UNAVAILABLE) + { + // couldn't get the semaphore + errno = EBUSY; + return -1; + } + else + // error + return -1; + else + // got the semaphore + return 0; +# endif /* ACE_HAS_STHREADS */ +# else + ACE_UNUSED_ARG (s); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::sema_wait (ACE_sema_t *s) +{ + ACE_OS_TRACE ("ACE_OS::sema_wait"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_sem_wait (s->sema_), int, -1); +# elif defined (ACE_HAS_POSIX_SEM) + ACE_OSCALL_RETURN (::sem_wait (s->sema_), int, -1); +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_wait (s), ace_result_), int, -1); +# elif defined (ACE_HAS_PTHREADS) + int result = 0; + + ACE_PTHREAD_CLEANUP_PUSH (&s->lock_); + + if (ACE_OS::mutex_lock (&s->lock_) != 0) + result = -1; + else + { + // Keep track of the number of waiters so that we can signal + // them properly in . + s->waiters_++; + + // Wait until the semaphore count is > 0. + while (s->count_ == 0) + if (ACE_OS::cond_wait (&s->count_nonzero_, + &s->lock_) == -1) + { + result = -2; // -2 means that we need to release the mutex. + break; + } + + --s->waiters_; + } + + if (result == 0) + --s->count_; + + if (result != -1) + ACE_OS::mutex_unlock (&s->lock_); + ACE_PTHREAD_CLEANUP_POP (0); + return result < 0 ? -1 : result; + +# elif defined (ACE_HAS_WTHREADS) +# if !defined (ACE_USES_WINCE_SEMA_SIMULATION) + switch (::WaitForSingleObject (*s, INFINITE)) + { + case WAIT_OBJECT_0: + return 0; + default: + // This is a hack, we need to find an appropriate mapping... + ACE_OS::set_errno_to_last_error (); + return -1; + } + /* NOTREACHED */ +# else /* ACE_USES_WINCE_SEMA_SIMULATION */ + // Timed wait. + int result = -1; + for (;;) + // Check if the semaphore is avialable or not and wait forever. + // Don't bother to grab the lock if it is not available (to avoid + // deadlock.) + switch (::WaitForSingleObject (s->count_nonzero_, INFINITE)) + { + case WAIT_OBJECT_0: + ACE_OS::thread_mutex_lock (&s->lock_); + + // Need to double check if the semaphore is still available. + // This time, we shouldn't wait at all. + if (::WaitForSingleObject (s->count_nonzero_, 0) == WAIT_OBJECT_0) + { + // Decrease the internal counter. Only update the event + // object's status when the state changed. + s->count_--; + if (s->count_ <= 0) + ACE_OS::event_reset (&s->count_nonzero_); + result = 0; + } + + ACE_OS::thread_mutex_unlock (&s->lock_); + // if we didn't get a hold on the semaphore, the result won't + // be 0 and thus, we'll start from the beginning again. + if (result == 0) + return 0; + break; + + default: + // Since we wait indefinitely, anything other than + // WAIT_OBJECT_O indicates an error. + ACE_OS::set_errno_to_last_error (); + // This is taken from the hack above. ;) + return -1; + } + /* NOTREACHED */ +# endif /* ACE_USES_WINCE_SEMA_SIMULATION */ +# elif defined (ACE_PSOS) + int result; + ACE_OSCALL (ACE_ADAPT_RETVAL (::sm_p (s->sema_, SM_WAIT, 0), result), + int, -1, result); + return result; +# elif defined (VXWORKS) + ACE_OSCALL_RETURN (::semTake (s->sema_, WAIT_FOREVER), int, -1); +# endif /* ACE_HAS_STHREADS */ +# else + ACE_UNUSED_ARG (s); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::sema_wait (ACE_sema_t *s, ACE_Time_Value &tv) +{ + ACE_OS_TRACE ("ACE_OS::sema_wait"); +# if defined (ACE_HAS_POSIX_SEM) + ACE_UNUSED_ARG (s); + ACE_UNUSED_ARG (tv); + ACE_NOTSUP_RETURN (-1); +# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_STHREADS) + ACE_UNUSED_ARG (s); + ACE_UNUSED_ARG (tv); + ACE_NOTSUP_RETURN (-1); +# elif defined (ACE_HAS_PTHREADS) + int result = 0; + ACE_Errno_Guard error (errno); + + ACE_PTHREAD_CLEANUP_PUSH (&s->lock_); + + if (ACE_OS::mutex_lock (&s->lock_) != 0) + result = -1; + else + { + // Keep track of the number of waiters so that we can signal + // them properly in . + s->waiters_++; + + // Wait until the semaphore count is > 0 or until we time out. + while (s->count_ == 0) + if (ACE_OS::cond_timedwait (&s->count_nonzero_, + &s->lock_, + &tv) == -1) + { + error = errno; + result = -2; // -2 means that we need to release the mutex. + break; + } + + --s->waiters_; + } + + if (result == 0) + { +# if defined (ACE_LACKS_COND_TIMEDWAIT_RESET) + tv = ACE_OS::gettimeofday (); +# endif /* ACE_LACKS_COND_TIMEDWAIT_RESET */ + --s->count_; + } + + if (result != -1) + ACE_OS::mutex_unlock (&s->lock_); + ACE_PTHREAD_CLEANUP_POP (0); + return result < 0 ? -1 : result; +# elif defined (ACE_HAS_WTHREADS) +# if !defined (ACE_USES_WINCE_SEMA_SIMULATION) + int msec_timeout; + + if (tv.sec () == 0 && tv.usec () == 0) + msec_timeout = 0; // Do a "poll." + else + { + // Note that we must convert between absolute time (which is + // passed as a parameter) and relative time (which is what + // expects). + ACE_Time_Value relative_time (tv - ACE_OS::gettimeofday ()); + + // Watchout for situations where a context switch has caused the + // current time to be > the timeout. + if (relative_time < ACE_Time_Value::zero) + msec_timeout = 0; + else + msec_timeout = relative_time.msec (); + } + + switch (::WaitForSingleObject (*s, msec_timeout)) + { + case WAIT_OBJECT_0: + tv = ACE_OS::gettimeofday (); // Update time to when acquired + return 0; + case WAIT_TIMEOUT: + errno = ETIME; + return -1; + default: + // This is a hack, we need to find an appropriate mapping... + ACE_OS::set_errno_to_last_error (); + return -1; + } + /* NOTREACHED */ +# else /* ACE_USES_WINCE_SEMA_SIMULATION */ + // Note that in this mode, the acquire is done in two steps, and + // we may get signaled but cannot grab the semaphore before + // timeout. In that case, we'll need to restart the process with + // updated timeout value. + + // is an absolute time + ACE_Time_Value relative_time = tv - ACE_OS::gettimeofday (); + int result = -1; + + // While we are not timeout yet. + while (relative_time > ACE_Time_Value::zero) + { + // Wait for our turn to get the object. + switch (::WaitForSingleObject (s->count_nonzero_, relative_time.msec ())) + { + case WAIT_OBJECT_0: + ACE_OS::thread_mutex_lock (&s->lock_); + + // Need to double check if the semaphore is still available. + // We can only do a "try lock" styled wait here to avoid + // blocking threads that want to signal the semaphore. + if (::WaitForSingleObject (s->count_nonzero_, 0) == WAIT_OBJECT_0) + { + // As before, only reset the object when the semaphore + // is no longer available. + s->count_--; + if (s->count_ <= 0) + ACE_OS::event_reset (&s->count_nonzero_); + result = 0; + } + + ACE_OS::thread_mutex_unlock (&s->lock_); + + // Only return when we successfully get the semaphore. + if (result == 0) + { + tv = ACE_OS::gettimeofday (); // Update to time acquired + return 0; + } + break; + + // We have timed out. + case WAIT_TIMEOUT: + errno = ETIME; + return -1; + + // What? + default: + ACE_OS::set_errno_to_last_error (); + // This is taken from the hack above. ;) + return -1; + }; + + // Haven't been able to get the semaphore yet, update the + // timeout value to reflect the remaining time we want to wait. + relative_time = tv - ACE_OS::gettimeofday (); + } + + // We have timed out. + errno = ETIME; + return -1; +# endif /* ACE_USES_WINCE_SEMA_SIMULATION */ +# elif defined (ACE_PSOS) + // Note that we must convert between absolute time (which is + // passed as a parameter) and relative time (which is what + // the system call expects). + ACE_Time_Value relative_time (tv - ACE_OS::gettimeofday ()); + + u_long ticks = relative_time.sec() * KC_TICKS2SEC + + relative_time.usec () * KC_TICKS2SEC / + ACE_ONE_SECOND_IN_USECS; + if(ticks == 0) + ACE_OSCALL_RETURN (::sm_p (s->sema_, SM_NOWAIT, 0), int, -1); //no timeout + else + ACE_OSCALL_RETURN (::sm_p (s->sema_, SM_WAIT, ticks), int, -1); +# elif defined (VXWORKS) + // Note that we must convert between absolute time (which is + // passed as a parameter) and relative time (which is what + // the system call expects). + ACE_Time_Value relative_time (tv - ACE_OS::gettimeofday ()); + + int ticks_per_sec = ::sysClkRateGet (); + + int ticks = relative_time.sec() * ticks_per_sec + + relative_time.usec () * ticks_per_sec / ACE_ONE_SECOND_IN_USECS; + if (::semTake (s->sema_, ticks) == ERROR) + { + if (errno == S_objLib_OBJ_TIMEOUT) + // Convert the VxWorks errno to one that's common for to ACE + // platforms. + errno = ETIME; + else if (errno == S_objLib_OBJ_UNAVAILABLE) + errno = EBUSY; + return -1; + } + else + { + tv = ACE_OS::gettimeofday (); // Update to time acquired + return 0; + } +# endif /* ACE_HAS_STHREADS */ +# else + ACE_UNUSED_ARG (s); + ACE_UNUSED_ARG (tv); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_POSIX_SEM */ +} + +ACE_INLINE int +ACE_OS::sema_wait (ACE_sema_t *s, ACE_Time_Value *tv) +{ + return tv == 0 ? ACE_OS::sema_wait (s) : ACE_OS::sema_wait (s, *tv); +} + +ACE_INLINE int +ACE_OS::rw_tryrdlock (ACE_rwlock_t *rw) +{ + ACE_OS_TRACE ("ACE_OS::rw_tryrdlock"); +#if defined (ACE_HAS_THREADS) +# if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT) +# if defined (ACE_HAS_PTHREADS_UNIX98_EXT) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_tryrdlock (rw), + ace_result_), + int, -1); +# else /* Solaris */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_tryrdlock (rw), ace_result_), int, -1); +# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */ +# else /* NT, POSIX, and VxWorks don't support this natively. */ + int result = -1; + + if (ACE_OS::mutex_lock (&rw->lock_) != -1) + { + ACE_Errno_Guard error (errno); + + if (rw->ref_count_ == -1 || rw->num_waiting_writers_ > 0) + { + error = EBUSY; + result = -1; + } + else + { + rw->ref_count_++; + result = 0; + } + + ACE_OS::mutex_unlock (&rw->lock_); + } + return result; +# endif /* ! ACE_LACKS_RWLOCK_T */ +#else + ACE_UNUSED_ARG (rw); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::rw_trywrlock (ACE_rwlock_t *rw) +{ + ACE_OS_TRACE ("ACE_OS::rw_trywrlock"); +#if defined (ACE_HAS_THREADS) +# if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT) +# if defined (ACE_HAS_PTHREADS_UNIX98_EXT) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_trywrlock (rw), + ace_result_), + int, -1); +# else /* Solaris */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_trywrlock (rw), ace_result_), int, -1); +# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */ +# else /* NT, POSIX, and VxWorks don't support this natively. */ + int result = -1; + + if (ACE_OS::mutex_lock (&rw->lock_) != -1) + { + ACE_Errno_Guard error (errno); + + if (rw->ref_count_ != 0) + { + error = EBUSY; + result = -1; + } + else + { + rw->ref_count_ = -1; + result = 0; + } + + ACE_OS::mutex_unlock (&rw->lock_); + } + return result; +# endif /* ! ACE_LACKS_RWLOCK_T */ +#else + ACE_UNUSED_ARG (rw); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::rw_rdlock (ACE_rwlock_t *rw) +{ + ACE_OS_TRACE ("ACE_OS::rw_rdlock"); +#if defined (ACE_HAS_THREADS) +# if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT) +# if defined (ACE_HAS_PTHREADS_UNIX98_EXT) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_rdlock (rw), + ace_result_), + int, -1); +# else /* Solaris */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_rdlock (rw), ace_result_), int, -1); +# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */ +# else /* NT, POSIX, and VxWorks don't support this natively. */ +# if defined (ACE_HAS_PTHREADS) + ACE_PTHREAD_CLEANUP_PUSH (&rw->lock_); +# endif /* ACE_HAS_PTHREADS */ + int result = 0; + if (ACE_OS::mutex_lock (&rw->lock_) == -1) + result = -1; // -1 means didn't get the mutex. + else + { + // Give preference to writers who are waiting. + while (rw->ref_count_ < 0 || rw->num_waiting_writers_ > 0) + { + rw->num_waiting_readers_++; + if (ACE_OS::cond_wait (&rw->waiting_readers_, &rw->lock_) == -1) + { + result = -2; // -2 means that we need to release the mutex. + break; + } + rw->num_waiting_readers_--; + } + } + if (result == 0) + rw->ref_count_++; + if (result != -1) + ACE_OS::mutex_unlock (&rw->lock_); +# if defined (ACE_HAS_PTHREADS) + ACE_PTHREAD_CLEANUP_POP (0); +# endif /* defined (ACE_HAS_PTHREADS) */ + return 0; +# endif /* ! ACE_LACKS_RWLOCK_T */ +#else + ACE_UNUSED_ARG (rw); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::rw_wrlock (ACE_rwlock_t *rw) +{ + ACE_OS_TRACE ("ACE_OS::rw_wrlock"); +#if defined (ACE_HAS_THREADS) +# if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT) +# if defined (ACE_HAS_PTHREADS_UNIX98_EXT) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_wrlock (rw), + ace_result_), + int, -1); +# else /* Solaris */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_wrlock (rw), ace_result_), int, -1); +# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */ +# else /* NT, POSIX, and VxWorks don't support this natively. */ +# if defined (ACE_HAS_PTHREADS) + ACE_PTHREAD_CLEANUP_PUSH (&rw->lock_); +# endif /* defined (ACE_HAS_PTHREADS) */ + int result = 0; + + if (ACE_OS::mutex_lock (&rw->lock_) == -1) + result = -1; // -1 means didn't get the mutex. + else + { + while (rw->ref_count_ != 0) + { + rw->num_waiting_writers_++; + + if (ACE_OS::cond_wait (&rw->waiting_writers_, &rw->lock_) == -1) + { + result = -2; // -2 means we need to release the mutex. + break; + } + + rw->num_waiting_writers_--; + } + } + if (result == 0) + rw->ref_count_ = -1; + if (result != -1) + ACE_OS::mutex_unlock (&rw->lock_); +# if defined (ACE_HAS_PTHREADS) + ACE_PTHREAD_CLEANUP_POP (0); +# endif /* defined (ACE_HAS_PTHREADS) */ + return 0; +# endif /* ! ACE_LACKS_RWLOCK_T */ +#else + ACE_UNUSED_ARG (rw); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::rw_unlock (ACE_rwlock_t *rw) +{ + ACE_OS_TRACE ("ACE_OS::rw_unlock"); +#if defined (ACE_HAS_THREADS) +# if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT) +# if defined (ACE_HAS_PTHREADS_UNIX98_EXT) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_unlock (rw), + ace_result_), + int, -1); +# else /* Solaris */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_unlock (rw), ace_result_), int, -1); +# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */ +# else /* NT, POSIX, and VxWorks don't support this natively. */ + if (ACE_OS::mutex_lock (&rw->lock_) == -1) + return -1; + + if (rw->ref_count_ > 0) // Releasing a reader. + rw->ref_count_--; + else if (rw->ref_count_ == -1) // Releasing a writer. + rw->ref_count_ = 0; + else + return -1; // @@ ACE_ASSERT (!"count should not be 0!\n"); + + + int result = 0; + ACE_Errno_Guard error (errno); + + if (rw->important_writer_ && rw->ref_count_ == 1) + // only the reader requesting to upgrade its lock is left over. + { + result = ACE_OS::cond_signal (&rw->waiting_important_writer_); + error = errno; + } + else if (rw->num_waiting_writers_ > 0 && rw->ref_count_ == 0) + // give preference to writers over readers... + { + result = ACE_OS::cond_signal (&rw->waiting_writers_); + error = errno; + } + else if (rw->num_waiting_readers_ > 0 && rw->num_waiting_writers_ == 0) + { + result = ACE_OS::cond_broadcast (&rw->waiting_readers_); + error = errno; + } + + ACE_OS::mutex_unlock (&rw->lock_); + return result; +# endif /* ! ace_lacks_rwlock_t */ +#else + ACE_UNUSED_ARG (rw); + ACE_NOTSUP_RETURN (-1); +#endif /* ace_has_threads */ +} + +// Note that the caller of this method *must* already possess this +// lock as a read lock. +// return {-1 and no errno set means: error, +// -1 and errno==EBUSY set means: could not upgrade, +// 0 means: upgraded successfully} + +ACE_INLINE int +ACE_OS::rw_trywrlock_upgrade (ACE_rwlock_t *rw) +{ + ACE_OS_TRACE ("ACE_OS::rw_trywrlock_upgrade"); +#if defined (ACE_HAS_THREADS) +# if !defined (ACE_LACKS_RWLOCK_T) + // Some native rwlocks, such as those on Solaris and HP-UX 11, don't + // support the upgrade feature . . . + ACE_UNUSED_ARG (rw); + ACE_NOTSUP_RETURN (-1); +# else /* NT, POSIX, and VxWorks don't support this natively. */ + // The ACE rwlock emulation does support upgrade . . . + int result = 0; + +# if defined (ACE_HAS_PTHREADS) + ACE_PTHREAD_CLEANUP_PUSH (&rw->lock_); +# endif /* defined (ACE_HAS_PTHREADS) */ + + if (ACE_OS::mutex_lock (&rw->lock_) == -1) + return -1; + // -1 means didn't get the mutex, error + else if (rw->important_writer_) + // an other reader upgrades already + { + result = -1; + errno = EBUSY; + } + else + { + while (rw->ref_count_ > 1) // wait until only I am left + { + rw->num_waiting_writers_++; // prohibit any more readers + rw->important_writer_ = 1; + + if (ACE_OS::cond_wait (&rw->waiting_important_writer_, &rw->lock_) == -1) + { + result = -1; + // we know that we have the lock again, we have this guarantee, + // but something went wrong + } + rw->important_writer_ = 0; + rw->num_waiting_writers_--; + } + if (result == 0) + { + // nothing bad happend + rw->ref_count_ = -1; + // now I am a writer + // everything is O.K. + } + } + + ACE_OS::mutex_unlock (&rw->lock_); + +# if defined (ACE_HAS_PTHREADS) + ACE_PTHREAD_CLEANUP_POP (0); +# endif /* defined (ACE_HAS_PTHREADS) */ + + return result; + +# endif /* ! ACE_LACKS_RWLOCK_T */ +#else + ACE_UNUSED_ARG (rw); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +#if defined (ACE_HAS_THREADS) && (!defined (ACE_LACKS_RWLOCK_T) || \ + defined (ACE_HAS_PTHREADS_UNIX98_EXT)) +ACE_INLINE int +ACE_OS::rwlock_init (ACE_rwlock_t *rw, + int type, + const ACE_TCHAR *name, + void *arg) +{ + // ACE_OS_TRACE ("ACE_OS::rwlock_init"); +# if defined (ACE_HAS_PTHREADS_UNIX98_EXT) + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (arg); + + int status; + pthread_rwlockattr_t attr; + pthread_rwlockattr_init (&attr); + pthread_rwlockattr_setpshared (&attr, (type == USYNC_THREAD ? + PTHREAD_PROCESS_PRIVATE : + PTHREAD_PROCESS_SHARED)); + status = ACE_ADAPT_RETVAL (pthread_rwlock_init (rw, &attr), status); + pthread_rwlockattr_destroy (&attr); + + return status; + +# else + type = type; + name = name; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rwlock_init (rw, type, arg), ace_result_), int, -1); +# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */ +} +#endif /* ACE_HAS THREADS && !defined (ACE_LACKS_RWLOCK_T) */ + +ACE_INLINE int +ACE_OS::rwlock_destroy (ACE_rwlock_t *rw) +{ + ACE_OS_TRACE ("ACE_OS::rwlock_destroy"); +#if defined (ACE_HAS_THREADS) +# if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT) +# if defined (ACE_HAS_PTHREADS_UNIX98_EXT) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_destroy (rw), + ace_result_), + int, -1); +# else /* Solaris */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rwlock_destroy (rw), ace_result_), int, -1); +# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */ +# else /* NT, POSIX, and VxWorks don't support this natively. */ + ACE_OS::mutex_destroy (&rw->lock_); + ACE_OS::cond_destroy (&rw->waiting_readers_); + ACE_OS::cond_destroy (&rw->waiting_important_writer_); + return ACE_OS::cond_destroy (&rw->waiting_writers_); +# endif /* ACE_HAS_STHREADS && !defined (ACE_LACKS_RWLOCK_T) */ +#else + ACE_UNUSED_ARG (rw); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::event_init (ACE_event_t *event, + int manual_reset, + int initial_state, + int type, + const char *name, + void *arg, + LPSECURITY_ATTRIBUTES sa) +{ +#if defined (ACE_WIN32) + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (arg); +# if defined (ACE_HAS_WINCE) + // @@todo (brunsch) This idea should be moved into ACE_OS_Win32. + *event = ::CreateEventW (ACE_OS::default_win32_security_attributes(sa), + manual_reset, + initial_state, + ACE_Ascii_To_Wide (name).wchar_rep ()); +# else /* ACE_HAS_WINCE */ + *event = ::CreateEventA (ACE_OS::default_win32_security_attributes(sa), + manual_reset, + initial_state, + name); +# endif /* ACE_HAS_WINCE */ + if (*event == NULL) + ACE_FAIL_RETURN (-1); + else + return 0; +#elif defined (ACE_HAS_THREADS) + ACE_UNUSED_ARG (sa); + event->manual_reset_ = manual_reset; + event->is_signaled_ = initial_state; + event->waiting_threads_ = 0; + + int result = ACE_OS::cond_init (&event->condition_, + ACE_static_cast (short, type), + name, + arg); + if (result == 0) + result = ACE_OS::mutex_init (&event->lock_, + type, + name, + (ACE_mutexattr_t *) arg); + return result; +#else + ACE_UNUSED_ARG (event); + ACE_UNUSED_ARG (manual_reset); + ACE_UNUSED_ARG (initial_state); + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (arg); + ACE_UNUSED_ARG (sa); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE int +ACE_OS::event_init (ACE_event_t *event, + int manual_reset, + int initial_state, + int type, + const wchar_t *name, + void *arg, + LPSECURITY_ATTRIBUTES sa) +{ +#if defined (ACE_WIN32) + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (arg); + *event = ::CreateEventW (ACE_OS::default_win32_security_attributes(sa), + manual_reset, + initial_state, + name); + if (*event == NULL) + ACE_FAIL_RETURN (-1); + + return 0; +#else /* ACE_WIN32 */ + return ACE_OS::event_init (event, + manual_reset, + initial_state, + type, + ACE_Wide_To_Ascii (name).char_rep (), + arg, + sa); +#endif /* ACE_WIN32 */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE int +ACE_OS::event_destroy (ACE_event_t *event) +{ +#if defined (ACE_WIN32) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*event), ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) + int r1 = ACE_OS::mutex_destroy (&event->lock_); + int r2 = ACE_OS::cond_destroy (&event->condition_); + return r1 != 0 || r2 != 0 ? -1 : 0; +#else + ACE_UNUSED_ARG (event); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::event_wait (ACE_event_t *event) +{ +#if defined (ACE_WIN32) + switch (::WaitForSingleObject (*event, INFINITE)) + { + case WAIT_OBJECT_0: + return 0; + default: + ACE_OS::set_errno_to_last_error (); + return -1; + } +#elif defined (ACE_HAS_THREADS) + int result = 0; + int error = 0; + + // grab the lock first + if (ACE_OS::mutex_lock (&event->lock_) == 0) + { + if (event->is_signaled_ == 1) + // Event is currently signaled. + { + if (event->manual_reset_ == 0) + // AUTO: reset state + event->is_signaled_ = 0; + } + else + // event is currently not signaled + { + event->waiting_threads_++; + + if (ACE_OS::cond_wait (&event->condition_, + &event->lock_) != 0) + { + result = -1; + error = errno; + // Something went wrong... + } + + event->waiting_threads_--; + } + + // Now we can let go of the lock. + ACE_OS::mutex_unlock (&event->lock_); + + if (result == -1) + // Reset errno in case mutex_unlock() also fails... + errno = error; + } + else + result = -1; + return result; +#else + ACE_UNUSED_ARG (event); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::event_timedwait (ACE_event_t *event, + ACE_Time_Value *timeout, + int use_absolute_time) +{ +#if defined (ACE_WIN32) + DWORD result; + + if (timeout == 0) + // Wait forever + result = ::WaitForSingleObject (*event, INFINITE); + else if (timeout->sec () == 0 && timeout->usec () == 0) + // Do a "poll". + result = ::WaitForSingleObject (*event, 0); + else + { + // Wait for upto number of milliseconds. Note + // that we must convert between absolute time (which is passed + // as a parameter) and relative time (which is what + // WaitForSingleObjects() expects). + // parameter is given in absolute or relative value + // depending on parameter . + int msec_timeout; + if (use_absolute_time) + { + // Time is given in absolute time, we should use + // gettimeofday() to calculate relative time + ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ()); + + // Watchout for situations where a context switch has caused + // the current time to be > the timeout. Thanks to Norbert + // Rapp for pointing this. + if (relative_time < ACE_Time_Value::zero) + msec_timeout = 0; + else + msec_timeout = relative_time.msec (); + } + else + // time is given in relative time, just convert it into + // milliseconds and use it + msec_timeout = timeout->msec (); + result = ::WaitForSingleObject (*event, msec_timeout); + } + + switch (result) + { + case WAIT_OBJECT_0: + return 0; + case WAIT_TIMEOUT: + errno = ETIME; + return -1; + default: + // This is a hack, we need to find an appropriate mapping... + ACE_OS::set_errno_to_last_error (); + return -1; + } +#elif defined (ACE_HAS_THREADS) + int result = 0; + int error = 0; + + // grab the lock first + if (ACE_OS::mutex_lock (&event->lock_) == 0) + { + if (event->is_signaled_ == 1) + // event is currently signaled + { + if (event->manual_reset_ == 0) + // AUTO: reset state + event->is_signaled_ = 0; + } + else + // event is currently not signaled + { + event->waiting_threads_++; + + // cond_timewait() expects absolute time, check + // flag. + if (use_absolute_time == 0 && timeout != 0) + *timeout += ACE_OS::gettimeofday (); + + if (ACE_OS::cond_timedwait (&event->condition_, + &event->lock_, + timeout) != 0) + { + result = -1; + error = errno; + } + + event->waiting_threads_--; + } + + // Now we can let go of the lock. + ACE_OS::mutex_unlock (&event->lock_); + + if (result == -1) + // Reset errno in case mutex_unlock() also fails... + errno = error; + } + else + result = -1; + return result; +#else + ACE_UNUSED_ARG (event); + ACE_UNUSED_ARG (timeout); + ACE_UNUSED_ARG (use_absolute_time); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::event_signal (ACE_event_t *event) +{ +#if defined (ACE_WIN32) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetEvent (*event), ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) + int result = 0; + int error = 0; + + // grab the lock first + if (ACE_OS::mutex_lock (&event->lock_) == 0) + { + // Manual-reset event. + if (event->manual_reset_ == 1) + { + // signal event + event->is_signaled_ = 1; + // wakeup all + if (ACE_OS::cond_broadcast (&event->condition_) != 0) + { + result = -1; + error = errno; + } + } + // Auto-reset event + else + { + if (event->waiting_threads_ == 0) + // No waiters: signal event. + event->is_signaled_ = 1; + + // Waiters: wakeup one waiter. + else if (ACE_OS::cond_signal (&event->condition_) != 0) + { + result = -1; + error = errno; + } + } + + // Now we can let go of the lock. + ACE_OS::mutex_unlock (&event->lock_); + + if (result == -1) + // Reset errno in case mutex_unlock() also fails... + errno = error; + } + else + result = -1; + return result; +#else + ACE_UNUSED_ARG (event); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::event_pulse (ACE_event_t *event) +{ +#if defined (ACE_WIN32) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::PulseEvent (*event), ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) + int result = 0; + int error = 0; + + // grab the lock first + if (ACE_OS::mutex_lock (&event->lock_) == 0) + { + // Manual-reset event. + if (event->manual_reset_ == 1) + { + // Wakeup all waiters. + if (ACE_OS::cond_broadcast (&event->condition_) != 0) + { + result = -1; + error = errno; + } + } + // Auto-reset event: wakeup one waiter. + else if (ACE_OS::cond_signal (&event->condition_) != 0) + { + result = -1; + error = errno; + } + + // Reset event. + event->is_signaled_ = 0; + + // Now we can let go of the lock. + ACE_OS::mutex_unlock (&event->lock_); + + if (result == -1) + // Reset errno in case mutex_unlock() also fails... + errno = error; + } + else + result = -1; + return result; +#else + ACE_UNUSED_ARG (event); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::event_reset (ACE_event_t *event) +{ +#if defined (ACE_WIN32) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ResetEvent (*event), ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) + int result = 0; + + // Grab the lock first. + if (ACE_OS::mutex_lock (&event->lock_) == 0) + { + // Reset event. + event->is_signaled_ = 0; + + // Now we can let go of the lock. + ACE_OS::mutex_unlock (&event->lock_); + } + else + result = -1; + return result; +#else + ACE_UNUSED_ARG (event); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +#if defined (ACE_WIN32) +# define ACE_SOCKCALL_RETURN(OP,TYPE,FAILVALUE) \ + do { TYPE ace_result_ = (TYPE) OP; \ + if (ace_result_ == FAILVALUE) { int ___ = ::WSAGetLastError (); errno = ___; return (TYPE) FAILVALUE; } else return ace_result_; \ + } while (0) +#else +# define ACE_SOCKCALL_RETURN(OP,TYPE,FAILVALUE) ACE_OSCALL_RETURN(OP,TYPE,FAILVALUE) +#endif /* ACE_WIN32 */ + +#if defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) +# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) +# define ACE_NETDBCALL_RETURN(OP,TYPE,FAILVALUE,TARGET,SIZE) \ + do \ + { \ + if (ACE_OS::netdb_acquire ()) \ + return FAILVALUE; \ + else \ + { \ + TYPE ace_result_; \ + ACE_OSCALL (OP, TYPE, FAILVALUE, ace_result_); \ + if (ace_result_ != FAILVALUE) \ + ::memcpy (TARGET, \ + ace_result_, \ + SIZE < sizeof (TYPE) ? SIZE : sizeof (TYPE)); \ + ACE_OS::netdb_release (); \ + return ace_result_; \ + } \ + } while(0) +# else /* ! (ACE_MT_SAFE && ACE_MT_SAFE != 0) */ +# define ACE_NETDBCALL_RETURN(OP,TYPE,FAILVALUE,TARGET,SIZE) \ + do \ + { \ + TYPE ace_result_; \ + ACE_OSCALL(OP,TYPE,FAILVALUE,ace_result_); \ + if (ace_result_ != FAILVALUE) \ + ::memcpy (TARGET, \ + ace_result_, \ + SIZE < sizeof (TYPE) ? SIZE : sizeof (TYPE)); \ + return ace_result_; \ + } while(0) +# endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */ +#endif /* ACE_LACKS_NETDB_REENTRANT_FUNCTIONS */ + +ACE_INLINE ACE_HANDLE +ACE_OS::accept (ACE_HANDLE handle, + struct sockaddr *addr, + int *addrlen) +{ + ACE_OS_TRACE ("ACE_OS::accept"); +#if defined (ACE_PSOS) +# if !defined (ACE_PSOS_DIAB_PPC) + ACE_SOCKCALL_RETURN (::accept ((ACE_SOCKET) handle, + (struct sockaddr_in *) addr, + (ACE_SOCKET_LEN *) addrlen), + ACE_HANDLE, + ACE_INVALID_HANDLE); +# else +ACE_SOCKCALL_RETURN (::accept ((ACE_SOCKET) handle, + (struct sockaddr *) addr, + (ACE_SOCKET_LEN *) addrlen), + ACE_HANDLE, + ACE_INVALID_HANDLE); +# endif /* defined ACE_PSOS_DIAB_PPC */ +#else + // On a non-blocking socket with no connections to accept, this + // system call will return EWOULDBLOCK or EAGAIN, depending on the + // platform. UNIX 98 allows either errno, and they may be the same + // numeric value. So to make life easier for upper ACE layers as + // well as application programmers, always change EAGAIN to + // EWOULDBLOCK. Rather than hack the ACE_OSCALL_RETURN macro, it's + // handled explicitly here. If the ACE_OSCALL macro ever changes, + // this function needs to be reviewed. On Win32, the regular macros + // can be used, as this is not an issue. + +# if defined (ACE_WIN32) + ACE_SOCKCALL_RETURN (::accept ((ACE_SOCKET) handle, + addr, + (ACE_SOCKET_LEN *) addrlen), + ACE_HANDLE, + ACE_INVALID_HANDLE); +# else +# if defined (ACE_HAS_BROKEN_ACCEPT_ADDR) + // Apparently some platforms like VxWorks can't correctly deal with + // a NULL addr. + + sockaddr_in fake_addr; + int fake_addrlen; + + if (addrlen == 0) + addrlen = &fake_addrlen; + + if (addr == 0) + { + addr = (sockaddr *) &fake_addr; + *addrlen = sizeof fake_addr; + } +# endif /* VXWORKS */ + ACE_HANDLE ace_result = ::accept ((ACE_SOCKET) handle, + addr, + (ACE_SOCKET_LEN *) addrlen) ; + if (ace_result == ACE_INVALID_HANDLE && errno == EAGAIN) + errno = EWOULDBLOCK; + return ace_result; + +# endif /* defined (ACE_WIN32) */ +#endif /* defined (ACE_PSOS) */ +} + +ACE_INLINE int +ACE_OS::enum_protocols (int *protocols, + ACE_Protocol_Info *protocol_buffer, + u_long *buffer_length) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + + ACE_SOCKCALL_RETURN (::WSAEnumProtocols (protocols, + protocol_buffer, + buffer_length), + int, + SOCKET_ERROR); + +#else + ACE_UNUSED_ARG (protocols); + ACE_UNUSED_ARG (protocol_buffer); + ACE_UNUSED_ARG (buffer_length); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_WINSOCK2 */ +} + + +ACE_INLINE int +ACE_OS::bind (ACE_HANDLE handle, struct sockaddr *addr, int addrlen) +{ + ACE_OS_TRACE ("ACE_OS::bind"); +#if defined (ACE_PSOS) && !defined (ACE_PSOS_DIAB_PPC) + ACE_SOCKCALL_RETURN (::bind ((ACE_SOCKET) handle, + (struct sockaddr_in *) addr, + (ACE_SOCKET_LEN) addrlen), + int, -1); +#else /* !defined (ACE_PSOS) || defined (ACE_PSOS_DIAB_PPC) */ + ACE_SOCKCALL_RETURN (::bind ((ACE_SOCKET) handle, + addr, + (ACE_SOCKET_LEN) addrlen), int, -1); +#endif /* defined (ACE_PSOS) && !defined (ACE_PSOS_DIAB_PPC) */ +} + +ACE_INLINE int +ACE_OS::connect (ACE_HANDLE handle, + struct sockaddr *addr, + int addrlen) +{ + ACE_OS_TRACE ("ACE_OS::connect"); +#if defined (ACE_PSOS) && !defined (ACE_PSOS_DIAB_PPC) + ACE_SOCKCALL_RETURN (::connect ((ACE_SOCKET) handle, + (struct sockaddr_in *) addr, + (ACE_SOCKET_LEN) addrlen), + int, -1); +#else /* !defined (ACE_PSOS) || defined (ACE_PSOS_DIAB_PPC) */ + ACE_SOCKCALL_RETURN (::connect ((ACE_SOCKET) handle, + addr, + (ACE_SOCKET_LEN) addrlen), int, -1); +#endif /* defined (ACE_PSOS) && !defined (ACE_PSOS_DIAB_PPC) */ +} + +#if !defined (VXWORKS) +ACE_INLINE struct hostent * +ACE_OS::gethostbyname (const char *name) +{ + ACE_OS_TRACE ("ACE_OS::gethostbyname"); +# if defined (ACE_PSOS) + ACE_UNUSED_ARG (name); + ACE_NOTSUP_RETURN (0); +# elif defined (ACE_HAS_NONCONST_GETBY) + ACE_SOCKCALL_RETURN (::gethostbyname (ACE_const_cast (char *, name)), + struct hostent *, + 0); +# else + ACE_SOCKCALL_RETURN (::gethostbyname (name), + struct hostent *, + 0); +# endif /* ACE_HAS_NONCONST_GETBY */ +} + + +ACE_INLINE struct hostent * +ACE_OS::gethostbyaddr (const char *addr, int length, int type) +{ + ACE_OS_TRACE ("ACE_OS::gethostbyaddr"); +# if defined (ACE_PSOS) + ACE_UNUSED_ARG (addr); + ACE_UNUSED_ARG (length); + ACE_UNUSED_ARG (type); + ACE_NOTSUP_RETURN (0); +# elif defined (ACE_HAS_NONCONST_GETBY) + ACE_SOCKCALL_RETURN (::gethostbyaddr (ACE_const_cast (char *, addr), + (ACE_SOCKET_LEN) length, + type), + struct hostent *, + 0); +# else + ACE_SOCKCALL_RETURN (::gethostbyaddr (addr, + (ACE_SOCKET_LEN) length, + type), + struct hostent *, + 0); +# endif /* ACE_HAS_NONCONST_GETBY */ +} + + +ACE_INLINE struct hostent * +ACE_OS::getipnodebyname (const char *name, int family, int flags) +{ + ACE_OS_TRACE ("ACE_OS::getipnodebyname"); +# if defined (ACE_PSOS) + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (family); + ACE_UNUSED_ARG (flags); + ACE_NOTSUP_RETURN (0); +# elif defined (ACE_HAS_IPV6) +# if defined (__GLIBC__) + ACE_UNUSED_ARG (flags); +# if defined (ACE_HAS_NONCONST_GETBY) + ACE_SOCKCALL_RETURN (::gethostbyname2 (ACE_const_cast (char *, name), + family), + struct hostent *, 0); +# else + ACE_SOCKCALL_RETURN (::gethostbyname2 (name, family), + struct hostent *, 0); +# endif /* ACE_HAS_NONCONST_GETBY */ +# else + struct hostent *hptr; + int errnum; + if ((hptr = ::getipnodebyname (name, family, flags, &errnum)) == 0) + { + errno = errnum; + } + return hptr; +# endif /* __GLIBC__ */ +# else + // IPv4-only implementation + ACE_UNUSED_ARG (flags); + if (family == AF_INET) + return ACE_OS::gethostbyname (name); + + ACE_NOTSUP_RETURN (0); +# endif /* ACE_PSOS */ +} + + +ACE_INLINE struct hostent * +ACE_OS::getipnodebyaddr (const void *src, size_t len, int family) +{ +#if defined (ACE_HAS_IPV6) +# if defined (__GLIBC__) + ACE_UNUSED_ARG (src); + ACE_UNUSED_ARG (len); + ACE_UNUSED_ARG (family); + ACE_NOTSUP_RETURN (0); +# else + struct hostent *hptr; + int errnum; + if ((hptr = ::getipnodebyaddr (src, len, family, &errnum)) == 0) + { + errno = errnum; + } + return hptr; +# endif /* whatever_doesnt_have_getipnodebyname */ +#else + // IPv4-only implementation + if (family == AF_INET) + return ACE_OS::gethostbyaddr (ACE_static_cast (const char *, src), + len, + family); + + ACE_NOTSUP_RETURN (0); +# endif /* ACE_PSOS */ +} +#endif /* ! VXWORKS */ + +// It would be really cool to add another version of select that would +// function like the one we're defending against below! +ACE_INLINE int +ACE_OS::select (int width, + fd_set *rfds, fd_set *wfds, fd_set *efds, + const ACE_Time_Value *timeout) +{ + ACE_OS_TRACE ("ACE_OS::select"); +#if defined (ACE_HAS_NONCONST_SELECT_TIMEVAL) + // We must defend against non-conformity! + timeval copy; + timeval *timep; + + if (timeout != 0) + { + copy = *timeout; + timep = © + } + else + timep = 0; +#else + const timeval *timep = (timeout == 0 ? (const timeval *)0 : *timeout); +#endif /* ACE_HAS_NONCONST_SELECT_TIMEVAL */ + ACE_SOCKCALL_RETURN (::select (width, + (ACE_FD_SET_TYPE *) rfds, + (ACE_FD_SET_TYPE *) wfds, + (ACE_FD_SET_TYPE *) efds, + timep), + int, -1); +} + +ACE_INLINE int +ACE_OS::select (int width, + fd_set *rfds, fd_set *wfds, fd_set *efds, + const ACE_Time_Value &timeout) +{ + ACE_OS_TRACE ("ACE_OS::select"); +#if defined (ACE_HAS_NONCONST_SELECT_TIMEVAL) +# define ___ACE_TIMEOUT © + timeval copy = timeout; +#else +# define ___ACE_TIMEOUT timep + const timeval *timep = timeout; +#endif /* ACE_HAS_NONCONST_SELECT_TIMEVAL */ + ACE_SOCKCALL_RETURN (::select (width, + (ACE_FD_SET_TYPE *) rfds, + (ACE_FD_SET_TYPE *) wfds, + (ACE_FD_SET_TYPE *) efds, + ___ACE_TIMEOUT), + int, -1); +#undef ___ACE_TIMEOUT +} + +ACE_INLINE int +ACE_OS::recv (ACE_HANDLE handle, char *buf, int len, int flags) +{ + ACE_OS_TRACE ("ACE_OS::recv"); + + // On UNIX, a non-blocking socket with no data to receive, this + // system call will return EWOULDBLOCK or EAGAIN, depending on the + // platform. UNIX 98 allows either errno, and they may be the same + // numeric value. So to make life easier for upper ACE layers as + // well as application programmers, always change EAGAIN to + // EWOULDBLOCK. Rather than hack the ACE_OSCALL_RETURN macro, it's + // handled explicitly here. If the ACE_OSCALL macro ever changes, + // this function needs to be reviewed. On Win32, the regular macros + // can be used, as this is not an issue. +#if defined (ACE_WIN32) + ACE_SOCKCALL_RETURN (::recv ((ACE_SOCKET) handle, buf, len, flags), int, -1); +#else + int ace_result_; + ace_result_ = ::recv ((ACE_SOCKET) handle, buf, len, flags); + if (ace_result_ == -1 && errno == EAGAIN) + errno = EWOULDBLOCK; + return ace_result_; +#endif /* defined (ACE_WIN32) */ +} + +ACE_INLINE int +ACE_OS::recvfrom (ACE_HANDLE handle, + char *buf, + int len, + int flags, + struct sockaddr *addr, + int *addrlen) +{ + ACE_OS_TRACE ("ACE_OS::recvfrom"); +#if defined (ACE_PSOS) +# if !defined ACE_PSOS_DIAB_PPC + ACE_SOCKCALL_RETURN (::recvfrom ((ACE_SOCKET) handle, buf, (ACE_SOCKET_LEN) len, flags, + (struct sockaddr_in *) addr, (ACE_SOCKET_LEN *) addrlen), + int, -1); +# else + ACE_SOCKCALL_RETURN (::recvfrom ((ACE_SOCKET) handle, buf, (ACE_SOCKET_LEN) len, flags, + (struct sockaddr *) addr, (ACE_SOCKET_LEN *) addrlen), + int, -1); +# endif /* defined ACE_PSOS_DIAB_PPC */ +#elif defined (ACE_WIN32) + int result = ::recvfrom ((ACE_SOCKET) handle, + buf, + (ACE_SOCKET_LEN) len, + flags, + addr, + (ACE_SOCKET_LEN *) addrlen); + if (result == SOCKET_ERROR) + { + ACE_OS::set_errno_to_wsa_last_error (); + if (errno == WSAEMSGSIZE && + ACE_BIT_ENABLED (flags, MSG_PEEK)) + return len; + else + return -1; + } + else + return result; +#else /* non Win32 and non PSOS */ + ACE_SOCKCALL_RETURN (::recvfrom ((ACE_SOCKET) handle, buf, (ACE_SOCKET_LEN) len, flags, + addr, (ACE_SOCKET_LEN *) addrlen), + int, -1); +#endif /* defined (ACE_PSOS) */ +} + +ACE_INLINE int +ACE_OS::send (ACE_HANDLE handle, const char *buf, int len, int flags) +{ + ACE_OS_TRACE ("ACE_OS::send"); + + // On UNIX, a non-blocking socket with no data to receive, this + // system call will return EWOULDBLOCK or EAGAIN, depending on the + // platform. UNIX 98 allows either errno, and they may be the same + // numeric value. So to make life easier for upper ACE layers as + // well as application programmers, always change EAGAIN to + // EWOULDBLOCK. Rather than hack the ACE_OSCALL_RETURN macro, it's + // handled explicitly here. If the ACE_OSCALL macro ever changes, + // this function needs to be reviewed. On Win32, the regular macros + // can be used, as this is not an issue. +#if defined (ACE_WIN32) + ACE_SOCKCALL_RETURN (::send ((ACE_SOCKET) handle, buf, len, flags), int, -1); +#else + int ace_result_; +# if defined (VXWORKS) || defined (HPUX) || defined (ACE_PSOS) + ace_result_ = ::send ((ACE_SOCKET) handle, (char *) buf, len, flags); +# else + ace_result_ = ::send ((ACE_SOCKET) handle, buf, len, flags); +# endif /* VXWORKS */ + if (ace_result_ == -1 && errno == EAGAIN) + errno = EWOULDBLOCK; + return ace_result_; +#endif /* defined (ACE_WIN32) */ +} + +ACE_INLINE int +ACE_OS::recvfrom (ACE_HANDLE handle, + iovec *buffers, + int buffer_count, + size_t &number_of_bytes_recvd, + int &flags, + struct sockaddr *addr, + int *addrlen, + ACE_OVERLAPPED *overlapped, + ACE_OVERLAPPED_COMPLETION_FUNC func) +{ + ACE_OS_TRACE ("ACE_OS::recvfrom"); + +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + DWORD bytes_recvd; + DWORD the_flags = flags; + int result = ::WSARecvFrom ((SOCKET) handle, + (WSABUF*)buffers, + buffer_count, + &bytes_recvd, + &the_flags, + addr, + addrlen, + overlapped, + func); + flags = the_flags; + number_of_bytes_recvd = ACE_static_cast (size_t, bytes_recvd); + return result; +#else + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (buffers); + ACE_UNUSED_ARG (buffer_count); + ACE_UNUSED_ARG (number_of_bytes_recvd); + ACE_UNUSED_ARG (flags); + ACE_UNUSED_ARG (addr); + ACE_UNUSED_ARG (addrlen); + ACE_UNUSED_ARG (overlapped); + ACE_UNUSED_ARG (func); + ACE_NOTSUP_RETURN (-1); +#endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */ +} + +ACE_INLINE int +ACE_OS::sendto (ACE_HANDLE handle, + const char *buf, + int len, + int flags, + const struct sockaddr *addr, + int addrlen) +{ + ACE_OS_TRACE ("ACE_OS::sendto"); +#if defined (VXWORKS) + ACE_SOCKCALL_RETURN (::sendto ((ACE_SOCKET) handle, (char *) buf, len, flags, + ACE_const_cast (struct sockaddr *, addr), addrlen), + int, -1); +#elif defined (ACE_PSOS) +# if !defined (ACE_PSOS_DIAB_PPC) + ACE_SOCKCALL_RETURN (::sendto ((ACE_SOCKET) handle, (char *) buf, len, flags, + (struct sockaddr_in *) addr, addrlen), + int, -1); +# else + ACE_SOCKCALL_RETURN (::sendto ((ACE_SOCKET) handle, (char *) buf, len, flags, + (struct sockaddr *) addr, addrlen), + int, -1); +# endif /*defined ACE_PSOS_DIAB_PPC */ +#else + ACE_SOCKCALL_RETURN (::sendto ((ACE_SOCKET) handle, buf, len, flags, + ACE_const_cast (struct sockaddr *, addr), addrlen), + int, -1); +#endif /* VXWORKS */ +} + +ACE_INLINE int +ACE_OS::sendto (ACE_HANDLE handle, + const iovec *buffers, + int buffer_count, + size_t &number_of_bytes_sent, + int flags, + const struct sockaddr *addr, + int addrlen, + ACE_OVERLAPPED *overlapped, + ACE_OVERLAPPED_COMPLETION_FUNC func) +{ + ACE_OS_TRACE ("ACE_OS::sendto"); +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + DWORD bytes_sent; + int result = ::WSASendTo ((SOCKET) handle, + (WSABUF*)buffers, + buffer_count, + &bytes_sent, + flags, + addr, + addrlen, + overlapped, + func); + number_of_bytes_sent = ACE_static_cast (size_t, bytes_sent); + return result; +#else + ACE_UNUSED_ARG (overlapped); + ACE_UNUSED_ARG (func); + + number_of_bytes_sent = 0; + + int result = 0; + + for (int i = 0; i < buffer_count; i++) + { + result = ACE_OS::sendto (handle, + ACE_reinterpret_cast (char *ACE_CAST_CONST, + buffers[i].iov_base), + buffers[i].iov_len, + flags, + addr, + addrlen); + if (result == -1) + break; + number_of_bytes_sent += result; + } + + return result; +#endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */ +} + +ACE_INLINE int +ACE_OS::getpeername (ACE_HANDLE handle, struct sockaddr *addr, + int *addrlen) +{ + ACE_OS_TRACE ("ACE_OS::getpeername"); +#if defined (ACE_PSOS) && !defined ACE_PSOS_DIAB_PPC + ACE_SOCKCALL_RETURN (::getpeername ((ACE_SOCKET) handle, + (struct sockaddr_in *) addr, + (ACE_SOCKET_LEN *) addrlen), + int, -1); +#else + ACE_SOCKCALL_RETURN (::getpeername ((ACE_SOCKET) handle, + addr, + (ACE_SOCKET_LEN *) addrlen), + int, -1); +#endif /* defined (ACE_PSOS) */ +} + +ACE_INLINE struct protoent * +ACE_OS::getprotobyname (const char *name) +{ +#if defined (VXWORKS) || defined (ACE_HAS_WINCE) || (defined (ghs) && defined (__Chorus)) || defined (ACE_PSOS) + ACE_UNUSED_ARG (name); + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_NONCONST_GETBY) + ACE_SOCKCALL_RETURN (::getprotobyname (ACE_const_cast (char *, name)), + struct protoent *, + 0); +#else + ACE_SOCKCALL_RETURN (::getprotobyname (name), + struct protoent *, + 0); +#endif /* VXWORKS */ +} + +ACE_INLINE struct protoent * +ACE_OS::getprotobyname_r (const char *name, + struct protoent *result, + ACE_PROTOENT_DATA buffer) +{ +#if defined (VXWORKS) || defined (ACE_HAS_WINCE) || (defined (ghs) && defined (__Chorus)) || defined (ACE_PSOS) + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (result); + ACE_UNUSED_ARG (buffer); + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE) +# if defined (AIX) || defined (DIGITAL_UNIX) || defined (HPUX_10) + if (::getprotobyname_r (name, result, (struct protoent_data *) buffer) == 0) + return result; + else + return 0; +# elif defined (__GLIBC__) + // GNU C library has a different signature + if (::getprotobyname_r (name, + result, + buffer, + sizeof (ACE_PROTOENT_DATA), + &result) == 0) + return result; + else + return 0; +# else +# if defined(ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) + ACE_UNUSED_ARG (result); + ACE_NETDBCALL_RETURN (::getprotobyname (name), + struct protoent *, 0, + buffer, sizeof (ACE_PROTOENT_DATA)); +# else + ACE_SOCKCALL_RETURN (::getprotobyname_r (name, + result, + buffer, + sizeof (ACE_PROTOENT_DATA)), + struct protoent *, 0); +# endif /* ACE_LACKS_NETDB_REENTRANT_FUNCTIONS */ +# endif /* defined (AIX) || defined (DIGITAL_UNIX) */ +#elif defined (ACE_HAS_NONCONST_GETBY) + ACE_UNUSED_ARG (result); + ACE_UNUSED_ARG (buffer); + ACE_SOCKCALL_RETURN (::getprotobyname (ACE_const_cast (char *, name)), + struct protoent *, 0); +#else + ACE_UNUSED_ARG (buffer); + ACE_UNUSED_ARG (result); + + ACE_SOCKCALL_RETURN (::getprotobyname (name), + struct protoent *, + 0); +#endif /* defined (ACE_HAS_REENTRANT_FUNCTIONS) !defined (UNIXWARE) */ +} + +ACE_INLINE struct protoent * +ACE_OS::getprotobynumber (int proto) +{ +#if defined (VXWORKS) || defined (ACE_HAS_WINCE) || (defined (ghs) && defined (__Chorus)) || defined (ACE_PSOS) + ACE_UNUSED_ARG (proto); + ACE_NOTSUP_RETURN (0); +#else + ACE_SOCKCALL_RETURN (::getprotobynumber (proto), + struct protoent *, 0); +#endif /* VXWORKS */ +} + +ACE_INLINE struct protoent * +ACE_OS::getprotobynumber_r (int proto, + struct protoent *result, + ACE_PROTOENT_DATA buffer) +{ +#if defined (VXWORKS) || defined (ACE_HAS_WINCE) || (defined (ghs) && defined (__Chorus)) || defined (ACE_PSOS) + ACE_UNUSED_ARG (proto); + ACE_UNUSED_ARG (result); + ACE_UNUSED_ARG (buffer); + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE) +# if defined (AIX) || defined (DIGITAL_UNIX) || defined (HPUX_10) + if (::getprotobynumber_r (proto, result, (struct protoent_data *) buffer) == 0) + return result; + else + return 0; +# elif defined (__GLIBC__) + // GNU C library has a different signature + if (::getprotobynumber_r (proto, + result, + buffer, + sizeof (ACE_PROTOENT_DATA), + &result) == 0) + return result; + else + return 0; +# else +# if defined(ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) + ACE_UNUSED_ARG (result); + ACE_NETDBCALL_RETURN (::getprotobynumber (proto), + struct protoent *, 0, + buffer, sizeof (ACE_PROTOENT_DATA)); +# else + ACE_SOCKCALL_RETURN (::getprotobynumber_r (proto, result, buffer, sizeof (ACE_PROTOENT_DATA)), + struct protoent *, 0); +# endif /* ACE_LACKS_NETDB_REENTRANT_FUNCTIONS */ +# endif /* defined (AIX) || defined (DIGITAL_UNIX) */ +#else + ACE_UNUSED_ARG (buffer); + ACE_UNUSED_ARG (result); + + ACE_SOCKCALL_RETURN (::getprotobynumber (proto), + struct protoent *, 0); +#endif /* defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE) */ +} + +ACE_INLINE struct servent * +ACE_OS::getservbyname (const char *svc, const char *proto) +{ + ACE_OS_TRACE ("ACE_OS::getservbyname"); +#if defined (ACE_LACKS_GETSERVBYNAME) + ACE_UNUSED_ARG (svc); + ACE_UNUSED_ARG (proto); + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_NONCONST_GETBY) + ACE_SOCKCALL_RETURN (::getservbyname (ACE_const_cast (char *, svc), + ACE_const_cast (char *, proto)), + struct servent *, + 0); +#else + ACE_SOCKCALL_RETURN (::getservbyname (svc, + proto), + struct servent *, + 0); +#endif /* ACE_HAS_NONCONST_GETBY */ +} + +ACE_INLINE int +ACE_OS::getsockname (ACE_HANDLE handle, + struct sockaddr *addr, + int *addrlen) +{ + ACE_OS_TRACE ("ACE_OS::getsockname"); +#if defined (ACE_PSOS) && !defined (ACE_PSOS_DIAB_PPC) + ACE_SOCKCALL_RETURN (::getsockname ((ACE_SOCKET) handle, + (struct sockaddr_in *) addr, + (ACE_SOCKET_LEN *) addrlen), + int, -1); +#else + ACE_SOCKCALL_RETURN (::getsockname ((ACE_SOCKET) handle, + addr, + (ACE_SOCKET_LEN *) addrlen), + int, -1); +#endif /* defined (ACE_PSOS) */ +} + +ACE_INLINE int +ACE_OS::getsockopt (ACE_HANDLE handle, + int level, + int optname, + char *optval, + int *optlen) +{ + ACE_OS_TRACE ("ACE_OS::getsockopt"); + ACE_SOCKCALL_RETURN (::getsockopt ((ACE_SOCKET) handle, + level, + optname, + optval, + (ACE_SOCKET_LEN *) optlen), + int, + -1); +} + +ACE_INLINE int +ACE_OS::listen (ACE_HANDLE handle, int backlog) +{ + ACE_OS_TRACE ("ACE_OS::listen"); + ACE_SOCKCALL_RETURN (::listen ((ACE_SOCKET) handle, backlog), int, -1); +} + +ACE_INLINE int +ACE_OS::setsockopt (ACE_HANDLE handle, + int level, + int optname, + const char *optval, + int optlen) +{ + ACE_OS_TRACE ("ACE_OS::setsockopt"); + ACE_SOCKCALL_RETURN (::setsockopt ((ACE_SOCKET) handle, + level, + optname, + (ACE_SOCKOPT_TYPE1) optval, + optlen), + int, + -1); +} + +ACE_INLINE int +ACE_OS::shutdown (ACE_HANDLE handle, int how) +{ + ACE_OS_TRACE ("ACE_OS::shutdown"); + ACE_SOCKCALL_RETURN (::shutdown ((ACE_SOCKET) handle, how), int, -1); +} + +ACE_INLINE ACE_HANDLE +ACE_OS::socket (int domain, + int type, + int proto) +{ + ACE_OS_TRACE ("ACE_OS::socket"); + ACE_SOCKCALL_RETURN (::socket (domain, + type, + proto), + ACE_HANDLE, + ACE_INVALID_HANDLE); +} + +ACE_INLINE ACE_HANDLE +ACE_OS::socket (int domain, + int type, + int proto, + ACE_Protocol_Info *protocolinfo, + ACE_SOCK_GROUP g, + u_long flags) +{ + ACE_OS_TRACE ("ACE_OS::socket"); + +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + ACE_SOCKCALL_RETURN (::WSASocket (domain, + type, + proto, + protocolinfo, + g, + flags), + ACE_HANDLE, + ACE_INVALID_HANDLE); +#else + ACE_UNUSED_ARG (protocolinfo); + ACE_UNUSED_ARG (g); + ACE_UNUSED_ARG (flags); + + return ACE_OS::socket (domain, + type, + proto); +#endif /* ACE_HAS_WINSOCK2 */ +} + +ACE_INLINE int +ACE_OS::atoi (const char *s) +{ +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_atoi (s), int, -1); +#else /* ACE_HAS_PACE */ + ACE_OSCALL_RETURN (::atoi (s), int, -1); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE int +ACE_OS::atoi (const wchar_t *s) +{ +#if defined (ACE_WIN32) + ACE_OSCALL_RETURN (::_wtoi (s), int, -1); +#else /* ACE_WIN32 */ + return ACE_OS::atoi (ACE_Wide_To_Ascii(s).char_rep()); +#endif /* ACE_WIN32 */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE double +ACE_OS::floor (double x) +{ + // This method computes the largest integral value not greater than x. + return double (ACE_static_cast (long, x)); +} + +ACE_INLINE double +ACE_OS::ceil (double x) +{ + // This method computes the smallest integral value not less than x. + double floor = ACE_OS::floor (x); + if (floor == x) + return floor; + else + return floor + 1; +} + +ACE_INLINE int +ACE_OS::recvmsg (ACE_HANDLE handle, struct msghdr *msg, int flags) +{ + ACE_OS_TRACE ("ACE_OS::recvmsg"); +#if !defined (ACE_LACKS_RECVMSG) +# if (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)) + DWORD bytes_received = 0; + + int result = ::WSARecvFrom ((SOCKET) handle, + (WSABUF *) msg->msg_iov, + msg->msg_iovlen, + &bytes_received, + (DWORD *) &flags, + msg->msg_name, + &msg->msg_namelen, + 0, + 0); + + if (result != 0) + { + ACE_OS::set_errno_to_last_error (); + return -1; + } + else + return (ssize_t) bytes_received; +# else /* ACE_HAS_WINSOCK2 */ + ACE_SOCKCALL_RETURN (::recvmsg (handle, msg, flags), int, -1); +# endif /* ACE_HAS_WINSOCK2 */ +#else + ACE_UNUSED_ARG (flags); + ACE_UNUSED_ARG (msg); + ACE_UNUSED_ARG (handle); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_LACKS_RECVMSG */ +} + +ACE_INLINE int +ACE_OS::sendmsg (ACE_HANDLE handle, + const struct msghdr *msg, + int flags) +{ + ACE_OS_TRACE ("ACE_OS::sendmsg"); +#if !defined (ACE_LACKS_SENDMSG) +# if (defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)) + DWORD bytes_sent = 0; + int result = ::WSASendTo ((SOCKET) handle, + (WSABUF *) msg->msg_iov, + msg->msg_iovlen, + &bytes_sent, + flags, + msg->msg_name, + msg->msg_namelen, + 0, + 0); + + if (result != 0) + { + ACE_OS::set_errno_to_last_error (); + return -1; + } + else + return (ssize_t) bytes_sent; +# elif defined (ACE_LACKS_POSIX_PROTOTYPES) || defined (ACE_PSOS) + ACE_SOCKCALL_RETURN (::sendmsg (handle, (struct msghdr *) msg, flags), int, -1); +# else + ACE_SOCKCALL_RETURN (::sendmsg (handle, (ACE_SENDMSG_TYPE *) msg, flags), int, -1); +# endif /* ACE_LACKS_POSIX_PROTOTYPES */ +#else + ACE_UNUSED_ARG (flags); + ACE_UNUSED_ARG (msg); + ACE_UNUSED_ARG (handle); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_LACKS_SENDMSG */ +} + +ACE_INLINE int +ACE_OS::fclose (FILE *fp) +{ +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_fclose (fp), int, -1); +#elif !defined (ACE_HAS_WINCE) + ACE_OS_TRACE ("ACE_OS::fclose"); + ACE_OSCALL_RETURN (::fclose (fp), int, -1); +#else + // On CE, FILE * == void * == HANDLE + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL(::CloseHandle (fp), ace_result_), + int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE ACE_TCHAR * +ACE_OS::fgets (ACE_TCHAR *buf, int size, FILE *fp) +{ + ACE_OS_TRACE ("ACE_OS::fgets"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_fgets (buf, size, fp), char*, 0); +#elif defined (ACE_HAS_WINCE) + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (size); + ACE_UNUSED_ARG (fp); + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR) + ACE_OSCALL_RETURN (::fgetws (buf, size, fp), wchar_t *, 0); +#else /* ACE_WIN32 */ + ACE_OSCALL_RETURN (::fgets (buf, size, fp), char *, 0); +#endif /* ACE_HAS_PACE */ +} + +#if !defined (ACE_WIN32) +// Win32 implementation of fopen(const ACE_TCHAR*, const ACE_TCHAR*) +// is in OS.cpp. +ACE_INLINE FILE * +ACE_OS::fopen (const ACE_TCHAR *filename, const ACE_TCHAR *mode) +{ +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_fopen (filename, mode), FILE*, 0); +#else + ACE_OS_TRACE ("ACE_OS::fopen"); + ACE_OSCALL_RETURN (::fopen (filename, mode), FILE *, 0); +#endif /* ACE_HAS_PACE */ +} +#endif /* ACE_WIN32 */ + +ACE_INLINE FILE * +ACE_OS::freopen (const ACE_TCHAR *filename, const ACE_TCHAR *mode, FILE* stream) +{ + ACE_OS_TRACE ("ACE_OS::freopen"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_freopen (filename, mode, stream), FILE*, 0); +#elif defined (ACE_HAS_WINCE) + ACE_UNUSED_ARG (filename); + ACE_UNUSED_ARG (mode); + ACE_UNUSED_ARG (stream); + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR) + ACE_OSCALL_RETURN (::_wfreopen (filename, mode, stream), FILE *, 0); +#else + ACE_OSCALL_RETURN (::freopen (filename, mode, stream), FILE *, 0); +#endif /* defined (ACE_HAS_PACE) */ +} + +ACE_INLINE int +ACE_OS::fflush (FILE *fp) +{ +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_fflush (fp), int, -1); +#elif !defined (ACE_HAS_WINCE) + ACE_OS_TRACE ("ACE_OS::fflush"); + ACE_OSCALL_RETURN (::fflush (fp), int, -1); +#else + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL(::FlushFileBuffers (fp), + ace_result_), + int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE size_t +ACE_OS::fread (void *ptr, size_t size, size_t nelems, FILE *fp) +{ + ACE_OS_TRACE ("ACE_OS::fread"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_fread (ptr, size, nelems, fp), int, 0); +#elif defined (ACE_HAS_WINCE) + DWORD len = 0; + size_t tlen = size * nelems; + + if (::ReadFile (fp, ptr, tlen, &len, NULL) == FALSE) + { + ACE_OS::set_errno_to_last_error (); + return -1; + } + else if (tlen != len) + { + // only return length of multiple of + len = (len / size) * size ; + // then rewind file pointer. + ::SetFilePointer (fp, (len - tlen), 0, FILE_CURRENT); + } + return len; +#elif defined (ACE_LACKS_POSIX_PROTOTYPES) + ACE_OSCALL_RETURN (::fread ((char *) ptr, size, nelems, fp), int, 0); +#else + ACE_OSCALL_RETURN (::fread (ptr, size, nelems, fp), int, 0); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE size_t +ACE_OS::fwrite (const void *ptr, size_t size, size_t nitems, FILE *fp) +{ + ACE_OS_TRACE ("ACE_OS::fwrite"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_fwrite (ptr, size, nitems, fp), int, 0); +#elif defined (ACE_HAS_WINCE) + DWORD len = 0; + size_t tlen = size * nitems; + + if (::WriteFile (fp, ptr, tlen, &len, NULL) == FALSE) + { + ACE_OS::set_errno_to_last_error (); + return -1; + } + else if (tlen != len) + { + // only return length of multiple of + len = (len / size) * size ; + // then rewind file pointer. + ::SetFilePointer (fp, (len - tlen), 0, FILE_CURRENT); + } + return len; +#elif defined (ACE_LACKS_POSIX_PROTOTYPES) + ACE_OSCALL_RETURN (::fwrite ((const char *) ptr, size, nitems, fp), int, 0); +#else + ACE_OSCALL_RETURN (::fwrite (ptr, size, nitems, fp), int, 0); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::truncate (const ACE_TCHAR *filename, + off_t offset) +{ + ACE_OS_TRACE ("ACE_OS::truncate"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + int fd = ::pace_open (filename, O_RDWR, ACE_DEFAULT_FILE_PERMS); + int result = 0; + if (fd == -1) + return -1; + ACE_OSCALL (::pace_ftruncate (fd, offset), int, -1, result); + pace_close (fd); + return result; +#elif defined (ACE_WIN32) + ACE_HANDLE handle = ACE_OS::open (filename, + O_WRONLY, + ACE_DEFAULT_FILE_PERMS); + if (handle == ACE_INVALID_HANDLE) + ACE_FAIL_RETURN (-1); + else if (::SetFilePointer (handle, + offset, + NULL, + FILE_BEGIN) != (unsigned) -1) + { + BOOL result = ::SetEndOfFile (handle); + ::CloseHandle (handle); + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (result, ace_result_), int, -1); + } + else + { + ::CloseHandle (handle); + ACE_FAIL_RETURN (-1); + } + /* NOTREACHED */ +#elif !defined (ACE_LACKS_TRUNCATE) + ACE_OSCALL_RETURN (::truncate (filename, offset), int, -1); +#else + ACE_UNUSED_ARG (filename); + ACE_UNUSED_ARG (offset); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +// Accessors to PWD file. + +ACE_INLINE struct passwd * +ACE_OS::getpwnam (const char *name) +{ +#if defined (ACE_HAS_PACE) + return ::pace_getpwnam (name); +#elif !defined (ACE_LACKS_PWD_FUNCTIONS) +# if !defined (ACE_WIN32) + return ::getpwnam (name); +# else + ACE_UNUSED_ARG (name); + ACE_NOTSUP_RETURN (0); +# endif /* ACE_WIN32 */ +#else + ACE_UNUSED_ARG (name); + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE void +ACE_OS::setpwent (void) +{ +#if !defined (ACE_LACKS_PWD_FUNCTIONS) +# if !defined (ACE_WIN32) + ::setpwent (); +# else +# endif /* ACE_WIN32 */ +#else +#endif /* ! ACE_LACKS_PWD_FUNCTIONS */ +} + +ACE_INLINE void +ACE_OS::endpwent (void) +{ +#if !defined (ACE_LACKS_PWD_FUNCTIONS) +# if !defined (ACE_WIN32) + ::endpwent (); +# else +# endif /* ACE_WIN32 */ +#else +#endif /* ! ACE_LACKS_PWD_FUNCTIONS */ +} + +ACE_INLINE struct passwd * +ACE_OS::getpwent (void) +{ +#if !defined (ACE_LACKS_PWD_FUNCTIONS) +# if !defined (ACE_WIN32) + return ::getpwent (); +# else + ACE_NOTSUP_RETURN (0); +# endif /* ACE_WIN32 */ +#else + ACE_NOTSUP_RETURN (0); +#endif /* ! ACE_LACKS_PWD_FUNCTIONS */ +} + +ACE_INLINE struct passwd * +ACE_OS::getpwnam_r (const char *name, struct passwd *pwent, + char *buffer, int buflen) +{ +#if defined (ACE_HAS_PACE) || defined (ACE_HAS_POSIX_GETPWNAM_R) + struct passwd *result; + int status; + +# if defined (ACE_HAS_PACE) + status = ::pace_getpwnam_r (name, pwent, buffer, buflen, &result); +# else + status = ::getpwnam_r (name, pwent, buffer, buflen, &result); +# endif /* ACE_HAS_PACE */ + + if (status != 0) + { + errno = status; + result = 0; + } + return result; +#elif !defined (ACE_LACKS_PWD_FUNCTIONS) +# if defined (ACE_HAS_REENTRANT_FUNCTIONS) +# if !defined (ACE_LACKS_PWD_REENTRANT_FUNCTIONS) +# if defined (ACE_HAS_PTHREADS_STD) && \ + !defined (ACE_HAS_STHREADS) || \ + defined (HPUX_11) || \ + defined (__USLC__) // Added by Roland Gigler for SCO UnixWare 7. + struct passwd *result; + int status; +# if defined (DIGITAL_UNIX) + ::_Pgetpwnam_r (name, pwent, buffer, buflen, &result); +# else + // VAC++ doesn't correctly grok the ::getpwnam_r - the function is redefined + // in pwd.h, and that redefinition is used here +# if defined (__IBMCPP__) && (__IBMCPP__ >= 400) /* VAC++ 4 */ + status = _posix_getpwnam_r (name, pwent, buffer, buflen, &result); +# else + status = ::getpwnam_r (name, pwent, buffer, buflen, &result); +# endif /* __IBMCPP__ && (__IBMCPP__ >= 400) */ + if (status != 0) + { + errno = status; + result = 0; + } +# endif /* (DIGITAL_UNIX) */ + return result; +# elif defined (AIX) || defined (HPUX_10) + if (::getpwnam_r (name, pwent, buffer, buflen) == -1) + return 0; + else + return pwent; +# else + return ::getpwnam_r (name, pwent, buffer, buflen); +# endif /* ACE_HAS_PTHREADS_STD */ +# else + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (pwent); + ACE_UNUSED_ARG (buffer); + ACE_UNUSED_ARG (buflen); + ACE_NOTSUP_RETURN (0); +# endif /* ! ACE_LACKS_PWD_REENTRANT_FUNCTIONS */ +# else + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (pwent); + ACE_UNUSED_ARG (buffer); + ACE_UNUSED_ARG (buflen); + ACE_NOTSUP_RETURN (0); +# endif /* ACE_HAS_REENTRANT_FUNCTIONS */ +#else + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (pwent); + ACE_UNUSED_ARG (buffer); + ACE_UNUSED_ARG (buflen); + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_PACE */ +} + +// DNS accessors. + +#if !defined (VXWORKS) +ACE_INLINE struct hostent * +ACE_OS::gethostbyaddr_r (const char *addr, + int length, + int type, + hostent *result, + ACE_HOSTENT_DATA buffer, + int *h_errnop) +{ + ACE_OS_TRACE ("ACE_OS::gethostbyaddr_r"); +# if defined (ACE_PSOS) + ACE_UNUSED_ARG (addr); + ACE_UNUSED_ARG (length); + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (result); + ACE_UNUSED_ARG (buffer); + ACE_UNUSED_ARG (h_errnop); + ACE_NOTSUP_RETURN (0); +# elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE) +# if defined (AIX) || defined (DIGITAL_UNIX) || defined (HPUX_10) + ::memset (buffer, 0, sizeof (ACE_HOSTENT_DATA)); + + if (::gethostbyaddr_r ((char *) addr, length, type, result, + (struct hostent_data *) buffer)== 0) + return result; + else + { + *h_errnop = h_errno; + return (struct hostent *) 0; + } +# elif defined (__GLIBC__) + // GNU C library has a different signature + ::memset (buffer, 0, sizeof (ACE_HOSTENT_DATA)); + + if (::gethostbyaddr_r ((char *) addr, + length, + type, + result, + buffer, + sizeof (ACE_HOSTENT_DATA), + &result, + h_errnop) == 0) + return result; + else + return (struct hostent *) 0; +# else +# if defined(ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) + ACE_UNUSED_ARG (result); + ACE_UNUSED_ARG (h_errnop); + ACE_NETDBCALL_RETURN (::gethostbyaddr (addr, (ACE_SOCKET_LEN) length, type), + struct hostent *, 0, + buffer, sizeof (ACE_HOSTENT_DATA)); +# else + ACE_SOCKCALL_RETURN (::gethostbyaddr_r (addr, length, type, result, + buffer, sizeof (ACE_HOSTENT_DATA), + h_errnop), + struct hostent *, 0); +# endif /* ACE_LACKS_NETDB_REENTRANT_FUNCTIONS */ +# endif /* defined (AIX) || defined (DIGITAL_UNIX) */ +# elif defined (ACE_HAS_NONCONST_GETBY) + ACE_UNUSED_ARG (result); + ACE_UNUSED_ARG (buffer); + ACE_UNUSED_ARG (h_errnop); + ACE_SOCKCALL_RETURN (::gethostbyaddr (ACE_const_cast (char *, addr), + (ACE_SOCKET_LEN) length, + type), + struct hostent *, + 0); +# else + ACE_UNUSED_ARG (h_errnop); + ACE_UNUSED_ARG (buffer); + ACE_UNUSED_ARG (result); + + ACE_SOCKCALL_RETURN (::gethostbyaddr (addr, + (ACE_SOCKET_LEN) length, + type), + struct hostent *, + 0); +# endif /* defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE) */ +} + +ACE_INLINE struct hostent * +ACE_OS::gethostbyname_r (const char *name, + hostent *result, + ACE_HOSTENT_DATA buffer, + int *h_errnop) +{ + ACE_OS_TRACE ("ACE_OS::gethostbyname_r"); +#if defined (ACE_PSOS) + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (result); + ACE_UNUSED_ARG (buffer); + ACE_UNUSED_ARG (h_errnop); + ACE_NOTSUP_RETURN (0); +# elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE) +# if defined (DIGITAL_UNIX) || \ + (defined (ACE_AIX_MINOR_VERS) && (ACE_AIX_MINOR_VERS > 2)) + ACE_UNUSED_ARG (result); + ACE_UNUSED_ARG (buffer); + ACE_UNUSED_ARG (h_errnop); + + // gethostbyname returns thread-specific storage on Digital Unix and + // AIX 4.3 + ACE_SOCKCALL_RETURN (::gethostbyname (name), struct hostent *, 0); +# elif defined (AIX) || defined (HPUX_10) + ::memset (buffer, 0, sizeof (ACE_HOSTENT_DATA)); + + if (::gethostbyname_r (name, result, (struct hostent_data *) buffer) == 0) + return result; + else + { + *h_errnop = h_errno; + return (struct hostent *) 0; + } +# elif defined (__GLIBC__) + // GNU C library has a different signature + ::memset (buffer, 0, sizeof (ACE_HOSTENT_DATA)); + + if (::gethostbyname_r (name, + result, + buffer, + sizeof (ACE_HOSTENT_DATA), + &result, + h_errnop) == 0) + return result; + else + return (struct hostent *) 0; +# else +# if defined(ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) + ACE_UNUSED_ARG (result); + ACE_UNUSED_ARG (h_errnop); + ACE_NETDBCALL_RETURN (::gethostbyname (name), + struct hostent *, 0, + buffer, sizeof (ACE_HOSTENT_DATA)); +# else + ACE_SOCKCALL_RETURN (::gethostbyname_r (name, result, buffer, + sizeof (ACE_HOSTENT_DATA), + h_errnop), + struct hostent *, + 0); +# endif /* ACE_LACKS_NETDB_REENTRANT_FUNCTIONS */ +# endif /* defined (AIX) || defined (DIGITAL_UNIX) */ +# elif defined (ACE_HAS_NONCONST_GETBY) + ACE_UNUSED_ARG (result); + ACE_UNUSED_ARG (buffer); + ACE_UNUSED_ARG (h_errnop); + ACE_SOCKCALL_RETURN (::gethostbyname (ACE_const_cast (char *, name)), + struct hostent *, + 0); +# else + ACE_UNUSED_ARG (result); + ACE_UNUSED_ARG (buffer); + ACE_UNUSED_ARG (h_errnop); + + ACE_SOCKCALL_RETURN (::gethostbyname (name), + struct hostent *, + 0); +# endif /* defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE) */ +} +#endif /* ! VXWORKS */ + +#if 0 +// @@ gets is evil anyway. +// and it is *** DEPRECATED *** now. If you +// really needs gets, use ACE_OS::gets (char*, int) +// instead. +ACE_INLINE char * +ACE_OS::gets (char *str) +{ + ACE_OS_TRACE ("ACE_OS::gets"); + ACE_OSCALL_RETURN (::gets (str), char *, 0); +} +#endif /* 0 */ + +ACE_INLINE struct servent * +ACE_OS::getservbyname_r (const char *svc, + const char *proto, + struct servent *result, + ACE_SERVENT_DATA buf) +{ + ACE_OS_TRACE ("ACE_OS::getservbyname_r"); +#if defined (ACE_LACKS_GETSERVBYNAME) + ACE_UNUSED_ARG (svc); + ACE_UNUSED_ARG (proto); + ACE_UNUSED_ARG (result); + ACE_UNUSED_ARG (buf); + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE) +# if defined (AIX) || defined (DIGITAL_UNIX) || defined (HPUX_10) + ::memset (buf, 0, sizeof (ACE_SERVENT_DATA)); + + if (::getservbyname_r (svc, proto, result, (struct servent_data *) buf) == 0) + return result; + else + return (struct servent *) 0; +# elif defined (__GLIBC__) + // GNU C library has a different signature + ::memset (buf, 0, sizeof (ACE_SERVENT_DATA)); + + if (::getservbyname_r (svc, + proto, + result, + buf, + sizeof (ACE_SERVENT_DATA), + &result) == 0) + return result; + else + return (struct servent *) 0; +# else +# if defined(ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) + ACE_UNUSED_ARG (result); + ACE_NETDBCALL_RETURN (::getservbyname (svc, proto), + struct servent *, 0, + buf, sizeof (ACE_SERVENT_DATA)); +# else + ACE_SOCKCALL_RETURN (::getservbyname_r (svc, proto, result, buf, + sizeof (ACE_SERVENT_DATA)), + struct servent *, 0); +# endif /* ACE_LACKS_NETDB_REENTRANT_FUNCTIONS */ +# endif /* defined (AIX) || defined (DIGITAL_UNIX) */ +#elif defined (ACE_HAS_NONCONST_GETBY) + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (result); + ACE_SOCKCALL_RETURN (::getservbyname (ACE_const_cast (char *, svc), + ACE_const_cast (char *, proto)), + struct servent *, + 0); +#else + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (result); + + ACE_SOCKCALL_RETURN (::getservbyname (svc, + proto), + struct servent *, + 0); +#endif /* defined (ACE_HAS_REENTRANT_FUNCTIONS) && !defined (UNIXWARE) */ +} + +ACE_INLINE unsigned long +ACE_OS::inet_addr (const char *name) +{ + ACE_OS_TRACE ("ACE_OS::inet_addr"); +#if defined (VXWORKS) || defined (ACE_PSOS) + + u_long ret = 0; + u_int segment; + u_int valid = 1; + + for (u_int i = 0; i < 4; ++i) + { + ret <<= 8; + if (*name != '\0') + { + segment = 0; + + while (*name >= '0' && *name <= '9') + { + segment *= 10; + segment += *name++ - '0'; + } + if (*name != '.' && *name != '\0') + { + valid = 0; + break; + } + + ret |= segment; + + if (*name == '.') + { + ++name; + } + } + } + return valid ? htonl (ret) : INADDR_NONE; +#elif defined (ACE_HAS_NONCONST_GETBY) + return ::inet_addr ((char *) name); +#else + return ::inet_addr (name); +#endif /* ACE_HAS_NONCONST_GETBY */ +} + +// For pSOS, this function is in OS.cpp +#if !defined (ACE_PSOS) +ACE_INLINE char * +ACE_OS::inet_ntoa (const struct in_addr addr) +{ + ACE_OS_TRACE ("ACE_OS::inet_ntoa"); + ACE_OSCALL_RETURN (::inet_ntoa (addr), + char *, + 0); +} +#endif /* defined (ACE_PSOS) */ + +ACE_INLINE int +ACE_OS::inet_pton (int family, const char *strptr, void *addrptr) +{ + ACE_OS_TRACE ("ACE_OS::inet_pton"); + +#if defined (ACE_HAS_IPV6) + ACE_OSCALL_RETURN (::inet_pton (family, strptr, addrptr), int, -1); +#else + if (family == AF_INET) + { + struct in_addr in_val; + + if (ACE_OS::inet_aton (strptr, &in_val)) + { + ACE_OS::memcpy (addrptr, &in_val, sizeof (struct in_addr)); + return 1; // Success + } + + return 0; // Input is not a valid presentation format + } + + ACE_NOTSUP_RETURN(-1); +#endif /* ACE_HAS_IPV6 */ +} + +ACE_INLINE const char * +ACE_OS::inet_ntop (int family, const void *addrptr, char *strptr, size_t len) +{ + ACE_OS_TRACE ("ACE_OS::inet_ntop"); + +#if defined (ACE_HAS_IPV6) + ACE_OSCALL_RETURN (::inet_ntop (family, addrptr, strptr, len), const char *, 0); +#else + const u_char *p = + ACE_reinterpret_cast (const u_char *, addrptr); + + if (family == AF_INET) + { + char temp[INET_ADDRSTRLEN]; + + // Stevens uses snprintf() in his implementation but snprintf() + // doesn't appear to be very portable. For now, hope that using + // sprintf() will not cause any string/memory overrun problems. + ACE_OS::sprintf (temp, + "%d.%d.%d.%d", + p[0], p[1], p[2], p[3]); + + if (ACE_OS::strlen (temp) >= len) + { + errno = ENOSPC; + return 0; // Failure + } + + ACE_OS::strcpy (strptr, temp); + return strptr; + } + + ACE_NOTSUP_RETURN(0); +#endif /* ACE_HAS_IPV6 */ +} + +ACE_INLINE int +ACE_OS::set_errno_to_last_error (void) +{ +# if defined (ACE_WIN32) +// Borland C++ Builder 4 has a bug in the RTL that resets the +// value to zero when errno is accessed. Thus, we have +// to use this to set errno to GetLastError. It's bad, but only for +// WIN32. +# if defined(__BORLANDC__) && (__BORLANDC__ == 0x540) || defined (__IBMCPP__) && (__IBMCPP__ >= 400) + int last_error = ::GetLastError (); + return errno = last_error; +# else /* defined(__BORLANDC__) && (__BORLANDC__ == 0x540) */ + return errno = ::GetLastError (); +# endif /* defined(__BORLANDC__) && (__BORLANDC__ == 0x540) */ +#else + return errno; +# endif /* defined(ACE_WIN32) */ +} + +ACE_INLINE int +ACE_OS::set_errno_to_wsa_last_error (void) +{ +# if defined (ACE_WIN32) +// Borland C++ Builder 4 has a bug in the RTL that resets the +// value to zero when errno is accessed. Thus, we have +// to use this to set errno to GetLastError. It's bad, but only for +// WIN32 +# if defined(__BORLANDC__) && (__BORLANDC__ == 0x540) || defined (__IBMCPP__) && (__IBMCPP__ >= 400) + int last_error = ::WSAGetLastError (); + return errno = last_error; +# else /* defined(__BORLANDC__) && (__BORLANDC__ == 0x540) */ + return errno = ::WSAGetLastError (); +# endif /* defined(__BORLANDC__) && (__BORLANDC__ == 0x540) */ +#else + return errno; +# endif /* defined(ACE_WIN32) */ +} + +ACE_INLINE int +ACE_OS::last_error (void) +{ + // ACE_OS_TRACE ("ACE_OS::last_error"); + +#if defined (ACE_WIN32) + int lerror = ::GetLastError (); + int lerrno = errno; + return lerrno == 0 ? lerror : lerrno; +#else + return errno; +#endif /* ACE_WIN32 */ +} + +ACE_INLINE void +ACE_OS::last_error (int error) +{ + ACE_OS_TRACE ("ACE_OS::last_error"); +#if defined (ACE_WIN32) + ::SetLastError (error); +#else + errno = error; +#endif /* ACE_WIN32 */ +} + +ACE_INLINE void +ACE_OS::perror (const ACE_TCHAR *s) +{ + ACE_OS_TRACE ("ACE_OS::perror"); +#if defined (ACE_HAS_PACE) + ::pace_perror (s); +#elif defined (ACE_HAS_WINCE) + // @@ WINCE: How should this be handled + ACE_UNUSED_ARG (s); +#elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR) + ::_wperror (s); +#else + ::perror (s); +#endif /* ACE_HAS_PACE */ +} + + +// @@ WINCE: Do we need to implement puts on WinCE??? +#if !defined (ACE_HAS_WINCE) +ACE_INLINE int +ACE_OS::puts (const ACE_TCHAR *s) +{ + ACE_OS_TRACE ("ACE_OS::puts"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_puts (s), int, -1); +#elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR) + ACE_OSCALL_RETURN (::_putws (s), int, -1); +#else /* ACE_WIN32 */ + ACE_OSCALL_RETURN (::puts (s), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::fputs (const ACE_TCHAR *s, FILE *stream) +{ + ACE_OS_TRACE ("ACE_OS::fputs"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_fputs (s, stream), int, -1); +#elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR) + ACE_OSCALL_RETURN (::fputws (s, stream), int, -1); +#else /* ACE_WIN32 */ + ACE_OSCALL_RETURN (::fputs (s, stream), int, -1); +#endif /* ACE_HAS_PACE */ +} +#endif /* ! ACE_HAS_WINCE */ + +ACE_INLINE ACE_SignalHandler +ACE_OS::signal (int signum, ACE_SignalHandler func) +{ + if (signum == 0) + return 0; + else +#if defined (ACE_HAS_PACE) +# if defined (ACE_HAS_LYNXOS_SIGNALS) + return (void (*)(...))::pace_signal (signum, (void (*)(int)) func); +# else + return ::pace_signal (signum, func); +# endif /* ACE_HAS_LYNXOS_SIGNALS */ +#elif defined (ACE_PSOS) && !defined (ACE_PSOS_TM) && !defined (ACE_PSOS_DIAB_MIPS) && !defined (ACE_PSOS_DIAB_PPC) + return (ACE_SignalHandler) ::signal (signum, (void (*)(void)) func); +#elif defined (ACE_PSOS_DIAB_MIPS) || defined (ACE_PSOS_DIAB_PPC) + return 0; +#elif defined (ACE_PSOS_TM) + // @@ It would be good to rework this so the ACE_PSOS_TM specific + // branch is not needed, but prying it out of ACE_LACKS_UNIX_SIGNALS + // will take some extra work - deferred for now. + return (ACE_SignalHandler) ::signal (signum, (void (*)(int)) func); +#elif defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) || !defined (ACE_LACKS_UNIX_SIGNALS) +# if !defined (ACE_HAS_TANDEM_SIGNALS) && !defined (ACE_HAS_LYNXOS_SIGNALS) + return ::signal (signum, func); +# else + return (ACE_SignalHandler) ::signal (signum, (void (*)(int)) func); +# endif /* !ACE_HAS_TANDEM_SIGNALS */ +#else + // @@ WINCE: Don't know how to implement signal on WinCE (yet.) + ACE_UNUSED_ARG (signum); + ACE_UNUSED_ARG (func); + ACE_NOTSUP_RETURN (0); // Should return SIG_ERR but it is not defined on WinCE. +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::system (const ACE_TCHAR *s) +{ + // ACE_OS_TRACE ("ACE_OS::system"); +#if defined (CHORUS) || defined (ACE_HAS_WINCE) || defined(ACE_PSOS) + ACE_UNUSED_ARG (s); + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR) + ACE_OSCALL_RETURN (::_wsystem (s), int, -1); +#else + ACE_OSCALL_RETURN (::system (s), int, -1); +#endif /* !CHORUS */ +} + +ACE_INLINE int +ACE_OS::thr_continue (ACE_hthread_t target_thread) +{ + ACE_OS_TRACE ("ACE_OS::thr_continue"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_continue (target_thread), ace_result_), int, -1); +# elif defined (ACE_HAS_PTHREADS) +# if defined (ACE_HAS_PTHREADS_UNIX98_EXT) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_continue (target_thread), + ace_result_), + int, -1); +# else + ACE_UNUSED_ARG (target_thread); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */ +# elif defined (ACE_HAS_WTHREADS) + DWORD result = ::ResumeThread (target_thread); + if (result == ACE_SYSCALL_FAILED) + ACE_FAIL_RETURN (-1); + else + return 0; +# elif defined (ACE_PSOS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::t_resume (target_thread), ace_result_), int, -1); +# elif defined (VXWORKS) +# if defined (ACE_HAS_PACE) + // pthread_continue (like pthread_suspend) is not an official POSIX + // function. We get this for free with ACE. So use the thread ID from + // the pace_pthread_t structure. + ACE_OSCALL_RETURN (::taskResume (target_thread->tid), int, -1); +# else + ACE_OSCALL_RETURN (::taskResume (target_thread), int, -1); +# endif /* ACE_HAS_PACE */ +# endif /* ACE_HAS_STHREADS */ +#else + ACE_UNUSED_ARG (target_thread); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thr_cmp (ACE_hthread_t t1, ACE_hthread_t t2) +{ +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + return ::pace_pthread_equal (t1, t2); +#elif defined (ACE_HAS_PTHREADS) +# if defined (pthread_equal) + // If it's a macro we can't say "::pthread_equal"... + return pthread_equal (t1, t2); +# else + return ::pthread_equal (t1, t2); +# endif /* pthread_equal */ +#else /* For STHREADS, WTHREADS, and VXWORKS ... */ + // Hum, Do we need to treat WTHREAD differently? + // levine 13 oct 98 % Probably, ACE_hthread_t is a HANDLE. + return t1 == t2; +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::thr_getconcurrency (void) +{ + ACE_OS_TRACE ("ACE_OS::thr_getconcurrency"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_STHREADS) + return ::thr_getconcurrency (); +# elif defined (ACE_HAS_PTHREADS) || defined (VXWORKS) || defined (ACE_PSOS) + ACE_NOTSUP_RETURN (-1); +# elif defined (ACE_HAS_WTHREADS) + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thr_getprio (ACE_hthread_t thr_id, int &prio) +{ + ACE_OS_TRACE ("ACE_OS::thr_getprio"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + struct sched_param param; + int result; + int policy = 0; + + result = ::pace_pthread_getschedparam (thr_id, &policy, ¶m); + + prio = param.sched_priority; + return result; +#elif defined (ACE_HAS_THREADS) +# if (defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_SETSCHED)) + +# if defined (ACE_HAS_PTHREADS_DRAFT4) + int result; + result = ::pthread_getprio (thr_id); + if (result != -1) + { + prio = result; + return 0; + } + else + return -1; +# elif defined (ACE_HAS_PTHREADS_DRAFT6) + + pthread_attr_t attr; + if (pthread_getschedattr (thr_id, &attr) == 0) + { + prio = pthread_attr_getprio(&attr); + return 0; + } + return -1; +# else + + struct sched_param param; + int result; + int policy = 0; + + ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_getschedparam (thr_id, &policy, ¶m), + result), int, + -1, result); + prio = param.sched_priority; + return result; +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_getprio (thr_id, &prio), ace_result_), int, -1); +# elif defined (ACE_HAS_WTHREADS) + prio = ::GetThreadPriority (thr_id); + if (prio == THREAD_PRIORITY_ERROR_RETURN) + ACE_FAIL_RETURN (-1); + else + return 0; +# elif defined (ACE_PSOS) + // passing a 0 in the second argument does not alter task priority, third arg gets existing one + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::t_setpri (thr_id, 0, (u_long *) &prio), ace_result_), int, -1); +# elif defined (VXWORKS) + ACE_OSCALL_RETURN (::taskPriorityGet (thr_id, &prio), int, -1); +# else + ACE_UNUSED_ARG (thr_id); + ACE_UNUSED_ARG (prio); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_STHREADS */ +#else + ACE_UNUSED_ARG (thr_id); + ACE_UNUSED_ARG (prio); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_TSS_EMULATION) + +# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) +ACE_INLINE int +ACE_OS::thr_getspecific (ACE_OS_thread_key_t key, void **data) +{ + ACE_OS_TRACE ("ACE_OS::thr_getspecific"); +// If we are using TSS emulation then we shuld use ACE's implementation +// of it and not make any PACE calls. +//# if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) +// *data = ::pace_pthread_getspecific (key); +// return 0; +//# elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) +# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) + return pthread_getspecific (key, data); +# else /* this is ACE_HAS_PTHREADS_DRAFT7 or STD */ +# if (pthread_getspecific) + // This is a macro on some platforms, e.g., CHORUS! + *data = pthread_getspecific (key); +# else + *data = pthread_getspecific (key); +# endif /* pthread_getspecific */ +# endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */ + return 0; +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_getspecific (key, data), ace_result_), int, -1); +# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS) + ACE_hthread_t tid; + ACE_OS::thr_self (tid); + return (::tsd_getval (key, tid, data) == 0) ? 0 : -1; +# elif defined (ACE_HAS_WTHREADS) + + // The following handling of errno is designed like this due to + // ACE_Log_Msg::instance calling ACE_OS::thr_getspecific. + // Basically, it is ok for a system call to reset the error to zero. + // (It really shouldn't, though). However, we have to remember to + // store errno *immediately* after an error is detected. Calling + // ACE_ERROR_RETURN((..., errno)) did not work because errno was + // cleared before being passed to the thread-specific instance of + // ACE_Log_Msg. The workaround for was to make it so + // thr_getspecific did not have the side effect of clearing errno. + // The correct fix is for ACE_ERROR_RETURN to store errno + //(actually ACE_OS::last_error) before getting the ACE_Log_Msg tss + // pointer, which is how it is implemented now. However, other uses + // of ACE_Log_Msg may not work correctly, so we're keeping this as + // it is for now. + + ACE_Errno_Guard error (errno); + *data = ::TlsGetValue (key); +# if !defined (ACE_HAS_WINCE) + if (*data == 0 && (error = ::GetLastError ()) != NO_ERROR) + return -1; + else +# endif /* ACE_HAS_WINCE */ + return 0; +# endif /* ACE_HAS_STHREADS */ +# else + ACE_UNUSED_ARG (key); + ACE_UNUSED_ARG (data); + ACE_NOTSUP_RETURN (-1); +//# endif /* ACE_HAS_PACE */ +# endif /* ACE_HAS_THREADS */ +} +# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ + +# if !defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) +ACE_INLINE +void **& +ACE_TSS_Emulation::tss_base () +{ +# if defined (VXWORKS) + return (void **&) taskIdCurrent->ACE_VXWORKS_SPARE; +# elif defined (ACE_PSOS) + // not supported + long x=0; //JINLU + return (void **&) x; +# else + // Uh oh. + ACE_NOTSUP_RETURN (0); +# endif /* VXWORKS */ +} +# endif /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */ + +ACE_INLINE +ACE_TSS_Emulation::ACE_TSS_DESTRUCTOR +ACE_TSS_Emulation::tss_destructor (const ACE_thread_key_t key) +{ + ACE_KEY_INDEX (key_index, key); + return tss_destructor_ [key_index]; +} + +ACE_INLINE +void +ACE_TSS_Emulation::tss_destructor (const ACE_thread_key_t key, + ACE_TSS_DESTRUCTOR destructor) +{ + ACE_KEY_INDEX (key_index, key); + tss_destructor_ [key_index] = destructor; +} + +ACE_INLINE +void *& +ACE_TSS_Emulation::ts_object (const ACE_thread_key_t key) +{ + ACE_KEY_INDEX (key_index, key); + +#if defined (ACE_PSOS) + u_long tss_base; + t_getreg (0, PSOS_TASK_REG_TSS, &tss_base); + return ((void **) tss_base)[key_index]; +#else +# if defined (VXWORKS) + /* If someone wants tss_base make sure they get one. This + gets used if someone spawns a VxWorks task directly, not + through ACE. The allocated array will never be deleted! */ + if (0 == taskIdCurrent->ACE_VXWORKS_SPARE) + { + taskIdCurrent->ACE_VXWORKS_SPARE = + ACE_reinterpret_cast (int, new void *[ACE_TSS_THREAD_KEYS_MAX]); + + // Zero the entire TSS array. Do it manually instead of using + // memset, for optimum speed. Though, memset may be faster :-) + void **tss_base_p = + ACE_reinterpret_cast (void **, taskIdCurrent->ACE_VXWORKS_SPARE); + for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p) + { + *tss_base_p = 0; + } + } +# endif /* VXWORKS */ + + return tss_base ()[key_index]; +#endif /* defined (ACE_PSOS) */ +} + +#endif /* ACE_HAS_TSS_EMULATION */ + + +ACE_INLINE int +ACE_OS::thr_getspecific (ACE_thread_key_t key, void **data) +{ + // ACE_OS_TRACE ("ACE_OS::thr_getspecific"); + // If we are using TSS emulation then we shuld use ACE's implementation + // of it and not make any PACE calls. +#if defined (ACE_HAS_PACE) && !defined (ACE_HAS_TSS_EMULATION) && !defined (ACE_WIN32) + *data = ::pace_pthread_getspecific (key); + return 0; +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_TSS_EMULATION) + ACE_KEY_INDEX (key_index, key); + if (key_index >= ACE_TSS_Emulation::total_keys ()) + { + errno = EINVAL; + data = 0; + return -1; + } + else + { + *data = ACE_TSS_Emulation::ts_object (key); + return 0; + } +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_getspecific (key, data), ace_result_), int, -1); +# elif defined (ACE_HAS_PTHREADS) +# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) + return ::pthread_getspecific (key, data); +# else /* this is Draft 7 or STD */ + *data = pthread_getspecific (key); + return 0; +# endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */ +# elif defined (ACE_HAS_WTHREADS) + + // The following handling of errno is designed like this due to + // ACE_Log_Msg::instance calling ACE_OS::thr_getspecific. + // Basically, it is ok for a system call to reset the error to zero. + // (It really shouldn't, though). However, we have to remember to + // store errno *immediately* after an error is detected. Calling + // ACE_ERROR_RETURN((..., errno)) did not work because errno was + // cleared before being passed to the thread-specific instance of + // ACE_Log_Msg. The workaround for was to make it so + // thr_getspecific did not have the side effect of clearing errno. + // The correct fix is for ACE_ERROR_RETURN to store errno + //(actually ACE_OS::last_error) before getting the ACE_Log_Msg tss + // pointer, which is how it is implemented now. However, other uses + // of ACE_Log_Msg may not work correctly, so we're keeping this as + // it is for now. + + ACE_Errno_Guard error (errno); + *data = ::TlsGetValue (key); +# if !defined (ACE_HAS_WINCE) + if (*data == 0 && (error = ::GetLastError ()) != NO_ERROR) + + return -1; + else +# endif /* ACE_HAS_WINCE */ + return 0; +# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS) + ACE_hthread_t tid; + ACE_OS::thr_self (tid); + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::tsd_getval (key, tid, data), + ace_result_), + int, -1); +# else + ACE_UNUSED_ARG (key); + ACE_UNUSED_ARG (data); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_STHREADS */ +#else + ACE_UNUSED_ARG (key); + ACE_UNUSED_ARG (data); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE && !ACE_HAS_TSS_EMULATION */ +} + +ACE_INLINE int +ACE_OS::thr_join (ACE_hthread_t thr_handle, + void **status) +{ + ACE_OS_TRACE ("ACE_OS::thr_join"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN ( ACE_ADAPT_RETVAL (::pace_pthread_join + (thr_handle, status), + ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_join (thr_handle, 0, status), ace_result_), + int, -1); +# elif defined (ACE_HAS_PTHREADS) +# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) + int ace_result; +# if defined (ACE_LACKS_NULL_PTHREAD_STATUS) + void *temp; + ACE_OSCALL (::pthread_join (thr_handle, + status == 0 ? &temp : status), + int, -1, ace_result); +# else + ACE_OSCALL (::pthread_join (thr_handle, status), int, -1, ace_result); +# endif /* ACE_LACKS_NULL_PTHREAD_STATUS */ + // Joinable threads need to be detached after joining on Pthreads + // draft 4 (at least) to reclaim thread storage. +# if defined (ACE_HAS_PTHREADS_DRAFT4) +# if defined (HPUX_10) + // HP-UX DCE threads' pthread_detach will smash thr_id if it's just given + // as an argument. Since the id is still needed, give pthread_detach + // a junker to scribble on. + ACE_thread_t junker; + cma_handle_assign(&thr_handle, &junker); + ::pthread_detach (&junker); +# else + ::pthread_detach (&thr_handle); +# endif /* HPUX_10 */ +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + + return ace_result; + +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_join (thr_handle, status), ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */ +# elif defined (ACE_HAS_WTHREADS) + void *local_status = 0; + + // Make sure that status is non-NULL. + if (status == 0) + status = &local_status; + + if (::WaitForSingleObject (thr_handle, INFINITE) == WAIT_OBJECT_0 + && ::GetExitCodeThread (thr_handle, (LPDWORD) status) != FALSE) + { + ::CloseHandle (thr_handle); + return 0; + } + ACE_FAIL_RETURN (-1); + /* NOTREACHED */ +# elif defined (VXWORKS) || defined (ACE_PSOS) + ACE_UNUSED_ARG (thr_handle); + ACE_UNUSED_ARG (status); + ACE_NOTSUP_RETURN (-1); +# else + ACE_UNUSED_ARG (thr_handle); + ACE_UNUSED_ARG (status); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_STHREADS */ +#else + ACE_UNUSED_ARG (thr_handle); + ACE_UNUSED_ARG (status); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::thr_join (ACE_thread_t waiter_id, + ACE_thread_t *thr_id, + void **status) +{ + ACE_OS_TRACE ("ACE_OS::thr_join"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_UNUSED_ARG (thr_id); + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_join + (waiter_id, status), + ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_join (waiter_id, thr_id, status), ace_result_), + int, -1); +# elif defined (ACE_HAS_PTHREADS) + ACE_UNUSED_ARG (thr_id); +# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) +# if defined (ACE_LACKS_NULL_PTHREAD_STATUS) + void *temp; + ACE_OSCALL_RETURN (::pthread_join (waiter_id, + status == 0 ? &temp : status), int, -1); +# else + ACE_OSCALL_RETURN (::pthread_join (waiter_id, status), int, -1); +# endif +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_join (waiter_id, status), ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */ +# elif defined (ACE_HAS_WTHREADS) + ACE_UNUSED_ARG (waiter_id); + ACE_UNUSED_ARG (thr_id); + ACE_UNUSED_ARG (status); + + // This could be implemented if the DLL-Main function or the + // task exit base class some log the threads which have exited + ACE_NOTSUP_RETURN (-1); +# elif defined (VXWORKS) || defined (ACE_PSOS) + ACE_UNUSED_ARG (waiter_id); + ACE_UNUSED_ARG (thr_id); + ACE_UNUSED_ARG (status); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_STHREADS */ +#else + ACE_UNUSED_ARG (waiter_id); + ACE_UNUSED_ARG (thr_id); + ACE_UNUSED_ARG (status); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::thr_setcancelstate (int new_state, int *old_state) +{ + ACE_OS_TRACE ("ACE_OS::thr_setcancelstate"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_setcancelstate + (new_state, old_state), + ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL) +# if defined (ACE_HAS_PTHREADS_DRAFT4) + int old; + old = pthread_setcancel (new_state); + if (old == -1) + return -1; + *old_state = old; + return 0; +# elif defined (ACE_HAS_PTHREADS_DRAFT6) + ACE_UNUSED_ARG(old_state); + ACE_OSCALL_RETURN (pthread_setintr (new_state), int, -1); +# else /* this is draft 7 or std */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setcancelstate (new_state, + old_state), + ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ +# elif defined (ACE_HAS_STHREADS) + ACE_UNUSED_ARG (new_state); + ACE_UNUSED_ARG (old_state); + ACE_NOTSUP_RETURN (-1); +# elif defined (ACE_HAS_WTHREADS) + ACE_UNUSED_ARG (new_state); + ACE_UNUSED_ARG (old_state); + ACE_NOTSUP_RETURN (-1); +# else /* Could be ACE_HAS_PTHREADS && ACE_LACKS_PTHREAD_CANCEL */ + ACE_UNUSED_ARG (new_state); + ACE_UNUSED_ARG (old_state); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PTHREADS */ +#else + ACE_UNUSED_ARG (new_state); + ACE_UNUSED_ARG (old_state); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::thr_setcanceltype (int new_type, int *old_type) +{ + ACE_OS_TRACE ("ACE_OS::thr_setcanceltype"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_setcanceltype + (new_type, old_type), + ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL) +# if defined (ACE_HAS_PTHREADS_DRAFT4) + int old; + old = pthread_setasynccancel(new_type); + if (old == -1) + return -1; + *old_type = old; + return 0; +# elif defined (ACE_HAS_PTHREADS_DRAFT6) + ACE_UNUSED_ARG(old_type); + ACE_OSCALL_RETURN (pthread_setintrtype (new_type), int, -1); +# else /* this is draft 7 or std */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setcanceltype (new_type, + old_type), + ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ +# else /* Could be ACE_HAS_PTHREADS && ACE_LACKS_PTHREAD_CANCEL */ + ACE_UNUSED_ARG (new_type); + ACE_UNUSED_ARG (old_type); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PTHREADS */ +#else + ACE_UNUSED_ARG (new_type); + ACE_UNUSED_ARG (old_type); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::thr_cancel (ACE_thread_t thr_id) +{ + ACE_OS_TRACE ("ACE_OS::thr_cancel"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_cancel (thr_id), + ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL) +# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) + ACE_OSCALL_RETURN (::pthread_cancel (thr_id), int, -1); +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_cancel (thr_id), + ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6 */ +# else /* Could be ACE_HAS_PTHREADS && ACE_LACKS_PTHREAD_CANCEL */ + ACE_UNUSED_ARG (thr_id); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PTHREADS */ +#else + ACE_UNUSED_ARG (thr_id); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::sigwait (sigset_t *set, int *sig) +{ + ACE_OS_TRACE ("ACE_OS::sigwait"); + int local_sig; + if (sig == 0) + sig = &local_sig; +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + errno = ::pace_sigwait (set, sig); + return errno == 0 ? *sig : -1; +#elif defined (ACE_HAS_THREADS) +# if (defined (__FreeBSD__) && (__FreeBSD__ < 3)) || defined (CHORUS) || defined (ACE_PSOS) || defined (__MACOSX__) + ACE_UNUSED_ARG (set); + ACE_NOTSUP_RETURN (-1); +# elif (defined (ACE_HAS_STHREADS) && !defined (_POSIX_PTHREAD_SEMANTICS)) + *sig = ::sigwait (set); + return *sig; +# elif defined (ACE_HAS_PTHREADS) + // LynxOS and Digital UNIX have their own hoops to jump through. +# if defined (__Lynx__) + // Second arg is a void **, which we don't need (the selected + // signal number is returned). + *sig = ::sigwait (set, 0); + return *sig; +# elif defined (DIGITAL_UNIX) && defined (__DECCXX_VER) + // DEC cxx (but not g++) needs this direct call to its internal + // sigwait (). This allows us to #undef sigwait, so that we can + // have ACE_OS::sigwait. cxx gets confused by ACE_OS::sigwait + // if sigwait is _not_ #undef'ed. + errno = ::_Psigwait (set, sig); + return errno == 0 ? *sig : -1; +# else /* ! __Lynx __ && ! (DIGITAL_UNIX && __DECCXX_VER) */ +# if (defined (ACE_HAS_PTHREADS_DRAFT4) || (defined (ACE_HAS_PTHREADS_DRAFT6)) && !defined(ACE_HAS_FSU_PTHREADS)) || (defined (_UNICOS) && _UNICOS == 9) +# if defined (HPUX_10) + *sig = cma_sigwait (set); +# else + *sig = ::sigwait (set); +# endif /* HPUX_10 */ + return *sig; +# elif defined(ACE_HAS_FSU_PTHREADS) + return ::sigwait (set, sig); +# else /* this is draft 7 or std */ + errno = ::sigwait (set, sig); + return errno == 0 ? *sig : -1; +# endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */ +# endif /* ! __Lynx__ && ! (DIGITAL_UNIX && __DECCXX_VER) */ +# elif defined (ACE_HAS_WTHREADS) + ACE_UNUSED_ARG (set); + ACE_NOTSUP_RETURN (-1); +# elif defined (VXWORKS) + // Second arg is a struct siginfo *, which we don't need (the + // selected signal number is returned). Third arg is timeout: 0 + // means forever. + *sig = ::sigtimedwait (set, 0, 0); + return *sig; +# endif /* __FreeBSD__ */ +#else + ACE_UNUSED_ARG (set); + ACE_UNUSED_ARG (sig); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::sigtimedwait (const sigset_t *set, + siginfo_t *info, + const ACE_Time_Value *timeout) +{ + ACE_OS_TRACE ("ACE_OS::sigtimedwait"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + timespec ts; + timespec *tsp; + if (timeout !=0) + { + ts = *timeout; + tsp = &ts; + } + else + tsp = 0; + ACE_OSCALL_RETURN (::pace_sigtimedwait (set, info, tsp), + int, -1); +#elif defined (ACE_HAS_SIGTIMEDWAIT) + timespec_t ts; + timespec_t *tsp; + + if (timeout != 0) + { + ts = *timeout; // Calls ACE_Time_Value::operator timespec_t(). + tsp = &ts; + } + else + tsp = 0; + + ACE_OSCALL_RETURN (::sigtimedwait (set, info, tsp), + int, -1); +#else + ACE_UNUSED_ARG (set); + ACE_UNUSED_ARG (info); + ACE_UNUSED_ARG (timeout); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE void +ACE_OS::thr_testcancel (void) +{ + ACE_OS_TRACE ("ACE_OS::thr_testcancel"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL) +#if defined(ACE_HAS_PTHREADS_DRAFT6) + ::pthread_testintr (); +#else /* ACE_HAS_PTHREADS_DRAFT6 */ + ::pthread_testcancel (); +#endif /* !ACE_HAS_PTHREADS_DRAFT6 */ +# elif defined (ACE_HAS_STHREADS) +# elif defined (ACE_HAS_WTHREADS) +# elif defined (VXWORKS) || defined (ACE_PSOS) +# else + // no-op: can't use ACE_NOTSUP_RETURN because there is no return value +# endif /* ACE_HAS_PTHREADS */ +#else +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thr_sigsetmask (int how, + const sigset_t *nsm, + sigset_t *osm) +{ + ACE_OS_TRACE ("ACE_OS::thr_sigsetmask"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_sigmask + (how, nsm, osm), + ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_LACKS_PTHREAD_THR_SIGSETMASK) + // DCE threads and Solaris 2.4 have no such function. + ACE_UNUSED_ARG (osm); + ACE_UNUSED_ARG (nsm); + ACE_UNUSED_ARG (how); + + ACE_NOTSUP_RETURN (-1); +# elif defined (ACE_HAS_SIGTHREADMASK) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sigthreadmask (how, nsm, osm), + ace_result_), int, -1); +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_sigsetmask (how, nsm, osm), + ace_result_), + int, -1); +# elif defined (ACE_HAS_PTHREADS) +# if defined (AIX) + ACE_OSCALL_RETURN (sigthreadmask (how, nsm, osm), int, -1); + // Draft 4 and 6 implementations will sometimes have a sigprocmask () that + // modifies the calling thread's mask only. If this is not so for your + // platform, define ACE_LACKS_PTHREAD_THR_SIGSETMASK. +# elif defined(ACE_HAS_PTHREADS_DRAFT4) || \ + defined (ACE_HAS_PTHREADS_DRAFT6) || (defined (_UNICOS) && _UNICOS == 9) + ACE_OSCALL_RETURN (::sigprocmask (how, nsm, osm), int, -1); +# elif !defined (ACE_LACKS_PTHREAD_SIGMASK) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_sigmask (how, nsm, osm), + ace_result_), int, -1); +# endif /* AIX */ + +#if 0 + /* Don't know if anyt platform actually needs this... */ + // as far as I can tell, this is now pthread_sigaction() -- jwr + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_sigaction (how, nsm, osm), + ace_result_), int, -1); +#endif /* 0 */ + +# elif defined (ACE_HAS_WTHREADS) || defined (ACE_PSOS) + ACE_UNUSED_ARG (osm); + ACE_UNUSED_ARG (nsm); + ACE_UNUSED_ARG (how); + + ACE_NOTSUP_RETURN (-1); +# elif defined (VXWORKS) + switch (how) + { + case SIG_BLOCK: + case SIG_UNBLOCK: + { + // get the old mask + *osm = ::sigsetmask (*nsm); + // create a new mask: the following assumes that sigset_t is 4 bytes, + // which it is on VxWorks 5.2, so bit operations are done simply . . . + ::sigsetmask (how == SIG_BLOCK ? (*osm |= *nsm) : (*osm &= ~*nsm)); + break; + } + case SIG_SETMASK: + *osm = ::sigsetmask (*nsm); + break; + default: + return -1; + } + + return 0; +# else /* Should not happen. */ + ACE_UNUSED_ARG (how); + ACE_UNUSED_ARG (nsm); + ACE_UNUSED_ARG (osm); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_LACKS_PTHREAD_THR_SIGSETMASK */ +#else + ACE_UNUSED_ARG (how); + ACE_UNUSED_ARG (nsm); + ACE_UNUSED_ARG (osm); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::thr_kill (ACE_thread_t thr_id, int signum) +{ + ACE_OS_TRACE ("ACE_OS::thr_kill"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_kill (thr_id, signum), + ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) +# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined(ACE_LACKS_PTHREAD_KILL) + ACE_UNUSED_ARG (signum); + ACE_UNUSED_ARG (thr_id); + ACE_NOTSUP_RETURN (-1); +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_kill (thr_id, signum), + ace_result_), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_kill (thr_id, signum), + ace_result_), + int, -1); +# elif defined (ACE_HAS_WTHREADS) || defined (ACE_PSOS) + ACE_UNUSED_ARG (signum); + ACE_UNUSED_ARG (thr_id); + + ACE_NOTSUP_RETURN (-1); +# elif defined (VXWORKS) + ACE_hthread_t tid; + ACE_OSCALL (::taskNameToId (thr_id), int, ERROR, tid); + + if (tid == ERROR) + return -1; + else + ACE_OSCALL_RETURN (::kill (tid, signum), int, -1); + +# else /* This should not happen! */ + ACE_UNUSED_ARG (thr_id); + ACE_UNUSED_ARG (signum); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_STHREADS */ +#else + ACE_UNUSED_ARG (thr_id); + ACE_UNUSED_ARG (signum); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE size_t +ACE_OS::thr_min_stack (void) +{ + ACE_OS_TRACE ("ACE_OS::thr_min_stack"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_STHREADS) +# if defined (ACE_HAS_THR_MINSTACK) + // Tandem did some weirdo mangling of STHREAD names... + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_minstack (), + ace_result_), + int, -1); +# else + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_min_stack (), + ace_result_), + int, -1); +# endif /* !ACE_HAS_THR_MINSTACK */ +# elif defined (ACE_HAS_PTHREADS) +# if defined (_SC_THREAD_STACK_MIN) + return (size_t) ACE_OS::sysconf (_SC_THREAD_STACK_MIN); +# elif defined (PTHREAD_STACK_MIN) + return PTHREAD_STACK_MIN; +# else + ACE_NOTSUP_RETURN (0); +# endif /* _SC_THREAD_STACK_MIN */ +# elif defined (ACE_HAS_WTHREADS) + ACE_NOTSUP_RETURN (0); +# elif defined (ACE_PSOS) + // there does not appear to be a way to get the + // task stack size except at task creation + ACE_NOTSUP_RETURN (0); +# elif defined (VXWORKS) + TASK_DESC taskDesc; + STATUS status; + + ACE_hthread_t tid; + ACE_OS::thr_self (tid); + +# if defined (ACE_HAS_PACE) + // pthread_min_stack is not a POSIX function. So use the thread ID from + // the pace_pthread_t structure. + ACE_OSCALL (ACE_ADAPT_RETVAL (::taskInfoGet (tid->tid, &taskDesc), + status), + STATUS, -1, status); +# else + ACE_OSCALL (ACE_ADAPT_RETVAL (::taskInfoGet (tid, &taskDesc), + status), + STATUS, -1, status); +# endif /* ACE_HAS_PACE */ + return status == OK ? taskDesc.td_stackSize : 0; +# else /* Should not happen... */ + ACE_NOTSUP_RETURN (0); +# endif /* ACE_HAS_STHREADS */ +#else + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thr_setconcurrency (int hint) +{ + ACE_OS_TRACE ("ACE_OS::thr_setconcurrency"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setconcurrency (hint), + ace_result_), + int, -1); +# elif defined (ACE_HAS_PTHREADS) + ACE_UNUSED_ARG (hint); + ACE_NOTSUP_RETURN (-1); +# elif defined (ACE_HAS_WTHREADS) + ACE_UNUSED_ARG (hint); + + ACE_NOTSUP_RETURN (-1); +# elif defined (VXWORKS) || defined (ACE_PSOS) + ACE_UNUSED_ARG (hint); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_STHREADS */ +#else + ACE_UNUSED_ARG (hint); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE int +ACE_OS::thr_setprio (ACE_hthread_t thr_id, int prio) +{ + ACE_OS_TRACE ("ACE_OS::thr_setprio"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + struct sched_param param; + int policy = 0; + int result; + ACE_OSCALL (ACE_ADAPT_RETVAL (::pace_pthread_getschedparam + (thr_id, &policy, ¶m), + result), int, -1, result); + + if (result == -1) + return result; // error in pthread_getschedparam + param.sched_priority = prio; +# if defined (ACE_WIN32) + int ace_result_ = 0; +# endif /* ACE_WIN32 */ + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_setschedparam + (thr_id, policy, ¶m), + ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) +# if (defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_SETSCHED)) + +# if defined (ACE_HAS_PTHREADS_DRAFT4) + int result; + result = ::pthread_setprio(thr_id, prio); + return (result == -1 ? -1 : 0); +# elif defined (ACE_HAS_PTHREADS_DRAFT6) + pthread_attr_t attr; + if (pthread_getschedattr (thr_id, &attr) == -1) + return -1; + if (pthread_attr_setprio (attr, prio) == -1) + return -1; + return pthread_setschedattr (thr_id, attr); +# else + struct sched_param param; + int policy = 0; + int result; + + ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_getschedparam (thr_id, &policy, ¶m), + result), // not sure if use of result here is cool, cjc + int, -1, result); + if (result == -1) + return result; // error in pthread_getschedparam + param.sched_priority = prio; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id, policy, ¶m), + result), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ +# elif defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setprio (thr_id, prio), + ace_result_), + int, -1); +# elif defined (ACE_HAS_WTHREADS) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetThreadPriority (thr_id, prio), + ace_result_), + int, -1); +# elif defined (ACE_PSOS) + u_long oldprio; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::t_setpri (thr_id, prio, &oldprio), + ace_result_), + int, -1); +# elif defined (VXWORKS) + ACE_OSCALL_RETURN (::taskPrioritySet (thr_id, prio), int, -1); +# else + // For example, platforms that support Pthreads but LACK_SETSCHED. + ACE_UNUSED_ARG (thr_id); + ACE_UNUSED_ARG (prio); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_STHREADS */ +#else + ACE_UNUSED_ARG (thr_id); + ACE_UNUSED_ARG (prio); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::thr_suspend (ACE_hthread_t target_thread) +{ + ACE_OS_TRACE ("ACE_OS::thr_suspend"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_STHREADS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_suspend (target_thread), ace_result_), int, -1); +# elif defined (ACE_HAS_PTHREADS) +# if defined (ACE_HAS_PTHREADS_UNIX98_EXT) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_suspend (target_thread), + ace_result_), + int, -1); +# else + ACE_UNUSED_ARG (target_thread); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PTHREADS_UNIX98_EXT */ +# elif defined (ACE_HAS_WTHREADS) + if (::SuspendThread (target_thread) != ACE_SYSCALL_FAILED) + return 0; + else + ACE_FAIL_RETURN (-1); + /* NOTREACHED */ +# elif defined (ACE_PSOS) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::t_suspend (target_thread), ace_result_), int, -1); +# elif defined (VXWORKS) +# if defined (ACE_HAS_PACE) + // pthread_suspend (like pthread_continue) is not an official POSIX + // function. We get this for free with ACE. So use the thread ID from + // the pace_pthread_t structure. + ACE_OSCALL_RETURN (::taskSuspend (target_thread->tid), int, -1); +# else + ACE_OSCALL_RETURN (::taskSuspend (target_thread), int, -1); +# endif /* ACE_HAS_PACE */ +# endif /* ACE_HAS_STHREADS */ +#else + ACE_UNUSED_ARG (target_thread); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +ACE_INLINE void +ACE_OS::thr_yield (void) +{ + ACE_OS_TRACE ("ACE_OS::thr_yield"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ::pace_sched_yield (); +#elif defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) +# if defined (ACE_HAS_PTHREADS_STD) + // Note - this is a POSIX.4 function - not a POSIX.1c function... + ::sched_yield (); +# elif defined (ACE_HAS_PTHREADS_DRAFT6) + ::pthread_yield (NULL); +# else /* Draft 4 and 7 */ + ::pthread_yield (); +# endif /* ACE_HAS_PTHREADS_STD */ +# elif defined (ACE_HAS_STHREADS) + ::thr_yield (); +# elif defined (ACE_HAS_WTHREADS) + ::Sleep (0); +# elif defined (VXWORKS) + // An argument of 0 to ::taskDelay doesn't appear to yield the + // current thread. + // Now, it does seem to work. The context_switch_time test + // works fine with task_delay set to 0. + ::taskDelay (0); +# endif /* ACE_HAS_STHREADS */ +#else + ; +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::priority_control (ACE_idtype_t idtype, ACE_id_t id, int cmd, void *arg) +{ + ACE_OS_TRACE ("ACE_OS::priority_control"); +#if defined (ACE_HAS_PRIOCNTL) + ACE_OSCALL_RETURN (priocntl (idtype, id, cmd, ACE_static_cast (caddr_t, arg)), + int, -1); +#else /* ! ACE_HAS_PRIOCNTL*/ + ACE_UNUSED_ARG (idtype); + ACE_UNUSED_ARG (id); + ACE_UNUSED_ARG (cmd); + ACE_UNUSED_ARG (arg); + ACE_NOTSUP_RETURN (-1); +#endif /* ! ACE_HAS_PRIOCNTL*/ +} + +ACE_INLINE void +ACE_OS::rewind (FILE *fp) +{ +#if defined (ACE_HAS_PACE) + ::pace_rewind (fp); +#elif !defined (ACE_HAS_WINCE) + ACE_OS_TRACE ("ACE_OS::rewind"); + ::rewind (fp); +#else + // In WinCE, "FILE *" is actually a HANDLE. + ::SetFilePointer (fp, 0L, 0L, FILE_BEGIN); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE ssize_t +ACE_OS::readv (ACE_HANDLE handle, + iovec *iov, + int iovlen) +{ + ACE_OS_TRACE ("ACE_OS::readv"); +#if defined (ACE_LACKS_READV) + ACE_OSCALL_RETURN (ACE_OS::readv_emulation (handle, iov, iovlen), + ssize_t, + -1); +#else /* ACE_LACKS_READV */ + ACE_OSCALL_RETURN (::readv (handle, iov, iovlen), ssize_t, -1); +#endif /* ACE_LACKS_READV */ +} + +ACE_INLINE ssize_t +ACE_OS::writev (ACE_HANDLE handle, + const iovec *iov, + int iovcnt) +{ + ACE_OS_TRACE ("ACE_OS::writev"); +#if defined (ACE_LACKS_WRITEV) + ACE_OSCALL_RETURN (ACE_OS::writev_emulation (handle, + (ACE_WRITEV_TYPE *) iov, + iovcnt), int, -1); +#else /* ACE_LACKS_WRITEV */ + ACE_OSCALL_RETURN (::writev (handle, + (ACE_WRITEV_TYPE *) iov, + iovcnt), int, -1); +#endif /* ACE_LACKS_WRITEV */ +} + +ACE_INLINE ssize_t +ACE_OS::recvv (ACE_HANDLE handle, + iovec *buffers, + int n) +{ +#if defined (ACE_HAS_WINSOCK2) + + DWORD bytes_received = 0; + int result = 1; + + // Winsock 2 has WSARecv and can do this directly, but Winsock 1 needs + // to do the recvs piece-by-piece. + +# if (ACE_HAS_WINSOCK2 != 0) + DWORD flags = 0; + result = ::WSARecv ((SOCKET) handle, + (WSABUF *) buffers, + n, + &bytes_received, + &flags, + 0, + 0); +# else + int i, chunklen; + char *chunkp = 0; + + // Step through the buffers requested by caller; for each one, cycle + // through reads until it's filled or an error occurs. + for (i = 0; i < n && result > 0; i++) + { + chunkp = buffers[i].iov_base; // Point to part of chunk being read + chunklen = buffers[i].iov_len; // Track how much to read to chunk + while (chunklen > 0 && result > 0) + { + result = ::recv ((SOCKET) handle, chunkp, chunklen, 0); + if (result > 0) + { + chunkp += result; + chunklen -= result; + bytes_received += result; + } + } + } +# endif /* ACE_HAS_WINSOCK2 != 0 */ + + if (result == SOCKET_ERROR) + { + ACE_OS::set_errno_to_wsa_last_error (); + return -1; + } + else + return (ssize_t) bytes_received; +#else + return ACE_OS::readv (handle, buffers, n); +#endif /* ACE_HAS_WINSOCK2 */ +} + +ACE_INLINE ssize_t +ACE_OS::sendv (ACE_HANDLE handle, + const iovec *buffers, + int n) +{ +#if defined (ACE_HAS_WINSOCK2) + DWORD bytes_sent = 0; + int result = 0; + + // Winsock 2 has WSASend and can do this directly, but Winsock 1 + // needs to do the sends one-by-one. +# if (ACE_HAS_WINSOCK2 != 0) + result = ::WSASend ((SOCKET) handle, + (WSABUF *) buffers, + n, + &bytes_sent, + 0, + 0, + 0); +# else + int i; + for (i = 0; i < n && result != SOCKET_ERROR; i++) + { + result = ::send ((SOCKET) handle, + buffers[i].iov_base, + buffers[i].iov_len, + 0); + bytes_sent += buffers[i].iov_len; // Gets ignored on error anyway + } +# endif /* ACE_HAS_WINSOCK2 != 0 */ + + if (result == SOCKET_ERROR) + { + ACE_OS::set_errno_to_wsa_last_error (); + return -1; + } + else + return (ssize_t) bytes_sent; + +#else + return ACE_OS::writev (handle, buffers, n); +#endif /* ACE_HAS_WINSOCK2 */ +} + +ACE_INLINE int +ACE_OS::poll (struct pollfd *pollfds, u_long len, const ACE_Time_Value *timeout) +{ + ACE_OS_TRACE ("ACE_OS::poll"); +#if defined (ACE_HAS_POLL) + int to = timeout == 0 ? -1 : int (timeout->msec ()); + ACE_OSCALL_RETURN (::poll (pollfds, len, to), int, -1); +#else + ACE_UNUSED_ARG (timeout); + ACE_UNUSED_ARG (len); + ACE_UNUSED_ARG (pollfds); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_POLL */ +} + +ACE_INLINE int +ACE_OS::poll (struct pollfd *pollfds, u_long len, const ACE_Time_Value &timeout) +{ + ACE_OS_TRACE ("ACE_OS::poll"); +#if defined (ACE_HAS_POLL) + ACE_OSCALL_RETURN (::poll (pollfds, len, int (timeout.msec ())), int, -1); +#else + ACE_UNUSED_ARG (timeout); + ACE_UNUSED_ARG (len); + ACE_UNUSED_ARG (pollfds); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_POLL */ +} + +ACE_INLINE char * +ACE_OS::compile (const char *instring, char *expbuf, char *endbuf) +{ + ACE_OS_TRACE ("ACE_OS::compile"); +#if defined (ACE_HAS_REGEX) + ACE_OSCALL_RETURN (::compile (instring, expbuf, endbuf), char *, 0); +#else + ACE_UNUSED_ARG (instring); + ACE_UNUSED_ARG (expbuf); + ACE_UNUSED_ARG (endbuf); + + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_REGEX */ +} + +ACE_INLINE long +ACE_OS::filesize (const ACE_TCHAR *filename) +{ + ACE_OS_TRACE ("ACE_OS::filesize"); + + ACE_HANDLE h = ACE_OS::open (filename, O_RDONLY); + if (h != ACE_INVALID_HANDLE) + { + long size = ACE_OS::filesize (h); + ACE_OS::close (h); + return size; + } + else + return -1; +} + +ACE_INLINE int +ACE_OS::closesocket (ACE_HANDLE handle) +{ + ACE_OS_TRACE ("ACE_OS::closesocket"); +#if defined (ACE_WIN32) + ACE_SOCKCALL_RETURN (::closesocket ((SOCKET) handle), int, -1); +#elif defined (ACE_PSOS_DIAB_PPC) + ACE_OSCALL_RETURN (::pna_close (handle), int, -1); +#else + ACE_OSCALL_RETURN (::close (handle), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::access (const char *path, int amode) +{ + ACE_OS_TRACE ("ACE_OS::access"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_access (path, amode), int, -1); +#elif defined (ACE_LACKS_ACCESS) + ACE_UNUSED_ARG (path); + ACE_UNUSED_ARG (amode); + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_WINCE) + // @@ WINCE: There should be a Win32 API that can do this. + // Hard coded read access here. + FILE* handle = ACE_OS::fopen (path, ACE_LIB_TEXT ("r")); + ACE_UNUSED_ARG (amode); + + ACE_OS::fclose (handle); + return (handle == ACE_INVALID_HANDLE ? -1 : 0); +#else + ACE_OSCALL_RETURN (::access (path, amode), int, -1); +#endif /* ACE_HAS_PACE */ +} + + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE int +ACE_OS::access (const wchar_t *path, int amode) +{ +#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) + ACE_OSCALL_RETURN (::_waccess (path, amode), int, -1); +#else /* ACE_WIN32 && !ACE_HAS_WINCE */ + return ACE_OS::access (ACE_Wide_To_Ascii (path).char_rep (), amode); +#endif /* ACE_WIN32 && !ACE_HAS_WINCE */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE ACE_HANDLE +ACE_OS::creat (const ACE_TCHAR *filename, mode_t mode) +{ + ACE_OS_TRACE ("ACE_OS::creat"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_creat (filename, mode), + ACE_HANDLE, ACE_INVALID_HANDLE); +#elif defined (ACE_WIN32) + return ACE_OS::open (filename, mode); +#elif defined(ACE_PSOS) + ACE_OSCALL_RETURN(::create_f((char *)filename, 1024, + S_IRUSR | S_IWUSR | S_IXUSR), + ACE_HANDLE, ACE_INVALID_HANDLE); +#elif defined(ACE_PSOS_TM) + ACE_UNUSED_ARG (filename); + ACE_UNUSED_ARG (mode); + ACE_NOTSUP_RETURN (-1); +#elif defined(ACE_PSOS) + ACE_UNUSED_ARG (filename); + ACE_UNUSED_ARG (mode); + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::creat (filename, mode), + ACE_HANDLE, ACE_INVALID_HANDLE); +#endif /* ACE_HAS_PACE */ +} + +#if !defined (ACE_WIN32) && !defined (VXWORKS) && !defined (CHORUS) && !defined (ACE_PSOS) +// Don't inline on those platforms because this function contains +// string literals, and some compilers, e.g., g++, don't handle those +// efficiently in unused inline functions. +ACE_INLINE int +ACE_OS::uname (ACE_utsname *name) +{ + ACE_OS_TRACE ("ACE_OS::uname"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_uname (name), int, -1); +#else + ACE_OSCALL_RETURN (::uname (name), int, -1); +#endif /* ACE_HAS_PACE */ +} +#endif /* ! ACE_WIN32 && ! VXWORKS && ! CHORUS */ + +ACE_INLINE int +ACE_OS::hostname (char name[], size_t maxnamelen) +{ + ACE_OS_TRACE ("ACE_OS::hostname"); +#if defined (ACE_HAS_PHARLAP) + // PharLap only can do net stuff with the RT version. +# if defined (ACE_HAS_PHARLAP_RT) + // @@This is not at all reliable... requires ethernet and BOOTP to be used. + // A more reliable way is to go thru the devices w/ EtsTCPGetDeviceCfg until + // a legit IP address is found, then get its name w/ gethostbyaddr. + ACE_SOCKCALL_RETURN (gethostname (name, maxnamelen), int, SOCKET_ERROR); +# else + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (maxnamelen); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_PHARLAP_RT */ +#elif defined (VXWORKS) || defined (ACE_HAS_WINCE) + ACE_OSCALL_RETURN (::gethostname (name, maxnamelen), int, -1); +#elif defined (ACE_WIN32) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::GetComputerNameA (name, + LPDWORD (&maxnamelen)), + ace_result_), int, -1); +#elif defined (CHORUS) + if (::gethostname (name, maxnamelen) == -1) + return -1; + else + { + if (ACE_OS::strlen (name) == 0) + { + // Try the HOST environment variable. + ACE_TCHAR *const hostenv = ::getenv (ACE_LIB_TEXT ("HOST")); + if (hostenv) + ACE_OS::strsncpy (name, hostenv, maxnamelen); + } + return 0; + } +#else /* ACE_HAS_PHARLAP */ + ACE_utsname host_info; + + if (ACE_OS::uname (&host_info) == -1) + return -1; + else + { + ACE_OS::strsncpy (name, host_info.nodename, maxnamelen); + return 0; + } +#endif /* ACE_HAS_PHARLAP */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE int +ACE_OS::hostname (wchar_t name[], size_t maxnamelen) +{ +#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (GetComputerNameW (name, + LPDWORD (&maxnamelen)), + ace_result_), int, -1); +#else /* ACE_WIN32 && !ACE_HAS_WINCE */ + // Emulate using the char version + char *char_name = 0; + int result = 0; + + ACE_NEW_RETURN (char_name, char[maxnamelen], -1); + + result = ACE_OS::hostname(char_name, maxnamelen); + ACE_OS::strcpy (name, ACE_Ascii_To_Wide (char_name).wchar_rep ()); + + delete [] char_name; + return result; +#endif /* ACE_WIN32 && !ACE_HAS_WINCE */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE int +ACE_OS::msgctl (int msqid, int cmd, struct msqid_ds *val) +{ + ACE_OS_TRACE ("ACE_OS::msgctl"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::msgctl (msqid, cmd, val), int, -1); +#else + ACE_UNUSED_ARG (msqid); + ACE_UNUSED_ARG (cmd); + ACE_UNUSED_ARG (val); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE int +ACE_OS::msgget (key_t key, int msgflg) +{ + ACE_OS_TRACE ("ACE_OS::msgget"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::msgget (key, msgflg), int, -1); +#else + ACE_UNUSED_ARG (key); + ACE_UNUSED_ARG (msgflg); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE int +ACE_OS::msgrcv (int int_id, void *buf, size_t len, + long type, int flags) +{ + ACE_OS_TRACE ("ACE_OS::msgrcv"); +#if defined (ACE_HAS_SYSV_IPC) +# if defined (ACE_LACKS_POSIX_PROTOTYPES) || defined (ACE_LACKS_SOME_POSIX_PROTOTYPES) + ACE_OSCALL_RETURN (::msgrcv (int_id, (msgbuf *) buf, len, type, flags), + int, -1); +# else + ACE_OSCALL_RETURN (::msgrcv (int_id, buf, len, type, flags), + int, -1); +# endif /* ACE_LACKS_POSIX_PROTOTYPES */ +#else + ACE_UNUSED_ARG (int_id); + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (len); + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (flags); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE int +ACE_OS::msgsnd (int int_id, const void *buf, size_t len, int flags) +{ + ACE_OS_TRACE ("ACE_OS::msgsnd"); +#if defined (ACE_HAS_SYSV_IPC) +# if defined (ACE_HAS_NONCONST_MSGSND) + ACE_OSCALL_RETURN (::msgsnd (int_id, (void *) buf, len, flags), int, -1); +# elif defined (ACE_LACKS_POSIX_PROTOTYPES) || defined (ACE_LACKS_SOME_POSIX_PROTOTYPES) + ACE_OSCALL_RETURN (::msgsnd (int_id, (msgbuf *) buf, len, flags), int, -1); +# else + ACE_OSCALL_RETURN (::msgsnd (int_id, buf, len, flags), int, -1); +# endif /* ACE_LACKS_POSIX_PROTOTYPES || ACE_HAS_NONCONST_MSGSND */ +#else + ACE_UNUSED_ARG (int_id); + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (len); + ACE_UNUSED_ARG (flags); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE u_int +ACE_OS::alarm (u_int secs) +{ + ACE_OS_TRACE ("ACE_OS::alarm"); +#if defined (ACE_HAS_PACE) + return ::pace_alarm (secs); +#elif defined (ACE_WIN32) || defined (VXWORKS) || defined (CHORUS) || defined (ACE_PSOS) + ACE_UNUSED_ARG (secs); + + ACE_NOTSUP_RETURN (0); +#else + return ::alarm (secs); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE u_int +ACE_OS::ualarm (u_int usecs, u_int interval) +{ + ACE_OS_TRACE ("ACE_OS::ualarm"); + +#if defined (ACE_HAS_UALARM) + return ::ualarm (usecs, interval); +#elif !defined (ACE_LACKS_UNIX_SIGNALS) + ACE_UNUSED_ARG (interval); + return ::alarm (usecs * ACE_ONE_SECOND_IN_USECS); +#else + ACE_UNUSED_ARG (usecs); + ACE_UNUSED_ARG (interval); + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_UALARM */ +} + +ACE_INLINE u_int +ACE_OS::ualarm (const ACE_Time_Value &tv, + const ACE_Time_Value &tv_interval) +{ + ACE_OS_TRACE ("ACE_OS::ualarm"); + +#if defined (ACE_HAS_UALARM) + u_int usecs = (tv.sec () * ACE_ONE_SECOND_IN_USECS) + tv.usec (); + u_int interval = (tv_interval.sec () * ACE_ONE_SECOND_IN_USECS) + tv_interval.usec (); + return ::ualarm (usecs, interval); +#elif !defined (ACE_LACKS_UNIX_SIGNALS) + ACE_UNUSED_ARG (tv_interval); + return ::alarm (tv.sec ()); +#else + ACE_UNUSED_ARG (tv_interval); + ACE_UNUSED_ARG (tv); + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_UALARM */ +} + +ACE_INLINE int +ACE_OS::dlclose (ACE_SHLIB_HANDLE handle) +{ + ACE_OS_TRACE ("ACE_OS::dlclose"); +#if defined (ACE_HAS_SVR4_DYNAMIC_LINKING) + +# if !defined (ACE_HAS_AUTOMATIC_INIT_FINI) + // SunOS4 does not automatically call _fini()! + void *ptr; + + ACE_OSCALL (::dlsym (handle, ACE_LIB_TEXT ("_fini")), void *, 0, ptr); + + if (ptr != 0) + (*((int (*)(void)) ptr)) (); // Call _fini hook explicitly. +# endif /* ACE_HAS_AUTOMATIC_INIT_FINI */ +#if defined (_M_UNIX) + ACE_OSCALL_RETURN (::_dlclose (handle), int, -1); +#else /* _MUNIX */ + ACE_OSCALL_RETURN (::dlclose (handle), int, -1); +#endif /* _M_UNIX */ +#elif defined (ACE_WIN32) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::FreeLibrary (handle), ace_result_), int, -1); +#elif defined (__hpux) + // HP-UX 10.x and 32-bit 11.00 do not pay attention to the ref count + // when unloading a dynamic lib. So, if the ref count is more than + // 1, do not unload the lib. This will cause a library loaded more + // than once to not be unloaded until the process runs down, but + // that's life. It's better than unloading a library that's in use. + // So far as I know, there's no way to decrement the refcnt that the + // kernel is looking at - the shl_descriptor is a copy of what the + // kernel has, not the actual struct. On 64-bit HP-UX using dlopen, + // this problem has been fixed. + struct shl_descriptor desc; + if (shl_gethandle_r (handle, &desc) == -1) + return -1; + if (desc.ref_count > 1) + return 0; +# if defined(__GNUC__) || __cplusplus >= 199707L + ACE_OSCALL_RETURN (::shl_unload (handle), int, -1); +# else + ACE_OSCALL_RETURN (::cxxshl_unload (handle), int, -1); +# endif /* aC++ vs. Hp C++ */ +#else + ACE_UNUSED_ARG (handle); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */ +} + +ACE_INLINE ACE_TCHAR * +ACE_OS::dlerror (void) +{ + ACE_OS_TRACE ("ACE_OS::dlerror"); +# if defined (ACE_HAS_SVR4_DYNAMIC_LINKING) +#if defined(_M_UNIX) + ACE_OSCALL_RETURN ((char *)::_dlerror (), char *, 0); +#else /* _M_UNIX */ + ACE_OSCALL_RETURN ((char *)::dlerror (), char *, 0); +#endif /* _M_UNIX */ +# elif defined (__hpux) + ACE_OSCALL_RETURN (::strerror(errno), char *, 0); +# elif defined (ACE_WIN32) + static ACE_TCHAR buf[128]; +# if defined (ACE_HAS_PHARLAP) + ACE_OS::sprintf (buf, "error code %d", GetLastError()); +# else + ACE_TEXT_FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + ::GetLastError (), + 0, + buf, + sizeof buf / sizeof buf[0], + NULL); +# endif /* ACE_HAS_PHARLAP */ + return buf; +# else + ACE_NOTSUP_RETURN (0); +# endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */ +} + +ACE_INLINE ACE_SHLIB_HANDLE +ACE_OS::dlopen (const ACE_TCHAR *fname, + int mode) +{ + ACE_OS_TRACE ("ACE_OS::dlopen"); + + // Get the correct OS type. + ACE_DL_TYPE filename = ACE_const_cast (ACE_DL_TYPE, fname); + +# if defined (ACE_HAS_SVR4_DYNAMIC_LINKING) + void *handle; +# if defined (ACE_HAS_SGIDLADD) + ACE_OSCALL (::sgidladd (filename, mode), void *, 0, handle); +# elif defined (_M_UNIX) + ACE_OSCALL (::_dlopen (filename, mode), void *, 0, handle); +# else + ACE_OSCALL (::dlopen (filename, mode), void *, 0, handle); +# endif /* ACE_HAS_SGIDLADD */ +# if !defined (ACE_HAS_AUTOMATIC_INIT_FINI) + if (handle != 0) + { + void *ptr; + // Some systems (e.g., SunOS4) do not automatically call _init(), so + // we'll have to call it manually. + + ACE_OSCALL (::dlsym (handle, ACE_LIB_TEXT ("_init")), void *, 0, ptr); + + if (ptr != 0 && (*((int (*)(void)) ptr)) () == -1) // Call _init hook explicitly. + { + // Close down the handle to prevent leaks. + ::dlclose (handle); + return 0; + } + } +# endif /* ACE_HAS_AUTOMATIC_INIT_FINI */ + return handle; +# elif defined (ACE_WIN32) + ACE_UNUSED_ARG (mode); + + ACE_WIN32CALL_RETURN (ACE_TEXT_LoadLibrary (filename), ACE_SHLIB_HANDLE, 0); +# elif defined (__hpux) + +# if defined(__GNUC__) || __cplusplus >= 199707L + ACE_OSCALL_RETURN (::shl_load(filename, mode, 0L), ACE_SHLIB_HANDLE, 0); +# else + ACE_OSCALL_RETURN (::cxxshl_load(filename, mode, 0L), ACE_SHLIB_HANDLE, 0); +# endif /* aC++ vs. Hp C++ */ + +# else + ACE_UNUSED_ARG (filename); + ACE_UNUSED_ARG (mode); + ACE_NOTSUP_RETURN (0); +# endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */ +} + +ACE_INLINE void * +ACE_OS::dlsym (ACE_SHLIB_HANDLE handle, + const ACE_TCHAR *sname) +{ + ACE_OS_TRACE ("ACE_OS::dlsym"); + + // Get the correct OS type. +#if defined (ACE_HAS_WINCE) + const wchar_t *symbolname = sname; +#elif defined (ACE_HAS_CHARPTR_DL) + char *symbolname = ACE_const_cast (char *, sname); +#elif !defined (ACE_WIN32) || !defined (ACE_USES_WCHAR) + const char *symbolname = sname; +#endif /* ACE_HAS_CHARPTR_DL */ + +# if defined (ACE_HAS_SVR4_DYNAMIC_LINKING) + +# if defined (ACE_LACKS_POSIX_PROTOTYPES) + ACE_OSCALL_RETURN (::dlsym (handle, symbolname), void *, 0); +# elif defined (ACE_USES_ASM_SYMBOL_IN_DLSYM) + int l = ACE_OS::strlen (symbolname) + 2; + char *asm_symbolname = 0; + ACE_NEW_RETURN (asm_symbolname, char[l], 0); + ACE_OS::strcpy (asm_symbolname, "_") ; + ACE_OS::strcpy (asm_symbolname + 1, symbolname) ; + void *ace_result; + ACE_OSCALL (::dlsym (handle, asm_symbolname), void *, 0, ace_result); + delete [] asm_symbolname; + return ace_result; +# elif defined (_M_UNIX) + ACE_OSCALL_RETURN (::_dlsym (handle, symbolname), void *, 0); +# else + ACE_OSCALL_RETURN (::dlsym (handle, symbolname), void *, 0); +# endif /* ACE_LACKS_POSIX_PROTOTYPES */ + +# elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR) && !defined (ACE_HAS_WINCE) + + ACE_WIN32CALL_RETURN (::GetProcAddress (handle, ACE_TEXT_ALWAYS_CHAR (sname)), void *, 0); + +# elif defined (ACE_WIN32) + + ACE_WIN32CALL_RETURN (::GetProcAddress (handle, symbolname), void *, 0); + +# elif defined (__hpux) + + void *value; + int status; + shl_t _handle = handle; + ACE_OSCALL (::shl_findsym(&_handle, symbolname, TYPE_UNDEFINED, &value), int, -1, status); + return status == 0 ? value : NULL; + +# else + + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (symbolname); + ACE_NOTSUP_RETURN (0); + +# endif /* ACE_HAS_SVR4_DYNAMIC_LINKING */ +} + +ACE_INLINE int +ACE_OS::step (const char *str, char *expbuf) +{ + ACE_OS_TRACE ("ACE_OS::step"); +#if defined (ACE_HAS_REGEX) + ACE_OSCALL_RETURN (::step (str, expbuf), int, -1); +#else + ACE_UNUSED_ARG (str); + ACE_UNUSED_ARG (expbuf); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_REGEX */ +} + +ACE_INLINE long +ACE_OS::sysinfo (int cmd, char *buf, long count) +{ + ACE_OS_TRACE ("ACE_OS::sysinfo"); +#if defined (ACE_HAS_SYSINFO) + ACE_OSCALL_RETURN (::sysinfo (cmd, buf, count), long, -1); +#else + ACE_UNUSED_ARG (cmd); + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (count); + + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_SYSINFO */ +} + +ACE_INLINE ssize_t +ACE_OS::write (ACE_HANDLE handle, const void *buf, size_t nbyte) +{ + ACE_OS_TRACE ("ACE_OS::write"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_write (handle, buf, nbyte), ssize_t, -1); +#elif defined (ACE_WIN32) + DWORD bytes_written; // This is set to 0 byte WriteFile. + + if (::WriteFile (handle, buf, nbyte, &bytes_written, 0)) + return (ssize_t) bytes_written; + else + ACE_FAIL_RETURN (-1); +#elif defined (ACE_PSOS) +# if defined (ACE_PSOS_LACKS_PHILE) + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (nbyte); + ACE_NOTSUP_RETURN (-1); +# else + if(::write_f (handle, (void *) buf, nbyte) == 0) + return (ssize_t) nbyte; + else + return -1; +# endif /* defined (ACE_PSOS_LACKS_PHILE) */ +#else +# if defined (ACE_LACKS_POSIX_PROTOTYPES) + ACE_OSCALL_RETURN (::write (handle, (const char *) buf, nbyte), ssize_t, -1); +# elif defined (ACE_PSOS) + ACE_OSCALL_RETURN (::write_f(handle, (void *) buf, nbyte), ssize_t, -1); +# elif defined (ACE_HAS_CHARPTR_SOCKOPT) + ACE_OSCALL_RETURN (::write (handle, (char *) buf, nbyte), ssize_t, -1); +# else + ACE_OSCALL_RETURN (::write (handle, buf, nbyte), ssize_t, -1); +# endif /* ACE_LACKS_POSIX_PROTOTYPES */ +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE ssize_t +ACE_OS::write (ACE_HANDLE handle, const void *buf, size_t nbyte, + ACE_OVERLAPPED *overlapped) +{ + ACE_OS_TRACE ("ACE_OS::write"); + overlapped = overlapped; +#if defined (ACE_WIN32) + DWORD bytes_written; // This is set to 0 byte WriteFile. + + if (::WriteFile (handle, buf, nbyte, &bytes_written, overlapped)) + return (ssize_t) bytes_written; + else + return -1; +#else + return ACE_OS::write (handle, buf, nbyte); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE ssize_t +ACE_OS::read (ACE_HANDLE handle, void *buf, size_t len) +{ + ACE_OS_TRACE ("ACE_OS::read"); +#if defined (ACE_HAS_PACE) + int result; + ACE_OSCALL (::pace_read (handle, buf, len), ssize_t, -1, result); + if (result == -1 && errno == EAGAIN) + errno = EWOULDBLOCK; + return result; +#elif defined (ACE_WIN32) + DWORD ok_len; + if (::ReadFile (handle, buf, len, &ok_len, 0)) + return (ssize_t) ok_len; + else + ACE_FAIL_RETURN (-1); +#elif defined (ACE_PSOS) +# if defined (ACE_PSOS_LACKS_PHILE) + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (len); + ACE_NOTSUP_RETURN (-1); +# else + u_long count; + u_long result = ::read_f (handle, buf, len, &count); + if (result != 0) + return ACE_static_cast (ssize_t, -1); + else + return ACE_static_cast (ssize_t, count == len ? count : 0); +# endif /* defined (ACE_PSOS_LACKS_PHILE */ +#else + + int result; + +# if defined (ACE_LACKS_POSIX_PROTOTYPES) || defined (ACE_HAS_CHARPTR_SOCKOPT) + ACE_OSCALL (::read (handle, (char *) buf, len), ssize_t, -1, result); +# else + ACE_OSCALL (::read (handle, buf, len), ssize_t, -1, result); +# endif /* ACE_LACKS_POSIX_PROTOTYPES */ + if (result == -1 && errno == EAGAIN) + errno = EWOULDBLOCK; + return result; +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE ssize_t +ACE_OS::read (ACE_HANDLE handle, void *buf, size_t len, + ACE_OVERLAPPED *overlapped) +{ + ACE_OS_TRACE ("ACE_OS::read"); + overlapped = overlapped; +#if defined (ACE_WIN32) + DWORD ok_len; + return ::ReadFile (handle, buf, len, &ok_len, overlapped) ? (ssize_t) ok_len : -1; +#else + return ACE_OS::read (handle, buf, len); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::readlink (const char *path, char *buf, size_t bufsiz) +{ + ACE_OS_TRACE ("ACE_OS::readlink"); +# if defined (ACE_LACKS_READLINK) || \ + defined (ACE_HAS_WINCE) || defined (ACE_WIN32) + ACE_UNUSED_ARG (path); + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (bufsiz); + ACE_NOTSUP_RETURN (-1); +# else +# if !defined(ACE_HAS_NONCONST_READLINK) + ACE_OSCALL_RETURN (::readlink (path, buf, bufsiz), int, -1); +# else + ACE_OSCALL_RETURN (::readlink ((char *)path, buf, bufsiz), int, -1); +# endif +# endif /* ACE_LACKS_READLINK */ +} + +ACE_INLINE int +ACE_OS::getmsg (ACE_HANDLE handle, + struct strbuf *ctl, + struct strbuf *data, + int *flags) +{ + ACE_OS_TRACE ("ACE_OS::getmsg"); +#if defined (ACE_HAS_STREAM_PIPES) + ACE_OSCALL_RETURN (::getmsg (handle, ctl, data, flags), int, -1); +#else + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (ctl); + ACE_UNUSED_ARG (data); + ACE_UNUSED_ARG (flags); + + // I'm not sure how to implement this correctly. + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +ACE_INLINE int +ACE_OS::getpmsg (ACE_HANDLE handle, + struct strbuf *ctl, + struct strbuf *data, + int *band, + int *flags) +{ + ACE_OS_TRACE ("ACE_OS::getpmsg"); +#if defined (ACE_HAS_STREAM_PIPES) + ACE_OSCALL_RETURN (::getpmsg (handle, ctl, data, band, flags), int, -1); +#else + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (ctl); + ACE_UNUSED_ARG (data); + ACE_UNUSED_ARG (band); + ACE_UNUSED_ARG (flags); + + // I'm not sure how to implement this correctly. + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +ACE_INLINE int +ACE_OS::getrusage (int who, struct rusage *ru) +{ + ACE_OS_TRACE ("ACE_OS::getrusage"); + +#if defined (ACE_HAS_SYSCALL_GETRUSAGE) + // This nonsense is necessary for HP/UX... + ACE_OSCALL_RETURN (::syscall (SYS_GETRUSAGE, who, ru), int, -1); +#elif defined (ACE_HAS_GETRUSAGE) +# if defined (ACE_WIN32) + ACE_UNUSED_ARG (who); + + FILETIME dummy_1; + FILETIME dummy_2; + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::GetProcessTimes (::GetCurrentProcess(), + &dummy_1, // start + &dummy_2, // exited + &ru->ru_stime, + &ru->ru_utime), + ace_result_), + int, -1); +# else +# if defined (ACE_HAS_RUSAGE_WHO_ENUM) + ACE_OSCALL_RETURN (::getrusage ((ACE_HAS_RUSAGE_WHO_ENUM) who, ru), int, -1); +# else + ACE_OSCALL_RETURN (::getrusage (who, ru), int, -1); +# endif /* ACE_HAS_RUSAGE_WHO_ENUM */ +# endif /* ACE_WIN32 */ +#else + who = who; + ru = ru; + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSCALL_GETRUSAGE */ +} + +ACE_INLINE int +ACE_OS::isastream (ACE_HANDLE handle) +{ + ACE_OS_TRACE ("ACE_OS::isastream"); +#if defined (ACE_HAS_STREAM_PIPES) + ACE_OSCALL_RETURN (::isastream (handle), int, -1); +#else + ACE_UNUSED_ARG (handle); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +// Implements simple read/write control for pages. Affects a page if +// part of the page is referenced. Currently PROT_READ, PROT_WRITE, +// and PROT_RDWR has been mapped in OS.h. This needn't have anything +// to do with a mmap region. + +ACE_INLINE int +ACE_OS::mprotect (void *addr, size_t len, int prot) +{ + ACE_OS_TRACE ("ACE_OS::mprotect"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_mprotect (addr, len, prot), int, -1); +#elif defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP) + DWORD dummy; // Sigh! + return ::VirtualProtect(addr, len, prot, &dummy) ? 0 : -1; +#elif !defined (ACE_LACKS_MPROTECT) + ACE_OSCALL_RETURN (::mprotect ((ACE_MMAP_TYPE) addr, len, prot), int, -1); +#else + ACE_UNUSED_ARG (addr); + ACE_UNUSED_ARG (len); + ACE_UNUSED_ARG (prot); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::msync (void *addr, size_t len, int sync) +{ + ACE_OS_TRACE ("ACE_OS::msync"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_msync (addr, len, sync), int, -1); +#elif defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP) + ACE_UNUSED_ARG (sync); + + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::FlushViewOfFile (addr, len), ace_result_), int, -1); +#elif !defined (ACE_LACKS_MSYNC) +# if !defined (ACE_HAS_BROKEN_NETBSD_MSYNC) + ACE_OSCALL_RETURN (::msync ((ACE_MMAP_TYPE) addr, len, sync), int, -1); +# else + ACE_OSCALL_RETURN (::msync ((ACE_MMAP_TYPE) addr, len), int, -1); + ACE_UNUSED_ARG (sync); +# endif /* ACE_HAS_BROKEN_NETBSD_MSYNC */ +#else + ACE_UNUSED_ARG (addr); + ACE_UNUSED_ARG (len); + ACE_UNUSED_ARG (sync); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::munmap (void *addr, size_t len) +{ + ACE_OS_TRACE ("ACE_OS::munmap"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_munmap (addr, len), int, -1); +#elif defined (ACE_WIN32) + ACE_UNUSED_ARG (len); + + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::UnmapViewOfFile (addr), ace_result_), int, -1); +#elif !defined (ACE_LACKS_MMAP) + ACE_OSCALL_RETURN (::munmap ((ACE_MMAP_TYPE) addr, len), int, -1); +#else + ACE_UNUSED_ARG (addr); + ACE_UNUSED_ARG (len); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::madvise (caddr_t addr, size_t len, int advice) +{ + ACE_OS_TRACE ("ACE_OS::madvise"); +#if defined (ACE_WIN32) + ACE_UNUSED_ARG (addr); + ACE_UNUSED_ARG (len); + ACE_UNUSED_ARG (advice); + + ACE_NOTSUP_RETURN (-1); +#elif !defined (ACE_LACKS_MADVISE) + ACE_OSCALL_RETURN (::madvise (addr, len, advice), int, -1); +#else + ACE_UNUSED_ARG (addr); + ACE_UNUSED_ARG (len); + ACE_UNUSED_ARG (advice); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::putmsg (ACE_HANDLE handle, const struct strbuf *ctl, + const struct strbuf *data, int flags) +{ + ACE_OS_TRACE ("ACE_OS::putmsg"); +#if defined (ACE_HAS_STREAM_PIPES) + ACE_OSCALL_RETURN (::putmsg (handle, + (ACE_STRBUF_TYPE) ctl, + (ACE_STRBUF_TYPE) data, + flags), int, -1); +#else + ACE_UNUSED_ARG (flags); + if (ctl == 0 && data == 0) + { + errno = EINVAL; + return 0; + } + // Handle the two easy cases. + else if (ctl != 0) + return ACE_OS::write (handle, ctl->buf, ctl->len); + else if (data != 0) + return ACE_OS::write (handle, data->buf, data->len); + else + { + // This is the hard case. + char *buf; + ACE_NEW_RETURN (buf, char [ctl->len + data->len], -1); + ACE_OS::memcpy (buf, ctl->buf, ctl->len); + ACE_OS::memcpy (buf + ctl->len, data->buf, data->len); + int result = ACE_OS::write (handle, buf, ctl->len + data->len); + delete [] buf; + return result; + } +#endif /* ACE_HAS_STREAM_PIPES */ +} + +ACE_INLINE int +ACE_OS::putpmsg (ACE_HANDLE handle, + const struct strbuf *ctl, + const struct strbuf *data, + int band, + int flags) +{ + ACE_OS_TRACE ("ACE_OS::putpmsg"); +#if defined (ACE_HAS_STREAM_PIPES) + ACE_OSCALL_RETURN (::putpmsg (handle, + (ACE_STRBUF_TYPE) ctl, + (ACE_STRBUF_TYPE) data, + band, flags), int, -1); +#else + ACE_UNUSED_ARG (flags); + ACE_UNUSED_ARG (band); + return ACE_OS::putmsg (handle, ctl, data, flags); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +ACE_INLINE int +ACE_OS::semctl (int int_id, int semnum, int cmd, semun value) +{ + ACE_OS_TRACE ("ACE_OS::semctl"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::semctl (int_id, semnum, cmd, value), int, -1); +#else + ACE_UNUSED_ARG (int_id); + ACE_UNUSED_ARG (semnum); + ACE_UNUSED_ARG (cmd); + ACE_UNUSED_ARG (value); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE int +ACE_OS::semget (key_t key, int nsems, int flags) +{ + ACE_OS_TRACE ("ACE_OS::semget"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::semget (key, nsems, flags), int, -1); +#else + ACE_UNUSED_ARG (key); + ACE_UNUSED_ARG (nsems); + ACE_UNUSED_ARG (flags); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE int +ACE_OS::semop (int int_id, struct sembuf *sops, size_t nsops) +{ + ACE_OS_TRACE ("ACE_OS::semop"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::semop (int_id, sops, nsops), int, -1); +#else + ACE_UNUSED_ARG (int_id); + ACE_UNUSED_ARG (sops); + ACE_UNUSED_ARG (nsops); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE void * +ACE_OS::shmat (int int_id, void *shmaddr, int shmflg) +{ + ACE_OS_TRACE ("ACE_OS::shmat"); +#if defined (ACE_HAS_SYSV_IPC) +# if defined (ACE_LACKS_POSIX_PROTOTYPES) || defined (ACE_LACKS_SOME_POSIX_PROTOTYPES) + ACE_OSCALL_RETURN (::shmat (int_id, (char *)shmaddr, shmflg), void *, (void *) -1); +# else + ACE_OSCALL_RETURN (::shmat (int_id, shmaddr, shmflg), void *, (void *) -1); +# endif /* ACE_LACKS_POSIX_PROTOTYPES */ +#else + ACE_UNUSED_ARG (int_id); + ACE_UNUSED_ARG (shmaddr); + ACE_UNUSED_ARG (shmflg); + + ACE_NOTSUP_RETURN ((void *) -1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE int +ACE_OS::shmctl (int int_id, int cmd, struct shmid_ds *buf) +{ + ACE_OS_TRACE ("ACE_OS::shmctl"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::shmctl (int_id, cmd, buf), int, -1); +#else + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (cmd); + ACE_UNUSED_ARG (int_id); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE int +ACE_OS::shmdt (void *shmaddr) +{ + ACE_OS_TRACE ("ACE_OS::shmdt"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::shmdt ((char *) shmaddr), int, -1); +#else + ACE_UNUSED_ARG (shmaddr); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE int +ACE_OS::shmget (key_t key, int size, int flags) +{ + ACE_OS_TRACE ("ACE_OS::shmget"); +#if defined (ACE_HAS_SYSV_IPC) + ACE_OSCALL_RETURN (::shmget (key, size, flags), int, -1); +#else + ACE_UNUSED_ARG (flags); + ACE_UNUSED_ARG (size); + ACE_UNUSED_ARG (key); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SYSV_IPC */ +} + +ACE_INLINE void +ACE_OS::tzset (void) +{ +#if defined (ACE_HAS_PACE) + ::pace_tzset (); +# elif !defined (ACE_HAS_WINCE) && !defined (VXWORKS) && !defined (ACE_PSOS) && ! defined(__rtems__) +# if defined (ACE_WIN32) + ::_tzset (); // For Win32. +# else + ::tzset (); // For UNIX platforms. +# endif /* ACE_WIN32 */ +# else + errno = ENOTSUP; +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE long +ACE_OS::timezone (void) +{ + return ::ace_timezone (); +} + +#if !defined (ACE_LACKS_DIFFTIME) +ACE_INLINE double +ACE_OS::difftime (time_t t1, time_t t0) +{ + return ::ace_difftime (t1, t0); +} +#endif /* ! ACE_LACKS_DIFFTIME */ + +ACE_INLINE ACE_TCHAR * +ACE_OS::ctime (const time_t *t) +{ + ACE_OS_TRACE ("ACE_OS::ctime"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_ctime (t), char*, 0); +#elif defined (ACE_HAS_BROKEN_CTIME) + ACE_OSCALL_RETURN (::asctime (::localtime (t)), char *, 0); +#elif defined(ACE_PSOS) && ! defined (ACE_PSOS_HAS_TIME) + return "ctime-return"; +#elif defined (ACE_HAS_WINCE) + ACE_TCHAR buf[26]; // 26 is a "magic number" ;) + return ACE_OS::ctime_r (t, buf, 26); +#elif defined (ACE_USES_WCHAR) + ACE_OSCALL_RETURN (::_wctime (t), wchar_t *, 0); +#else + ACE_OSCALL_RETURN (::ctime (t), char *, 0); +# endif /* ACE_HAS_PACE */ +} + +#if !defined (ACE_HAS_WINCE) /* CE version in OS.cpp */ +ACE_INLINE ACE_TCHAR * +ACE_OS::ctime_r (const time_t *t, ACE_TCHAR *buf, int buflen) +{ + ACE_OS_TRACE ("ACE_OS::ctime_r"); +#if defined (ACE_HAS_PACE) + ACE_UNUSED_ARG (buflen); + ACE_OSCALL_RETURN (::pace_ctime_r (t, buf), ACE_TCHAR*, 0); +#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) +# if defined (ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R) + ACE_TCHAR *result; +# if defined (DIGITAL_UNIX) + ACE_OSCALL (::_Pctime_r (t, buf), ACE_TCHAR *, 0, result); +# else /* DIGITAL_UNIX */ + ACE_OSCALL (::ctime_r (t, buf), ACE_TCHAR *, 0, result); +# endif /* DIGITAL_UNIX */ + if (result != 0) + // This needs to be rather than + // to avoid problems on certain platforms. + ACE_OS::strncpy (buf, result, buflen); + return buf; +# else /* ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R */ + +# if defined (ACE_CTIME_R_RETURNS_INT) + return (::ctime_r (t, buf, buflen) == -1 ? 0 : buf); +# else /* ACE_CTIME_R_RETURNS_INT */ + ACE_OSCALL_RETURN (::ctime_r (t, buf, buflen), ACE_TCHAR *, 0); +# endif /* ACE_CTIME_R_RETURNS_INT */ + +# endif /* ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R */ +#else /* ACE_HAS_REENTRANT_FUNCTIONS */ +# if defined (ACE_PSOS) && ! defined (ACE_PSOS_HAS_TIME) + ACE_OS::strsncpy (buf, "ctime-return", buflen); + return buf; +# else /* ACE_PSOS && !ACE_PSOS_HAS_TIME */ + + ACE_TCHAR *result; +# if defined (ACE_USES_WCHAR) + ACE_OSCALL (::_wctime (t), wchar_t *, 0, result); +# else /* ACE_WIN32 */ + ACE_OSCALL (::ctime (t), char *, 0, result); +# endif /* ACE_WIN32 */ + if (result != 0) + // This needs to be rather than + // to avoid problems on certain platforms. + ACE_OS::strncpy (buf, result, buflen); + return buf; +# endif /* ACE_PSOS && !ACE_PSOS_HAS_TIME */ +#endif /* ACE_HAS_PACE */ +} +#endif /* !ACE_HAS_WINCE */ + +ACE_INLINE struct tm * +ACE_OS::localtime (const time_t *t) +{ +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_localtime (t), pace_tm*, 0); +#elif !defined (ACE_HAS_WINCE) && !defined(ACE_PSOS) || defined (ACE_PSOS_HAS_TIME) + ACE_OS_TRACE ("ACE_OS::localtime"); + ACE_OSCALL_RETURN (::localtime (t), struct tm *, 0); +#else + // @@ Don't you start wondering what kind of functions + // does WinCE really support? + ACE_UNUSED_ARG (t); + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE struct tm * +ACE_OS::gmtime (const time_t *t) +{ +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_gmtime (t), pace_tm*, 0); +#elif !defined (ACE_HAS_WINCE) && !defined (ACE_PSOS) || defined (ACE_PSOS_HAS_TIME) + ACE_OS_TRACE ("ACE_OS::gmtime"); + ACE_OSCALL_RETURN (::gmtime (t), struct tm *, 0); +#else + // @@ WinCE doesn't have gmtime also. + ACE_UNUSED_ARG (t); + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE struct tm * +ACE_OS::gmtime_r (const time_t *t, struct tm *res) +{ + ACE_OS_TRACE ("ACE_OS::gmtime_r"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_gmtime_r (t, res), pace_tm*, 0); +#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) +# if defined (DIGITAL_UNIX) + ACE_OSCALL_RETURN (::_Pgmtime_r (t, res), struct tm *, 0); +# elif defined (HPUX_10) + return (::gmtime_r (t, res) == 0 ? res : (struct tm *) 0); +# else + ACE_OSCALL_RETURN (::gmtime_r (t, res), struct tm *, 0); +# endif /* DIGITAL_UNIX */ +#elif !defined (ACE_HAS_WINCE) && !defined(ACE_PSOS) || defined (ACE_PSOS_HAS_TIME) + struct tm *result; + ACE_OSCALL (::gmtime (t), struct tm *, 0, result) ; + if (result != 0) + *res = *result; + return res; +#else + // @@ Same as ACE_OS::gmtime (), you need to implement it + // yourself. + ACE_UNUSED_ARG (t); + ACE_UNUSED_ARG (res); + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE char * +ACE_OS::asctime (const struct tm *t) +{ +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_asctime (t), char*, 0); +#elif !defined (ACE_HAS_WINCE) && !defined(ACE_PSOS) || defined (ACE_PSOS_HAS_TIME) + ACE_OS_TRACE ("ACE_OS::asctime"); + ACE_OSCALL_RETURN (::asctime (t), char *, 0); +#else + // @@ WinCE doesn't have gmtime also. + ACE_UNUSED_ARG (t); + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE char * +ACE_OS::asctime_r (const struct tm *t, char *buf, int buflen) +{ + ACE_OS_TRACE ("ACE_OS::asctime_r"); +#if defined (ACE_HAS_PACE) + ACE_UNUSED_ARG (buflen); + ACE_OSCALL_RETURN (::pace_asctime_r (t, buf), char*, 0); +#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) +# if defined (ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R) + char *result; +# if defined (DIGITAL_UNIX) + ACE_OSCALL (::_Pasctime_r (t, buf), char *, 0, result); +# else + ACE_OSCALL (::asctime_r (t, buf), char *, 0, result); +# endif /* DIGITAL_UNIX */ + ACE_OS::strsncpy (buf, result, buflen); + return buf; +# else +# if defined (HPUX_10) + return (::asctime_r(t, buf, buflen) == 0 ? buf : (char *)0); +# else + ACE_OSCALL_RETURN (::asctime_r (t, buf, buflen), char *, 0); +# endif /* HPUX_10 */ +# endif /* ACE_HAS_2_PARAM_ASCTIME_R_AND_CTIME_R */ +#elif ! defined (ACE_HAS_WINCE) && !defined(ACE_PSOS) || defined (ACE_PSOS_HAS_TIME) + char *result; + ACE_OSCALL (::asctime (t), char *, 0, result); + ACE_OS::strsncpy (buf, result, buflen); + return buf; +#else + // @@ Same as ACE_OS::asctime (), you need to implement it + // yourself. + ACE_UNUSED_ARG (t); + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (buflen); + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE size_t +ACE_OS::strftime (char *s, size_t maxsize, const char *format, + const struct tm *timeptr) +{ +#if defined (ACE_HAS_PACE) + return ::pace_strftime (s, maxsize, format, timeptr); +#elif !defined (ACE_HAS_WINCE) && !defined(ACE_PSOS) || defined (ACE_PSOS_HAS_TIME) + return ::strftime (s, maxsize, format, timeptr); +#else + ACE_UNUSED_ARG (s); + ACE_UNUSED_ARG (maxsize); + ACE_UNUSED_ARG (format); + ACE_UNUSED_ARG (timeptr); + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::flock_init (ACE_OS::ace_flock_t *lock, + int flags, + const ACE_TCHAR *name, + mode_t perms) +{ + ACE_OS_TRACE ("ACE_OS::flock_init"); +#if defined (CHORUS) + lock->lockname_ = 0; + // Let's see if it already exists. + lock->handle_ = ACE_OS::shm_open (name, + flags | O_CREAT | O_EXCL, + perms); + if (lock->handle_ == ACE_INVALID_HANDLE) + { + if (errno == EEXIST) + // It's already there, so we'll just open it. + lock->handle_ = ACE_OS::shm_open (name, + flags | O_CREAT, + ACE_DEFAULT_FILE_PERMS); + else + return -1; + } + else + { + // We own this shared memory object! Let's set its size. + if (ACE_OS::ftruncate (lock->handle_, + sizeof (ACE_mutex_t)) == -1) + return -1; + // Note that only the owner can destroy a file lock... + ACE_ALLOCATOR_RETURN (lock->lockname_, + ACE_OS::strdup (name), + -1); + } + if (lock->handle_ == ACE_INVALID_HANDLE) + return -1; + + lock->process_lock_ = + (ACE_mutex_t *) ACE_OS::mmap (0, + sizeof (ACE_mutex_t), + PROT_RDWR, + MAP_SHARED, + lock->handle_, + 0); + if (lock->process_lock_ == MAP_FAILED) + return -1; + + if (lock->lockname_ + // Only initialize it if we're the one who created it. + && ACE_OS::mutex_init (lock->process_lock_, + USYNC_PROCESS, + name, + 0) != 0) + return -1; + return 0; +#else +#if defined (ACE_WIN32) + // Once initialized, these values are never changed. + lock->overlapped_.Internal = 0; + lock->overlapped_.InternalHigh = 0; + lock->overlapped_.OffsetHigh = 0; + lock->overlapped_.hEvent = NULL; +#endif /* ACE_WIN32 */ + lock->handle_ = ACE_INVALID_HANDLE; + lock->lockname_ = 0; + + if (name != 0) + { + ACE_OSCALL (ACE_OS::open (name, flags, perms), + ACE_HANDLE, + ACE_INVALID_HANDLE, + lock->handle_); + lock->lockname_ = ACE_OS::strdup (name); + return lock->handle_ == ACE_INVALID_HANDLE ? -1 : 0; + } + else + return 0; +#endif /* CHORUS */ +} + +#if defined (ACE_WIN32) +ACE_INLINE void +ACE_OS::adjust_flock_params (ACE_OS::ace_flock_t *lock, + short whence, + off_t &start, + off_t &len) +{ + switch (whence) + { + case SEEK_SET: + break; + case SEEK_CUR: + start += SetFilePointer (lock->handle_, 0, 0, FILE_CURRENT); + break; + case SEEK_END: + start += ::GetFileSize (lock->handle_, NULL); + break; + } + lock->overlapped_.Offset = start; + if (len == 0) + len = ::GetFileSize (lock->handle_, + NULL) - start; +} +#endif /* ACE_WIN32 */ + +ACE_INLINE int +ACE_OS::flock_wrlock (ACE_OS::ace_flock_t *lock, + short whence, + off_t start, + off_t len) +{ + ACE_OS_TRACE ("ACE_OS::flock_wrlock"); +#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) + ACE_OS::adjust_flock_params (lock, whence, start, len); +# if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::LockFileEx (lock->handle_, + LOCKFILE_EXCLUSIVE_LOCK, + 0, + len, + 0, + &lock->overlapped_), + ace_result_), int, -1); +# else /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::LockFile (lock->handle_, + lock->overlapped_.Offset, + 0, + len, + 0), + ace_result_), int, -1); +# endif /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ +#elif defined (CHORUS) + ACE_UNUSED_ARG (whence); + ACE_UNUSED_ARG (start); + ACE_UNUSED_ARG (len); + return ACE_OS::mutex_lock (lock->process_lock_); +#elif defined (ACE_LACKS_FILELOCKS) + ACE_UNUSED_ARG (lock); + ACE_UNUSED_ARG (whence); + ACE_UNUSED_ARG (start); + ACE_UNUSED_ARG (len); + ACE_NOTSUP_RETURN (-1); +#else + lock->lock_.l_whence = whence; + lock->lock_.l_start = start; + lock->lock_.l_len = len; + lock->lock_.l_type = F_WRLCK; // set write lock + // block, if no access + ACE_OSCALL_RETURN (ACE_OS::fcntl (lock->handle_, F_SETLKW, + ACE_reinterpret_cast (long, &lock->lock_)), + int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::flock_rdlock (ACE_OS::ace_flock_t *lock, + short whence, + off_t start, + off_t len) +{ + ACE_OS_TRACE ("ACE_OS::flock_rdlock"); +#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) + ACE_OS::adjust_flock_params (lock, whence, start, len); +# if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::LockFileEx (lock->handle_, + 0, + 0, + len, + 0, + &lock->overlapped_), + ace_result_), int, -1); +# else /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::LockFile (lock->handle_, + lock->overlapped_.Offset, + 0, + len, + 0), + ace_result_), int, -1); +# endif /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ +#elif defined (CHORUS) + ACE_UNUSED_ARG (whence); + ACE_UNUSED_ARG (start); + ACE_UNUSED_ARG (len); + return ACE_OS::mutex_lock (lock->process_lock_); +#elif defined (ACE_LACKS_FILELOCKS) + ACE_UNUSED_ARG (lock); + ACE_UNUSED_ARG (whence); + ACE_UNUSED_ARG (start); + ACE_UNUSED_ARG (len); + ACE_NOTSUP_RETURN (-1); +#else + lock->lock_.l_whence = whence; + lock->lock_.l_start = start; + lock->lock_.l_len = len; + lock->lock_.l_type = F_RDLCK; // set read lock + // block, if no access + ACE_OSCALL_RETURN (ACE_OS::fcntl (lock->handle_, F_SETLKW, + ACE_reinterpret_cast (long, &lock->lock_)), + int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::flock_trywrlock (ACE_OS::ace_flock_t *lock, + short whence, + off_t start, + off_t len) +{ + ACE_OS_TRACE ("ACE_OS::ace_flock_trywrlock"); +#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) +# if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0) + ACE_OS::adjust_flock_params (lock, whence, start, len); + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::LockFileEx (lock->handle_, + LOCKFILE_FAIL_IMMEDIATELY | LOCKFILE_EXCLUSIVE_LOCK, + 0, + len, + 0, + &lock->overlapped_), + ace_result_), int, -1); +# else /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ + ACE_UNUSED_ARG (lock); + ACE_UNUSED_ARG (whence); + ACE_UNUSED_ARG (start); + ACE_UNUSED_ARG (len); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ +#elif defined (CHORUS) + ACE_UNUSED_ARG (whence); + ACE_UNUSED_ARG (start); + ACE_UNUSED_ARG (len); + return ACE_OS::mutex_trylock (lock->process_lock_); +#elif defined (ACE_LACKS_FILELOCKS) + ACE_UNUSED_ARG (lock); + ACE_UNUSED_ARG (whence); + ACE_UNUSED_ARG (start); + ACE_UNUSED_ARG (len); + ACE_NOTSUP_RETURN (-1); +#else + lock->lock_.l_whence = whence; + lock->lock_.l_start = start; + lock->lock_.l_len = len; + lock->lock_.l_type = F_WRLCK; // set write lock + + int result = 0; + // Does not block, if no access, returns -1 and set errno = EBUSY; + ACE_OSCALL (ACE_OS::fcntl (lock->handle_, + F_SETLK, + ACE_reinterpret_cast (long, &lock->lock_)), + int, -1, result); + +# if ! defined (ACE_PSOS) + if (result == -1 && (errno == EACCES || errno == EAGAIN)) + errno = EBUSY; +# endif /* ! defined (ACE_PSOS) */ + + return result; +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::flock_tryrdlock (ACE_OS::ace_flock_t *lock, + short whence, + off_t start, + off_t len) +{ + ACE_OS_TRACE ("ACE_OS::ace_flock_tryrdlock"); +#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) +# if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0) + ACE_OS::adjust_flock_params (lock, whence, start, len); + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::LockFileEx (lock->handle_, + LOCKFILE_FAIL_IMMEDIATELY, + 0, + len, + 0, + &lock->overlapped_), + ace_result_), int, -1); +# else /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ + ACE_UNUSED_ARG (lock); + ACE_UNUSED_ARG (whence); + ACE_UNUSED_ARG (start); + ACE_UNUSED_ARG (len); + ACE_NOTSUP_RETURN (-1); +# endif /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ +#elif defined (CHORUS) + ACE_UNUSED_ARG (whence); + ACE_UNUSED_ARG (start); + ACE_UNUSED_ARG (len); + return ACE_OS::mutex_trylock (lock->process_lock_); +#elif defined (ACE_LACKS_FILELOCKS) + ACE_UNUSED_ARG (lock); + ACE_UNUSED_ARG (whence); + ACE_UNUSED_ARG (start); + ACE_UNUSED_ARG (len); + ACE_NOTSUP_RETURN (-1); +#else + lock->lock_.l_whence = whence; + lock->lock_.l_start = start; + lock->lock_.l_len = len; + lock->lock_.l_type = F_RDLCK; // set read lock + + int result = 0; + // Does not block, if no access, returns -1 and set errno = EBUSY; + ACE_OSCALL (ACE_OS::fcntl (lock->handle_, F_SETLK, + ACE_reinterpret_cast (long, &lock->lock_)), + int, -1, result); + +# if ! defined (ACE_PSOS) + if (result == -1 && (errno == EACCES || errno == EAGAIN)) + errno = EBUSY; +# endif /* ! defined (ACE_PSOS) */ + + return result; +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::flock_unlock (ACE_OS::ace_flock_t *lock, + short whence, + off_t start, + off_t len) +{ + ACE_OS_TRACE ("ACE_OS::flock_unlock"); +#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) + ACE_OS::adjust_flock_params (lock, whence, start, len); + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::UnlockFile (lock->handle_, + lock->overlapped_.Offset, + 0, + len, + 0), + ace_result_), int, -1); +#elif defined (CHORUS) + ACE_UNUSED_ARG (whence); + ACE_UNUSED_ARG (start); + ACE_UNUSED_ARG (len); + return ACE_OS::mutex_unlock (lock->process_lock_); +#elif defined (ACE_LACKS_FILELOCKS) + ACE_UNUSED_ARG (lock); + ACE_UNUSED_ARG (whence); + ACE_UNUSED_ARG (start); + ACE_UNUSED_ARG (len); + ACE_NOTSUP_RETURN (-1); +#else + lock->lock_.l_whence = whence; + lock->lock_.l_start = start; + lock->lock_.l_len = len; + lock->lock_.l_type = F_UNLCK; // Unlock file. + + // release lock + ACE_OSCALL_RETURN (ACE_OS::fcntl (lock->handle_, F_SETLK, + ACE_reinterpret_cast (long, &lock->lock_)), + int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::flock_destroy (ACE_OS::ace_flock_t *lock, + int unlink_file) +{ + ACE_OS_TRACE ("ACE_OS::flock_destroy"); + if (lock->handle_ != ACE_INVALID_HANDLE) + { + ACE_OS::flock_unlock (lock); + // Close the handle. + ACE_OS::close (lock->handle_); + lock->handle_ = ACE_INVALID_HANDLE; +#if defined (CHORUS) + // Are we the owner? + if (lock->process_lock_ && lock->lockname_ != 0) + { + // Only destroy the lock if we're the owner + ACE_OS::mutex_destroy (lock->process_lock_); + ACE_OS::munmap (lock->process_lock_, + sizeof (ACE_mutex_t)); + if (unlink_file) + ACE_OS::shm_unlink (lock->lockname_); + ACE_OS::free (ACE_static_cast (void *, + ACE_const_cast (ACE_TCHAR *, + lock->lockname_))); + } + else if (lock->process_lock_) + // Just unmap the memory. + ACE_OS::munmap (lock->process_lock_, + sizeof (ACE_mutex_t)); +#else + if (lock->lockname_ != 0) + { + if (unlink_file) + ACE_OS::unlink (lock->lockname_); + ACE_OS::free (ACE_static_cast (void *, + ACE_const_cast (ACE_TCHAR *, + lock->lockname_))); + } +#endif /* CHORUS */ + lock->lockname_ = 0; + } + return 0; +} + +ACE_INLINE int +ACE_OS::execv (const char *path, + char *const argv[]) +{ + ACE_OS_TRACE ("ACE_OS::execv"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_execv (path, argv), int, -1); +#elif defined (ACE_LACKS_EXEC) + ACE_UNUSED_ARG (path); + ACE_UNUSED_ARG (argv); + + ACE_NOTSUP_RETURN (-1); +#elif defined (CHORUS) + KnCap cactorcap; + int result = ::afexecv (path, &cactorcap, 0, argv); + if (result != -1) + ACE_OS::actorcaps_[result] = cactorcap; + return result; +#elif defined (ACE_WIN32) +# if defined (__BORLANDC__) /* VSB */ + return ::execv (path, argv); +# elif defined (__MINGW32__) + return ::_execv (path, (char *const *) argv); +# else + return ::_execv (path, (const char *const *) argv); +# endif /* __BORLANDC__ */ +#elif defined (ACE_LACKS_POSIX_PROTOTYPES) + ACE_OSCALL_RETURN (::execv (path, (const char **) argv), int, -1); +#else + ACE_OSCALL_RETURN (::execv (path, argv), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::execve (const char *path, + char *const argv[], + char *const envp[]) +{ + ACE_OS_TRACE ("ACE_OS::execve"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_execve (path, argv, envp), int, -1); +#elif defined (ACE_LACKS_EXEC) + ACE_UNUSED_ARG (path); + ACE_UNUSED_ARG (argv); + ACE_UNUSED_ARG (envp); + + ACE_NOTSUP_RETURN (-1); +#elif defined(CHORUS) + KnCap cactorcap; + int result = ::afexecve (path, &cactorcap, 0, argv, envp); + if (result != -1) + ACE_OS::actorcaps_[result] = cactorcap; + return result; +#elif defined (ACE_WIN32) +# if defined (__BORLANDC__) /* VSB */ + return ::execve (path, argv, envp); +# elif defined (__MINGW32__) + return ::_execve (path, (char *const *) argv, (char *const *) envp); +# else + return ::_execve (path, (const char *const *) argv, (const char *const *) envp); +# endif /* __BORLANDC__ */ +#elif defined (ACE_LACKS_POSIX_PROTOTYPES) + ACE_OSCALL_RETURN (::execve (path, (const char **) argv, (char **) envp), int, -1); +#else + ACE_OSCALL_RETURN (::execve (path, argv, envp), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::execvp (const char *file, + char *const argv[]) +{ + ACE_OS_TRACE ("ACE_OS::execvp"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_execvp (file, argv), int, -1); +#elif defined (ACE_LACKS_EXEC) + ACE_UNUSED_ARG (file); + ACE_UNUSED_ARG (argv); + + ACE_NOTSUP_RETURN (-1); +#elif defined(CHORUS) + KnCap cactorcap; + int result = ::afexecvp (file, &cactorcap, 0, argv); + if (result != -1) + ACE_OS::actorcaps_[result] = cactorcap; + return result; +#elif defined (ACE_WIN32) +# if defined (__BORLANDC__) /* VSB */ + return ::execvp (file, argv); +# elif defined (__MINGW32__) + return ::_execvp (file, (char *const *) argv); +# else + return ::_execvp (file, (const char *const *) argv); +# endif /* __BORLANDC__ */ +#elif defined (ACE_LACKS_POSIX_PROTOTYPES) + ACE_OSCALL_RETURN (::execvp (file, (const char **) argv), int, -1); +#else + ACE_OSCALL_RETURN (::execvp (file, argv), int, -1); +#endif /* ACE_HAS_PACE */ +} + +#if !defined (ACE_HAS_WINCE) +ACE_INLINE FILE * +ACE_OS::fdopen (ACE_HANDLE handle, const ACE_TCHAR *mode) +{ + ACE_OS_TRACE ("ACE_OS::fdopen"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_fdopen (handle, mode), FILE*, 0); +# elif defined (ACE_WIN32) + // kernel file handle -> FILE* conversion... + // Options: _O_APPEND, _O_RDONLY and _O_TEXT are lost + + FILE *file = 0; + + int crt_handle = ::_open_osfhandle ((long) handle, 0); + + if (crt_handle != -1) + { +# if defined(__BORLANDC__) /* VSB */ + file = ::_fdopen (crt_handle, (char *) mode); +# elif defined (ACE_USES_WCHAR) + file = ::_wfdopen (crt_handle, mode); +# else + file = ::_fdopen (crt_handle, mode); +# endif /* __BORLANDC__ */ + + if (!file) + { +# if (defined(__BORLANDC__) && __BORLANDC__ >= 0x0530) + ::_rtl_close (crt_handle); +# else + ::_close (crt_handle); +# endif /* (defined(__BORLANDC__) && __BORLANDC__ >= 0x0530) */ + } + } + + return file; +# elif defined (ACE_PSOS) + // @@ it may be possible to implement this for pSOS, + // but it isn't obvious how to do this (perhaps via + // f_stat to glean the default volume, and then open_fn ?) + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (mode); + ACE_NOTSUP_RETURN (0); +# else + ACE_OSCALL_RETURN (::fdopen (handle, mode), FILE *, 0); +# endif /* ACE_HAS_PACE */ +} +#endif /* ! ACE_HAS_WINCE */ + +ACE_INLINE int +ACE_OS::getrlimit (int resource, struct rlimit *rl) +{ + ACE_OS_TRACE ("ACE_OS::getrlimit"); + +#if defined (ACE_LACKS_RLIMIT) + ACE_UNUSED_ARG (resource); + ACE_UNUSED_ARG (rl); + + ACE_NOTSUP_RETURN (-1); +#else +# if defined (ACE_HAS_RLIMIT_RESOURCE_ENUM) + ACE_OSCALL_RETURN (::getrlimit ((ACE_HAS_RLIMIT_RESOURCE_ENUM) resource, rl), int, -1); +# else + ACE_OSCALL_RETURN (::getrlimit (resource, rl), int, -1); +# endif /* ACE_HAS_RLIMIT_RESOURCE_ENUM */ +#endif /* ACE_LACKS_RLIMIT */ +} + +ACE_INLINE int +ACE_OS::setrlimit (int resource, ACE_SETRLIMIT_TYPE *rl) +{ + ACE_OS_TRACE ("ACE_OS::setrlimit"); + +#if defined (ACE_LACKS_RLIMIT) + ACE_UNUSED_ARG (resource); + ACE_UNUSED_ARG (rl); + + ACE_NOTSUP_RETURN (-1); +#else +# if defined (ACE_HAS_RLIMIT_RESOURCE_ENUM) + ACE_OSCALL_RETURN (::setrlimit ((ACE_HAS_RLIMIT_RESOURCE_ENUM) resource, rl), int, -1); +# else + ACE_OSCALL_RETURN (::setrlimit (resource, rl), int, -1); +# endif /* ACE_HAS_RLIMIT_RESOURCE_ENUM */ +#endif /* ACE_LACKS_RLIMIT */ +} + +ACE_INLINE int +ACE_OS::socketpair (int domain, int type, + int protocol, ACE_HANDLE sv[2]) +{ + ACE_OS_TRACE ("ACE_OS::socketpair"); +#if defined (ACE_WIN32) || defined (ACE_LACKS_SOCKETPAIR) + ACE_UNUSED_ARG (domain); + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (protocol); + ACE_UNUSED_ARG (sv); + + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::socketpair (domain, type, protocol, sv), + int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE ACE_HANDLE +ACE_OS::dup (ACE_HANDLE handle) +{ + ACE_OS_TRACE ("ACE_OS::dup"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_dup (handle), ACE_HANDLE, ACE_INVALID_HANDLE); +#elif defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) + ACE_HANDLE new_fd; + if (::DuplicateHandle(::GetCurrentProcess (), + handle, + ::GetCurrentProcess(), + &new_fd, + 0, + TRUE, + DUPLICATE_SAME_ACCESS)) + return new_fd; + else + ACE_FAIL_RETURN (ACE_INVALID_HANDLE); + /* NOTREACHED */ +#elif defined (VXWORKS) || defined (ACE_PSOS) + ACE_UNUSED_ARG (handle); + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_HAS_WINCE) + ACE_UNUSED_ARG (handle); + ACE_NOTSUP_RETURN (0); +#else + ACE_OSCALL_RETURN (::dup (handle), ACE_HANDLE, ACE_INVALID_HANDLE); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::dup2 (ACE_HANDLE oldhandle, ACE_HANDLE newhandle) +{ + ACE_OS_TRACE ("ACE_OS::dup2"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_dup2 (oldhandle, newhandle), int, -1); +#elif defined (ACE_WIN32) || defined (VXWORKS) || defined (ACE_PSOS) + // msvcrt has _dup2 ?! + ACE_UNUSED_ARG (oldhandle); + ACE_UNUSED_ARG (newhandle); + + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::dup2 (oldhandle, newhandle), int, -1); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ghs) && defined (ACE_HAS_PENTIUM) && !defined (ACE_WIN32) + extern "C" ACE_hrtime_t ACE_gethrtime (); +#endif /* ghs && ACE_HAS_PENTIUM */ + +ACE_INLINE ACE_hrtime_t +ACE_OS::gethrtime (const ACE_HRTimer_Op op) +{ + ACE_OS_TRACE ("ACE_OS::gethrtime"); +#if defined (ACE_HAS_HI_RES_TIMER) + ACE_UNUSED_ARG (op); + return ::gethrtime (); +#elif defined (ACE_HAS_AIX_HI_RES_TIMER) + ACE_UNUSED_ARG (op); + timebasestruct_t tb; + + ::read_real_time(&tb, TIMEBASE_SZ); + ::time_base_to_time(&tb, TIMEBASE_SZ); + + return ACE_hrtime_t(tb.tb_high) * ACE_ONE_SECOND_IN_NSECS + tb.tb_low; +#elif defined (ghs) && defined (ACE_HAS_PENTIUM) && !defined (ACE_WIN32) + ACE_UNUSED_ARG (op); + // Use .obj/gethrtime.o, which was compiled with g++. + return ACE_gethrtime (); +#elif (defined(__KCC) || defined (__GNUG__)) && !defined (__MINGW32__) && defined (ACE_HAS_PENTIUM) + ACE_UNUSED_ARG (op); + +# if defined (ACE_LACKS_LONGLONG_T) + double now; +# else /* ! ACE_LACKS_LONGLONG_T */ + ACE_hrtime_t now; +# endif /* ! ACE_LACKS_LONGLONG_T */ + + // See comments about the RDTSC Pentium instruction for the ACE_WIN32 + // version of ACE_OS::gethrtime (), below. + // + // Read the high-res tick counter directly into memory variable "now". + // The A constraint signifies a 64-bit int. + asm volatile ("rdtsc" : "=A" (now) : : "memory"); + +# if defined (ACE_LACKS_LONGLONG_T) + ACE_UINT32 least, most; + ACE_OS::memcpy (&least, &now, sizeof (ACE_UINT32)); + ACE_OS::memcpy (&most, (u_char *) &now + sizeof (ACE_UINT32), + sizeof (ACE_UINT32)); + + ACE_hrtime_t ret (least, most); + return ret; +# else /* ! ACE_LACKS_LONGLONG_T */ + return now; +# endif /* ! ACE_LACKS_LONGLONG_T */ +#elif defined (linux) && defined (ACE_HAS_ALPHA_TIMER) + // NOTE: alphas only have a 32 bit tick (cycle) counter. The rpcc + // instruction actually reads 64 bits, but the high 32 bits are + // implementation-specific. Linux and Digital Unix, for example, + // use them for virtual tick counts, i.e., taking into account only + // the time that the process was running. This information is from + // David Mosberger's article, see comment below. + ACE_UINT32 now; + + // The following statement is based on code published by: + // Mosberger, David, "How to Make Your Applications Fly, Part 1", + // Linux Journal Issue 42, October 1997, page 50. It reads the + // high-res tick counter directly into the memory variable. + asm volatile ("rpcc %0" : "=r" (now) : : "memory"); + + return now; +#elif defined (ACE_WIN32) + ACE_UNUSED_ARG(op); + LARGE_INTEGER freq; + + ::QueryPerformanceCounter (&freq); + +# if defined (ACE_LACKS_LONGLONG_T) + ACE_UINT64 uint64_freq(freq.u.LowPart, ACE_static_cast (unsigned int, freq.u.HighPart)); + return uint64_freq; +# else + return freq.QuadPart; +# endif //ACE_LACKS_LONGLONG_T + +#elif defined (CHORUS) + if (op == ACE_OS::ACE_HRTIMER_GETTIME) + { + struct timespec ts; + + ACE_OS::clock_gettime (CLOCK_REALTIME, &ts); + + // Carefully create the return value to avoid arithmetic overflow + // if ACE_hrtime_t is ACE_U_LongLong. + ACE_hrtime_t now = ts.tv_sec; + now *= ACE_U_ONE_SECOND_IN_NSECS; + now += ts.tv_nsec; + + return now; + } + else + { + // Use the sysBench timer on Chorus. On MVME177, at least, it only + // has 32 bits. Be careful, because using it disables interrupts! + ACE_UINT32 now; + if (::sysBench (op, (int *) &now) == K_OK) + { + now *= 1000u /* nanoseconds/microsecond */; + return (ACE_hrtime_t) now; + } + else + { + // Something went wrong. Just return 0. + return (ACE_hrtime_t) 0; + } + } + +#elif defined (ACE_HAS_POWERPC_TIMER) && (defined (ghs) || defined (__GNUG__)) + // PowerPC w/ GreenHills or g++. + + ACE_UNUSED_ARG (op); + u_long most; + u_long least; + ACE_OS::readPPCTimeBase (most, least); +#if defined (ACE_LACKS_LONGLONG_T) + return ACE_U_LongLong (least, most); +#else /* ! ACE_LACKS_LONGLONG_T */ + return 0x100000000llu * most + least; +#endif /* ! ACE_LACKS_LONGLONG_T */ + +#elif defined (ACE_HAS_CLOCK_GETTIME) || defined (ACE_PSOS) + // e.g., VxWorks (besides POWERPC && GreenHills) . . . + ACE_UNUSED_ARG (op); + struct timespec ts; + + ACE_OS::clock_gettime (CLOCK_REALTIME, &ts); + + // Carefully create the return value to avoid arithmetic overflow + // if ACE_hrtime_t is ACE_U_LongLong. + return ACE_static_cast (ACE_hrtime_t, ts.tv_sec) * + ACE_U_ONE_SECOND_IN_NSECS + ACE_static_cast (ACE_hrtime_t, ts.tv_nsec); +#else + ACE_UNUSED_ARG (op); + const ACE_Time_Value now = ACE_OS::gettimeofday (); + + // Carefully create the return value to avoid arithmetic overflow + // if ACE_hrtime_t is ACE_U_LongLong. + return (ACE_static_cast (ACE_hrtime_t, now.sec ()) * (ACE_UINT32) 1000000 + + ACE_static_cast (ACE_hrtime_t, now.usec ())) * (ACE_UINT32) 1000; +#endif /* ACE_HAS_HI_RES_TIMER */ +} + +ACE_INLINE int +ACE_OS::fdetach (const char *file) +{ + ACE_OS_TRACE ("ACE_OS::fdetach"); +#if defined (ACE_HAS_STREAM_PIPES) + ACE_OSCALL_RETURN (::fdetach (file), int, -1); +#else + ACE_UNUSED_ARG (file); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +ACE_INLINE int +ACE_OS::fattach (int handle, const char *path) +{ + ACE_OS_TRACE ("ACE_OS::fattach"); +#if defined (ACE_HAS_STREAM_PIPES) + ACE_OSCALL_RETURN (::fattach (handle, path), int, -1); +#else + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (path); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_STREAM_PIPES */ +} + +ACE_INLINE pid_t +ACE_OS::fork (void) +{ + ACE_OS_TRACE ("ACE_OS::fork"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_fork (), pid_t, -1); +#elif defined (ACE_LACKS_FORK) + ACE_NOTSUP_RETURN (pid_t (-1)); +#else + ACE_OSCALL_RETURN (::fork (), pid_t, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::getpagesize (void) +{ + ACE_OS_TRACE ("ACE_OS::getpagesize"); +#if defined (ACE_WIN32) && !defined (ACE_HAS_PHARLAP) + SYSTEM_INFO sys_info; + ::GetSystemInfo (&sys_info); + return (int) sys_info.dwPageSize; +#elif defined (_SC_PAGESIZE) + return (int) ::sysconf (_SC_PAGESIZE); +#elif defined (ACE_HAS_GETPAGESIZE) + return ::getpagesize (); +#else + // Use the default set in config.h + return ACE_PAGE_SIZE; +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::allocation_granularity (void) +{ +#if defined (ACE_WIN32) + SYSTEM_INFO sys_info; + ::GetSystemInfo (&sys_info); + return (int) sys_info.dwAllocationGranularity; +#else + return ACE_OS::getpagesize (); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE pid_t +ACE_OS::getpid (void) +{ + // ACE_OS_TRACE ("ACE_OS::getpid"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_getpid (), int , -1); +#elif defined (ACE_WIN32) + return ::GetCurrentProcessId (); +#elif defined (VXWORKS) || defined (ACE_PSOS) + // getpid() is not supported: just one process anyways + return 0; +#elif defined (CHORUS) + return (pid_t) (::agetId ()); +#else + ACE_OSCALL_RETURN (::getpid (), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE pid_t +ACE_OS::getpgid (pid_t pid) +{ + ACE_OS_TRACE ("ACE_OS::getpgid"); +#if defined (ACE_LACKS_GETPGID) + ACE_UNUSED_ARG (pid); + ACE_NOTSUP_RETURN (-1); +#elif defined (VXWORKS) || defined (ACE_PSOS) + // getpgid() is not supported, only one process anyway. + ACE_UNUSED_ARG (pid); + return 0; +#elif defined (linux) && __GLIBC__ > 1 && __GLIBC_MINOR__ >= 0 + // getpgid() is from SVR4, which appears to be the reason why GLIBC + // doesn't enable its prototype by default. + // Rather than create our own extern prototype, just use the one + // that is visible (ugh). + ACE_OSCALL_RETURN (::__getpgid (pid), pid_t, -1); +#else + ACE_OSCALL_RETURN (::getpgid (pid), pid_t, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE pid_t +ACE_OS::getppid (void) +{ + ACE_OS_TRACE ("ACE_OS::getppid"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_getppid (), pid_t, -1); +#elif defined (ACE_LACKS_GETPPID) + ACE_NOTSUP_RETURN (-1); +#elif defined (VXWORKS) || defined (ACE_PSOS) + // getppid() is not supported, only one process anyway. + return 0; +#else + ACE_OSCALL_RETURN (::getppid (), pid_t, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::setpgid (pid_t pid, pid_t pgid) +{ + ACE_OS_TRACE ("ACE_OS::setpgid"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_setpgid (pid, pgid), int, -1); +#elif defined (ACE_LACKS_SETPGID) + ACE_UNUSED_ARG (pid); + ACE_UNUSED_ARG (pgid); + ACE_NOTSUP_RETURN (-1); +#elif defined (VXWORKS) || defined (ACE_PSOS) + // is not supported, only one process anyway. + ACE_UNUSED_ARG (pid); + ACE_UNUSED_ARG (pgid); + return 0; +#else + ACE_OSCALL_RETURN (::setpgid (pid, pgid), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::setreuid (uid_t ruid, uid_t euid) +{ + ACE_OS_TRACE ("ACE_OS::setreuid"); +#if defined (ACE_LACKS_SETREUID) + ACE_UNUSED_ARG (ruid); + ACE_UNUSED_ARG (euid); + ACE_NOTSUP_RETURN (-1); +#elif defined (VXWORKS) || defined (ACE_PSOS) + // is not supported, only one process anyway. + ACE_UNUSED_ARG (ruid); + ACE_UNUSED_ARG (euid); + return 0; +#else + ACE_OSCALL_RETURN (::setreuid (ruid, euid), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::setregid (gid_t rgid, gid_t egid) +{ + ACE_OS_TRACE ("ACE_OS::setregid"); +#if defined (ACE_LACKS_SETREGID) + ACE_UNUSED_ARG (rgid); + ACE_UNUSED_ARG (egid); + ACE_NOTSUP_RETURN (-1); +#elif defined (VXWORKS) || defined (ACE_PSOS) + // is not supported, only one process anyway. + ACE_UNUSED_ARG (rgid); + ACE_UNUSED_ARG (egid); + return 0; +#else + ACE_OSCALL_RETURN (::setregid (rgid, egid), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE off_t +ACE_OS::lseek (ACE_HANDLE handle, off_t offset, int whence) +{ + ACE_OS_TRACE ("ACE_OS::lseek"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_lseek (handle, offset, whence), pace_off_t, -1); +#elif defined (ACE_WIN32) +# if SEEK_SET != FILE_BEGIN || SEEK_CUR != FILE_CURRENT || SEEK_END != FILE_END + //#error Windows NT is evil AND rude! + switch (whence) + { + case SEEK_SET: + whence = FILE_BEGIN; + break; + case SEEK_CUR: + whence = FILE_CURRENT; + break; + case SEEK_END: + whence = FILE_END; + break; + default: + errno = EINVAL; + return ACE_static_cast (off_t, -1); // rather safe than sorry + } +# endif /* SEEK_SET != FILE_BEGIN || SEEK_CUR != FILE_CURRENT || SEEK_END != FILE_END */ + DWORD result = ::SetFilePointer (handle, offset, NULL, whence); + if (result == ACE_SYSCALL_FAILED) + ACE_FAIL_RETURN (ACE_static_cast (off_t, -1)); + else + return result; +#elif defined (ACE_PSOS) +# if defined (ACE_PSOS_LACKS_PHILE) + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (offset); + ACE_UNUSED_ARG (whence); + ACE_NOTSUP_RETURN (ACE_static_cast (off_t, -1)); +# else + unsigned long oldptr, newptr, result; + // seek to the requested position + result = ::lseek_f (handle, whence, offset, &oldptr); + if (result != 0) + { + errno = result; + return ACE_static_cast (off_t, -1); + } + // now do a dummy seek to the current position to obtain the position + result = ::lseek_f (handle, SEEK_CUR, 0, &newptr); + if (result != 0) + { + errno = result; + return ACE_static_cast (off_t, -1); + } + return ACE_static_cast (off_t, newptr); +# endif /* defined (ACE_PSOS_LACKS_PHILE */ +#else + ACE_OSCALL_RETURN (::lseek (handle, offset, whence), off_t, -1); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_LLSEEK) || defined (ACE_HAS_LSEEK64) +ACE_INLINE ACE_LOFF_T +ACE_OS::llseek (ACE_HANDLE handle, ACE_LOFF_T offset, int whence) +{ + ACE_OS_TRACE ("ACE_OS::llseek"); + +#if ACE_SIZEOF_LONG == 8 + /* The native lseek is 64 bit. Use it. */ + return ACE_OS::lseek (handle, offset, whence); +#elif defined (ACE_HAS_LLSEEK) && defined (ACE_HAS_LSEEK64) +# error Either ACE_HAS_LSEEK64 and ACE_HAS_LLSEEK should be defined, not both! +#elif defined (ACE_HAS_LSEEK64) + ACE_OSCALL_RETURN (::lseek64 (handle, offset, whence), ACE_LOFF_T, -1); +#elif defined (ACE_HAS_LLSEEK) + # if defined (ACE_WIN32) + LARGE_INTEGER li; + li.QuadPart = offset; + li.LowPart = ::SetFilePointer (handle, li.LowPart, &li.HighPart, whence); + if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) + li.QuadPart = -1; + return li.QuadPart; + # else + ACE_OSCALL_RETURN (::llseek (handle, offset, whence), ACE_LOFF_T, -1); + # endif /* WIN32 */ +#endif +} +#endif /* ACE_HAS_LLSEEK || ACE_HAS_LSEEK64 */ + +ACE_INLINE int +ACE_OS::fseek (FILE *fp, long offset, int whence) +{ +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_fseek (fp, offset, whence), int, -1); +#elif defined (ACE_HAS_WINCE) + return ACE_OS::lseek (fp, offset, whence); +#else /* ACE_HAS_WINCE */ +# if defined (ACE_WIN32) +# if SEEK_SET != FILE_BEGIN || SEEK_CUR != FILE_CURRENT || SEEK_END != FILE_END + //#error Windows NT is evil AND rude! + switch (whence) + { + case SEEK_SET: + whence = FILE_BEGIN; + break; + case SEEK_CUR: + whence = FILE_CURRENT; + break; + case SEEK_END: + whence = FILE_END; + break; + default: + errno = EINVAL; + return -1; // rather safe than sorry + } +# endif /* SEEK_SET != FILE_BEGIN || SEEK_CUR != FILE_CURRENT || SEEK_END != FILE_END */ +# endif /* ACE_WIN32 */ + ACE_OSCALL_RETURN (::fseek (fp, offset, whence), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE pid_t +ACE_OS::waitpid (pid_t pid, + ACE_exitcode *status, + int wait_options, + ACE_HANDLE handle) +{ + ACE_OS_TRACE ("ACE_OS::waitpid"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_UNUSED_ARG (handle); + ACE_OSCALL_RETURN (::pace_waitpid (pid, status, wait_options), int, -1); +#elif defined (VXWORKS) || defined (ACE_PSOS) + ACE_UNUSED_ARG (pid); + ACE_UNUSED_ARG (status); + ACE_UNUSED_ARG (wait_options); + ACE_UNUSED_ARG (handle); + + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_WIN32) + int blocking_period = ACE_BIT_ENABLED (wait_options, WNOHANG) + ? 0 /* don't hang */ + : INFINITE; + + ACE_HANDLE phandle = handle; + + if (phandle == 0) + { + phandle = ::OpenProcess (SYNCHRONIZE, + FALSE, + pid); + + if (phandle == 0) + { + ACE_OS::set_errno_to_last_error (); + return -1; + } + } + + pid_t result = pid; + + // Don't try to get the process exit status if wait failed so we can + // keep the original error code intact. + switch (::WaitForSingleObject (phandle, + blocking_period)) + { + case WAIT_OBJECT_0: + if (status != 0) + // The error status of is nonetheless + // not tested because we don't know how to return the value. + ::GetExitCodeProcess (phandle, + status); + break; + case WAIT_TIMEOUT: + errno = ETIME; + result = 0; + break; + default: + ACE_OS::set_errno_to_last_error (); + result = -1; + } + if (handle == 0) + ::CloseHandle (phandle); + return result; +#elif defined (CHORUS) + ACE_UNUSED_ARG (status); + ACE_UNUSED_ARG (wait_options); + ACE_UNUSED_ARG (handle); + ACE_OSCALL_RETURN (::await (&ACE_OS::actorcaps_[pid]), + pid_t, -1); +#else + ACE_UNUSED_ARG (handle); + ACE_OSCALL_RETURN (::waitpid (pid, status, wait_options), + pid_t, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE pid_t +ACE_OS::wait (pid_t pid, + ACE_exitcode *status, + int wait_options, + ACE_HANDLE handle) +{ + ACE_OS_TRACE ("ACE_OS::wait"); + return ACE_OS::waitpid (pid, + status, + wait_options, + handle); +} + +ACE_INLINE pid_t +ACE_OS::wait (int *status) +{ + ACE_OS_TRACE ("ACE_OS::wait"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_wait (status), pace_pid_t, -1); +#elif defined (ACE_WIN32) || defined (VXWORKS) || defined(CHORUS) || defined (ACE_PSOS) + ACE_UNUSED_ARG (status); + + ACE_NOTSUP_RETURN (0); +#else +# if defined (ACE_HAS_UNION_WAIT) + ACE_OSCALL_RETURN (::wait ((union wait *) status), pid_t, -1); +# else + ACE_OSCALL_RETURN (::wait (status), pid_t, -1); +# endif /* ACE_HAS_UNION_WAIT */ +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::ioctl (ACE_HANDLE handle, + int cmd, + void *val) +{ + ACE_OS_TRACE ("ACE_OS::ioctl"); + +#if defined (ACE_WIN32) + ACE_SOCKET sock = (ACE_SOCKET) handle; + ACE_SOCKCALL_RETURN (::ioctlsocket (sock, cmd, (u_long *) val), int, -1); +#elif defined (VXWORKS) + ACE_OSCALL_RETURN (::ioctl (handle, cmd, ACE_reinterpret_cast (int, val)), + int, -1); +#elif defined (ACE_PSOS) + ACE_OSCALL_RETURN (::ioctl (handle, cmd, (char *) val), int, -1); +#elif defined (__CYGWIN32__) + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (cmd); + ACE_UNUSED_ARG (val); + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::ioctl (handle, cmd, val), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::kill (pid_t pid, int signum) +{ + ACE_OS_TRACE ("ACE_OS::kill"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_kill (pid, signum), int, -1); +#elif defined (ACE_WIN32) || defined (CHORUS) || defined (ACE_PSOS) + ACE_UNUSED_ARG (pid); + ACE_UNUSED_ARG (signum); + ACE_NOTSUP_RETURN (-1); +#else + ACE_OSCALL_RETURN (::kill (pid, signum), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::sigaction (int signum, + const struct sigaction *nsa, + struct sigaction *osa) +{ + ACE_OS_TRACE ("ACE_OS::sigaction"); + if (signum == 0) + return 0; +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_sigaction (signum, nsa, osa), int, -1); +#elif defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) + struct sigaction sa; + + if (osa == 0) + osa = &sa; + + if (nsa == 0) + { + osa->sa_handler = ::signal (signum, SIG_IGN); + ::signal (signum, osa->sa_handler); + } + else + osa->sa_handler = ::signal (signum, nsa->sa_handler); + return osa->sa_handler == SIG_ERR ? -1 : 0; +#elif defined (CHORUS) || defined (ACE_HAS_WINCE) || defined(ACE_PSOS) + ACE_UNUSED_ARG (signum); + ACE_UNUSED_ARG (nsa); + ACE_UNUSED_ARG (osa); + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_LACKS_POSIX_PROTOTYPES) || defined (ACE_LACKS_SOME_POSIX_PROTOTYPES) + ACE_OSCALL_RETURN (::sigaction (signum, (struct sigaction*) nsa, osa), int, -1); +#else + ACE_OSCALL_RETURN (::sigaction (signum, nsa, osa), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE ACE_TCHAR * +ACE_OS::getcwd (ACE_TCHAR *buf, size_t size) +{ + ACE_OS_TRACE ("ACE_OS::getcwd"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_getcwd (buf, size), char*, 0); +#elif defined (ACE_PSOS_LACKS_PHILE) + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (size); + ACE_NOTSUP_RETURN ( (char*)-1); +#elif defined (ACE_PSOS) + + static char pathbuf [BUFSIZ]; + + // blank the path buffer + ACE_OS::memset (pathbuf, '\0', BUFSIZ); + + // the following was suggested in the documentation for get_fn () + u_long result; + char cur_dir_name [BUFSIZ] = "."; + + u_long cur_dir = 0, prev_dir = 0; + while ((ACE_OS::strlen (pathbuf) < BUFSIZ) && + (ACE_OS::strlen (cur_dir_name) < BUFSIZ - ACE_OS::strlen ("/.."))) + { + // get the current directory handle + result = ::get_fn (cur_dir_name, &cur_dir); + + // check whether we're at the root: this test is + // really lame, but the get_fn documentation says + // *either* condition indicates you're trying to + // move above the root. + if ((result != 0) || ( cur_dir == prev_dir)) + { + break; + } + + // change name to the parent directory + ACE_OS::strcat (cur_dir_name, "/.."); + + // open the parent directory + XDIR xdir; + result = ::open_dir (cur_dir_name, &xdir); + if (result != 0) + { + return 0; + } + + // look for an entry that matches the current directory handle + struct dirent dir_entry; + while (1) + { + // get the next directory entry + result = ::read_dir (&xdir, &dir_entry); + if (result != 0) + { + return 0; + } + + // check for a match + if (dir_entry.d_filno == cur_dir) + { + // prefix the previous path with the entry's name and break + if (ACE_OS::strlen (pathbuf) + ACE_OS::strlen (dir_entry.d_name) < BUFSIZ) + { + ACE_OS::strcpy (pathbuf + ACE_OS::strlen (dir_entry.d_name), pathbuf); + ACE_OS::strcpy (pathbuf, dir_entry.d_name); + break; + } + else + { + // we're out of room in the buffer + return 0; + } + } + } + + // close the parent directory + result = ::close_dir (&xdir); + if (result != 0) + { + return 0; + } + + // save the current directory handle as the previous + prev_dir = cur_dir; + } + + // return the path, if there is one + return (ACE_OS::strlen (pathbuf) > 0) ? pathbuf : (char *) 0; +#elif defined (ACE_HAS_WINCE) + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (size); + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR) + return ::_wgetcwd (buf, size); +#else + ACE_OSCALL_RETURN (::getcwd (buf, size), char *, 0); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::sleep (u_int seconds) +{ + ACE_OS_TRACE ("ACE_OS::sleep"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_sleep (seconds), int, -1); +#elif defined (ACE_WIN32) + ::Sleep (seconds * ACE_ONE_SECOND_IN_MSECS); + return 0; +#if 0 +#elif defined (HPUX_10) && defined (ACE_HAS_PTHREADS_DRAFT4) + // On HP-UX 10, _CMA_NOWRAPPERS_ disables the mapping from sleep to cma_sleep + // which makes sleep() put the whole process to sleep, and keeps it from + // noticing pending cancels. So, in this case, use pthread_delay_np + struct timespec rqtp; + rqtp.tv_sec = seconds; + rqtp.tv_nsec = 0L; + return pthread_delay_np (&rqtp); +#endif /* 0 */ +#elif defined (ACE_HAS_CLOCK_GETTIME) + struct timespec rqtp; + // Initializer doesn't work with Green Hills 1.8.7 + rqtp.tv_sec = seconds; + rqtp.tv_nsec = 0L; + ACE_OSCALL_RETURN (::nanosleep (&rqtp, 0), int, -1); +#elif defined (ACE_PSOS) + timeval wait; + wait.tv_sec = seconds; + wait.tv_usec = 0; + ACE_OSCALL_RETURN (::select (0, 0, 0, 0, &wait), int, -1); +#else + ACE_OSCALL_RETURN (::sleep (seconds), int, -1); +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::sleep (const ACE_Time_Value &tv) +{ + ACE_OS_TRACE ("ACE_OS::sleep"); +#if defined (ACE_WIN32) + ::Sleep (tv.msec ()); + return 0; +#else +# if defined (ACE_HAS_NONCONST_SELECT_TIMEVAL) + // Copy the timeval, because this platform doesn't declare the timeval + // as a pointer to const. + timeval tv_copy = tv; + ACE_OSCALL_RETURN (::select (0, 0, 0, 0, &tv_copy), int, -1); +# else /* ! ACE_HAS_NONCONST_SELECT_TIMEVAL */ + const timeval *tvp = tv; + ACE_OSCALL_RETURN (::select (0, 0, 0, 0, tvp), int, -1); +# endif /* ACE_HAS_NONCONST_SELECT_TIMEVAL */ +#endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::nanosleep (const struct timespec *requested, + struct timespec *remaining) +{ + ACE_OS_TRACE ("ACE_OS::nanosleep"); +#if defined (ACE_HAS_PACE) + return ::pace_nanosleep (requested, remaining); +#elif defined (ACE_HAS_CLOCK_GETTIME) + // ::nanosleep () is POSIX 1003.1b. So is ::clock_gettime (). So, + // if ACE_HAS_CLOCK_GETTIME is defined, then ::nanosleep () should + // be available on the platform. On Solaris 2.x, both functions + // require linking with -lposix4. + return ::nanosleep ((ACE_TIMESPEC_PTR) requested, remaining); +#elif defined (ACE_PSOS) +# if ! defined (ACE_PSOS_DIAB_MIPS) + double ticks = KC_TICKS2SEC * requested->tv_sec + + ( ACE_static_cast (double, requested->tv_nsec) * + ACE_static_cast (double, KC_TICKS2SEC) ) / + ACE_static_cast (double, ACE_ONE_SECOND_IN_NSECS); + + if (ticks > ACE_static_cast (double, ACE_PSOS_Time_t::max_ticks)) + { + ticks -= ACE_static_cast (double, ACE_PSOS_Time_t::max_ticks); + remaining->tv_sec = ACE_static_cast (time_t, + (ticks / + ACE_static_cast (double, + KC_TICKS2SEC))); + ticks -= ACE_static_cast (double, remaining->tv_sec) * + ACE_static_cast (double, KC_TICKS2SEC); + + remaining->tv_nsec = + ACE_static_cast (long, + (ticks * ACE_static_cast (double, + ACE_ONE_SECOND_IN_NSECS)) / + ACE_static_cast (double, KC_TICKS2SEC)); + + ::tm_wkafter (ACE_PSOS_Time_t::max_ticks); + } + else + { + remaining->tv_sec = 0; + remaining->tv_nsec = 0; + ::tm_wkafter (ACE_static_cast (u_long, ticks)); + } + + // tm_wkafter always returns 0 +# endif /* ACE_PSOS_DIAB_MIPS */ + return 0; +#else + ACE_UNUSED_ARG (remaining); + + // Convert into seconds and microseconds. +# if ! defined(ACE_HAS_BROKEN_TIMESPEC_MEMBERS) + ACE_Time_Value tv (requested->tv_sec, + requested->tv_nsec / 1000); +# else + ACE_Time_Value tv (requested->ts_sec, + requested->ts_nsec / 1000); +# endif /* ACE_HAS_BROKEN_TIMESPEC_MEMBERS */ + return ACE_OS::sleep (tv); +#endif /* ACE_HAS_CLOCK_GETTIME */ +} + +ACE_INLINE int +ACE_OS::mkdir (const ACE_TCHAR *path, mode_t mode) +{ +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_mkdir (path, mode), int, -1); +#elif defined (ACE_PSOS_LACKS_PHILE) + ACE_UNUSED_ARG (path); + ACE_UNUSED_ARG (mode); + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_PSOS) + //The pSOS make_dir fails if the last character is a '/' + int location; + char *phile_path; + + phile_path = (char *)ACE_OS::malloc(strlen(path)); + if (phile_path == 0) + { + ACE_OS::printf ("malloc in make_dir failed: [%X]\n", + errno); + return -1; + } + else + ACE_OS::strcpy (phile_path, path); + + location = ACE_OS::strlen(phile_path); + if(phile_path[location-1] == '/') + { + phile_path[location-1] = 0; + } + + u_long result; + result = ::make_dir ((char *) phile_path, mode); + if (result == 0x2011) // Directory already exists + { + result = 0; + } + else if (result != 0) + { + result = -1; + } + + ACE_OS::free(phile_path); + return result; + +#elif defined (VXWORKS) + ACE_UNUSED_ARG (mode); + ACE_OSCALL_RETURN (::mkdir ((char *) path), int, -1); +#elif defined (ACE_WIN32) && defined (__IBMCPP__) && (__IBMCPP__ >= 400) + ACE_UNUSED_ARG (mode); + ACE_OSCALL_RETURN (::_mkdir ((char *) path), int, -1); +#elif defined (ACE_HAS_WINCE) + ACE_UNUSED_ARG (mode); + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CreateDirectory (path, NULL), + ace_result_), + int, -1); +#elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR) + ACE_UNUSED_ARG (mode); + ACE_OSCALL_RETURN (::_wmkdir (path), int, -1); +#elif defined (ACE_WIN32) + ACE_UNUSED_ARG (mode); + ACE_OSCALL_RETURN (::mkdir (path), int, -1); +#else + ACE_OSCALL_RETURN (::mkdir (path, mode), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE char * +ACE_OS::getenv (const char *symbol) +{ + ACE_OS_TRACE ("ACE_OS::getenv"); +#if defined (ACE_LACKS_ENV) + ACE_UNUSED_ARG (symbol); + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_getenv (symbol), char*, 0); +#elif defined (ACE_PSOS) + ACE_UNUSED_ARG (symbol); + ACE_NOTSUP_RETURN (0); +#else /* ACE_PSOS */ + ACE_OSCALL_RETURN (::getenv (symbol), char *, 0); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) && defined (ACE_WIN32) +ACE_INLINE wchar_t * +ACE_OS::getenv (const wchar_t *symbol) +{ +#if defined (ACE_LACKS_ENV) + ACE_UNUSED_ARG (symbol); + ACE_NOTSUP_RETURN (0); +#else + ACE_OSCALL_RETURN (::_wgetenv (symbol), wchar_t *, 0); +#endif /* ACE_LACKS_ENV */ +} +#endif /* ACE_HAS_WCHAR && ACE_WIN32 */ + +ACE_INLINE int +ACE_OS::putenv (const ACE_TCHAR *string) +{ + ACE_OS_TRACE ("ACE_OS::putenv"); +#if defined (ACE_LACKS_ENV) + ACE_UNUSED_ARG (string); + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_WINCE) || defined (ACE_PSOS) + // WinCE and pSOS don't have the concept of environment variables. + ACE_UNUSED_ARG (string); + ACE_NOTSUP_RETURN (-1); +#elif defined (ACE_WIN32) && defined (ACE_USES_WCHAR) + ACE_OSCALL_RETURN (::_wputenv (string), int, -1); +#else /* ! ACE_HAS_WINCE && ! ACE_PSOS */ + // VxWorks declares ::putenv with a non-const arg. + ACE_OSCALL_RETURN (::putenv ((char *) string), int, -1); +#endif /* ACE_HAS_WINCE */ +} + +ACE_INLINE +ACE_Str_Buf::ACE_Str_Buf (void *b, int l, int max) +{ + this->maxlen = max; + this->len = l; + this->buf = (char *) b; +} + +ACE_INLINE +ACE_Str_Buf::ACE_Str_Buf (strbuf &sb) +{ + this->maxlen = sb.maxlen; + this->len = sb.len; + this->buf = sb.buf; +} + +ACE_INLINE u_int +ACE_OS::wslen (const WChar *s) +{ + u_int len = 0; + + while (*s++ != 0) + len++; + + return len; +} + +ACE_INLINE ACE_OS::WChar * +ACE_OS::wscpy (WChar *dest, const WChar *src) +{ + WChar *original_dest = dest; + + while ((*dest++ = *src++) != 0) + continue; + + return original_dest; +} + +ACE_INLINE int +ACE_OS::wscmp (const WChar *s, const WChar *t) +{ + const WChar *scan1 = s; + const WChar *scan2 = t; + + while (*scan1 != 0 && *scan1 == *scan2) + { + ++scan1; + ++scan2; + } + + return *scan1 - *scan2; +} + +ACE_INLINE int +ACE_OS::wsncmp (const WChar *s, const WChar *t, size_t len) +{ + const WChar *scan1 = s; + const WChar *scan2 = t; + + while (len != 0 && *scan1 != 0 && *scan1 == *scan2) + { + ++scan1; + ++scan2; + --len; + } + + return len == 0 ? 0 : *scan1 - *scan2; +} + +#if defined (ACE_LACKS_COND_T) && defined (ACE_HAS_THREADS) && (!defined (ACE_HAS_PACE) || defined (ACE_WIN32)) +ACE_INLINE long +ACE_cond_t::waiters (void) const +{ + return this->waiters_; +} +#endif /* ACE_LACKS_COND_T && ACE_HAS_THREADS && ! ACE_HAS_PACE */ + +#if 0 +ACE_INLINE int +ACE_OS::thr_continue (const ACE_Thread_ID &thr_id) +{ + ACE_OS_TRACE ("ACE_OS::thr_continue"); + return ACE_OS::thr_continue (thr_id.id ()); +} + +ACE_INLINE int +ACE_OS::thr_create (ACE_THR_FUNC func, + void *args, + long flags, + ACE_Thread_ID *thr_id, + long priority, + void *stack, + size_t stacksize); +{ + ACE_OS_TRACE ("ACE_OS::thr_create"); + ACE_thread_t thread_id; + ACE_hthread_t thread_handle; + + int result = ACE_OS::thr_create (func, args, flags, + &thread_id, &thread_handle, + priority, stack, stacksize); + if (result == -1) + return -1; + else if (thr_id != 0) + { + thr_id->id (thread_id); + thr_id->handle (thread_handle); + return result; + } +} + +ACE_INLINE int +ACE_OS::thr_getprio (const ACE_Thread_ID &thr_id, int &prio) +{ + ACE_OS_TRACE ("ACE_OS::thr_getprio"); + return ACE_OS::thr_getprio (thr_id.handle (), prio); +} + +ACE_INLINE int +ACE_OS::thr_join (const ACE_Thread_ID &thr_id, void **status) +{ +# if defined (ACE_WIN32) + return ACE_OS::thr_join (thr_id.handle (), status); +# else + return ACE_OS::thr_join (thr_id.id (), status); +# endif /* ACE_WIN32 */ +} + +ACE_INLINE int +ACE_OS::thr_cancel (const ACE_Thread_ID &thr_id) +{ + return ACE_OS::thr_cancel (thr_id.id ()); +} + +ACE_INLINE int +ACE_OS::thr_kill (const ACE_Thread_ID &thr_id, int signum) +{ + return ACE_OS::thr_kill (thr_id.id (), signum); +} + +ACE_INLINE ACE_Thread_ID +ACE_OS::thr_self (void) +{ + ACE_hthread_t thr_handle; + ACE_OS::thr_self (thr_handle); + ACE_thread_t thr_id = ACE_OS::thr_self (); + + return ACE_Thread_ID (thr_id, thr_handle); +} + +ACE_INLINE int +ACE_OS::thr_setprio (const ACE_Thread_ID &thr_id, int prio) +{ + ACE_OS_TRACE ("ACE_OS::thr_setprio"); + return ACE_OS::thr_setprio (thr_id.handle (), prio); +} + +ACE_INLINE int +ACE_OS::thr_suspend (const ACE_Thread_ID &thr_id) +{ + return ACE_OS::thr_suspend (thr_id.handle ()); +} + +#endif /* 0 */ + +ACE_INLINE int +ACE_OS::sigaddset (sigset_t *s, int signum) +{ + ACE_OS_TRACE ("ACE_OS::sigaddset"); +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_sigaddset (s, signum), int, -1); +#elif defined (ACE_LACKS_SIGSET) || defined (ACE_LACKS_SIGSET_DEFINITIONS) + if (s == NULL) + { + errno = EFAULT; + return -1; + } + else if (signum < 1 || signum >= ACE_NSIG) + { + errno = EINVAL; + return -1; // Invalid signum, return error + } +# if defined (ACE_PSOS) && defined (__DIAB) && ! defined(ACE_PSOS_DIAB_MIPS) && !defined (ACE_PSOS_DIAB_PPC) + // treat 0th u_long of sigset_t as high bits, + // and 1st u_long of sigset_t as low bits. + if (signum <= ACE_BITS_PER_ULONG) + s->s[1] |= (1 << (signum - 1)); + else + s->s[0] |= (1 << (signum - ACE_BITS_PER_ULONG - 1)); +# else + *s |= (1 << (signum - 1)) ; +# endif /* defined (ACE_PSOS) && defined (__DIAB) */ + return 0 ; +#else + ACE_OSCALL_RETURN (::sigaddset (s, signum), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::sigdelset (sigset_t *s, int signum) +{ +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_sigdelset (s, signum), int, -1); +#elif defined (ACE_LACKS_SIGSET) || defined (ACE_LACKS_SIGSET_DEFINITIONS) + if (s == NULL) + { + errno = EFAULT; + return -1; + } + else if (signum < 1 || signum >= ACE_NSIG) + { + errno = EINVAL; + return -1; // Invalid signum, return error + } +# if defined (ACE_PSOS) && defined (__DIAB) && ! defined (ACE_PSOS_DIAB_MIPS) && !defined (ACE_PSOS_DIAB_PPC) + // treat 0th u_long of sigset_t as high bits, + // and 1st u_long of sigset_t as low bits. + if (signum <= ACE_BITS_PER_ULONG) + s->s[1] &= ~(1 << (signum - 1)); + else + s->s[0] &= ~(1 << (signum - ACE_BITS_PER_ULONG - 1)); +# else + *s &= ~(1 << (signum - 1)) ; +# endif /* defined (ACE_PSOS) && defined (__DIAB) */ + return 0; +#else + ACE_OSCALL_RETURN (::sigdelset (s, signum), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::sigemptyset (sigset_t *s) +{ +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_sigemptyset (s), int, -1); +#elif defined (ACE_LACKS_SIGSET) || defined (ACE_LACKS_SIGSET_DEFINITIONS) + if (s == NULL) + { + errno = EFAULT; + return -1; + } +# if defined (ACE_PSOS) && defined (__DIAB) && ! defined (ACE_PSOS_DIAB_MIPS) && !defined (ACE_PSOS_DIAB_PPC) + s->s[0] = 0; + s->s[1] = 0; +# else + *s = 0 ; +# endif /* defined (ACE_PSOS) && defined (__DIAB) */ + return 0 ; +#else + ACE_OSCALL_RETURN (::sigemptyset (s), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::sigfillset (sigset_t *s) +{ +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_sigfillset (s), int, -1); +#elif defined (ACE_LACKS_SIGSET) || defined (ACE_LACKS_SIGSET_DEFINITIONS) + if (s == NULL) + { + errno = EFAULT; + return -1; + } +# if defined (ACE_PSOS) && defined (__DIAB) && ! defined (ACE_PSOS_DIAB_MIPS) && !defined (ACE_PSOS_DIAB_PPC) + s->s[0] = ~(u_long) 0; + s->s[1] = ~(u_long) 0; +# else + *s = ~(sigset_t) 0; +# endif /* defined (ACE_PSOS) && defined (__DIAB) */ + return 0 ; +#else + ACE_OSCALL_RETURN (::sigfillset (s), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::sigismember (sigset_t *s, int signum) +{ +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_sigismember (s, signum), int, -1); +#elif defined (ACE_LACKS_SIGSET) || defined (ACE_LACKS_SIGSET_DEFINITIONS) + if (s == NULL) + { + errno = EFAULT; + return -1; + } + else if (signum < 1 || signum >= ACE_NSIG) + { + errno = EINVAL; + return -1; // Invalid signum, return error + } +# if defined (ACE_PSOS) && defined (__DIAB) && ! defined (ACE_PSOS_DIAB_MIPS) && !defined (ACE_PSOS_DIAB_PPC) + // treat 0th u_long of sigset_t as high bits, + // and 1st u_long of sigset_t as low bits. + if (signum <= ACE_BITS_PER_ULONG) + return ((s->s[1] & (1 << (signum - 1))) != 0); + else + return ((s->s[0] & (1 << (signum - ACE_BITS_PER_ULONG - 1))) != 0); +# else + return ((*s & (1 << (signum - 1))) != 0) ; +# endif /* defined (ACE_PSOS) && defined (__DIAB) */ +#else +# if defined (ACE_HAS_SIGISMEMBER_BUG) + if (signum < 1 || signum >= ACE_NSIG) + { + errno = EINVAL; + return -1; // Invalid signum, return error + } +# endif /* ACE_HAS_SIGISMEMBER_BUG */ + ACE_OSCALL_RETURN (::sigismember (s, signum), int, -1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::sigsuspend (const sigset_t *sigset) +{ +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_sigsuspend (sigset), int, -1); +#elif defined (ACE_HAS_SIGSUSPEND) + sigset_t s; + + if (sigset == 0) + { + sigset = &s; + ACE_OS::sigemptyset (&s); + } + ACE_OSCALL_RETURN (::sigsuspend (sigset), int, -1); +#else + ACE_UNUSED_ARG (sigset); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::sigprocmask (int how, const sigset_t *nsp, sigset_t *osp) +{ +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (::pace_sigprocmask (how, nsp, osp), int, -1); +#elif defined (ACE_LACKS_SIGSET) || defined (ACE_LACKS_SIGSET_DEFINITIONS) + ACE_UNUSED_ARG (how); + ACE_UNUSED_ARG (nsp); + ACE_UNUSED_ARG (osp); + ACE_NOTSUP_RETURN (-1); +#else +# if defined (ACE_LACKS_POSIX_PROTOTYPES) + ACE_OSCALL_RETURN (::sigprocmask (how, (int*) nsp, osp), int, -1); +# else + ACE_OSCALL_RETURN (::sigprocmask (how, nsp, osp), int, -1); +# endif /* ACE_LACKS_POSIX_PROTOTYPES */ +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::pthread_sigmask (int how, const sigset_t *nsp, sigset_t *osp) +{ +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pace_pthread_sigmask (how, nsp, osp), + ace_result_), int, -1); +#elif defined (ACE_HAS_PTHREADS_STD) && !defined (ACE_LACKS_PTHREAD_SIGMASK) + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_sigmask (how, nsp, osp), + ace_result_), + int, + -1); +#else /* !ACE_HAS_PTHREADS_STD */ + ACE_UNUSED_ARG (how); + ACE_UNUSED_ARG (nsp); + ACE_UNUSED_ARG (osp); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PACE */ +} + +// **************************************************************** + +#if defined (ACE_PSOS) +ACE_INLINE int +isatty (int h) +{ + return ACE_OS::isatty (h); +} +#if defined (fileno) +#undef fileno +#endif /* defined (fileno)*/ +ACE_INLINE ACE_HANDLE +fileno (FILE *fp) +{ + return (ACE_HANDLE) fp; +} +#endif /* defined (ACE_PSOS) */ + +ACE_INLINE +ACE_Cleanup::ACE_Cleanup (void) +{ +} + +ACE_INLINE void * +ACE_OS::bsearch (const void *key, + const void *base, + size_t nel, + size_t size, + ACE_COMPARE_FUNC compar) +{ +#if defined (ACE_HAS_PACE) + return ::pace_bsearch (key, base, nel, size, compar); +#elif !defined (ACE_LACKS_BSEARCH) + return ::bsearch (key, base, nel, size, compar); +#else + ACE_UNUSED_ARG (key); + ACE_UNUSED_ARG (base); + ACE_UNUSED_ARG (nel); + ACE_UNUSED_ARG (size); + ACE_UNUSED_ARG (compar); + ACE_NOTSUP_RETURN (NULL); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE void +ACE_OS::qsort (void *base, + size_t nel, + size_t width, + ACE_COMPARE_FUNC compar) +{ +#if defined (ACE_HAS_PACE) + ::pace_qsort (base, nel, width, compar); +#elif !defined (ACE_LACKS_QSORT) + ::qsort (base, nel, width, compar); +#else + ACE_UNUSED_ARG (base); + ACE_UNUSED_ARG (nel); + ACE_UNUSED_ARG (width); + ACE_UNUSED_ARG (compar); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::setuid (uid_t uid) +{ + ACE_OS_TRACE ("ACE_OS::setuid"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_setuid (uid), int, -1); +# elif defined (VXWORKS) || defined (ACE_PSOS) + // setuid() is not supported: just one user anyways + ACE_UNUSED_ARG (uid); + return 0; +# elif defined (ACE_WIN32) || defined(CHORUS) + ACE_UNUSED_ARG (uid); + ACE_NOTSUP_RETURN (-1); +# else + ACE_OSCALL_RETURN (::setuid (uid), int, -1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE uid_t +ACE_OS::getuid (void) +{ + ACE_OS_TRACE ("ACE_OS::getuid"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_getuid (), pace_uid_t, (pace_uid_t) -1); +# elif defined (VXWORKS) || defined (ACE_PSOS) + // getuid() is not supported: just one user anyways + return 0; +# elif defined (ACE_WIN32) || defined(CHORUS) + ACE_NOTSUP_RETURN (ACE_static_cast (uid_t, -1)); +# else + ACE_OSCALL_RETURN (::getuid (), uid_t, (uid_t) -1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS::setgid (gid_t gid) +{ + ACE_OS_TRACE ("ACE_OS::setgid"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_setgid (gid), int, -1); +# elif defined (VXWORKS) || defined (ACE_PSOS) + // setgid() is not supported: just one user anyways + ACE_UNUSED_ARG (gid); + return 0; +# elif defined (ACE_WIN32) || defined(CHORUS) + ACE_UNUSED_ARG (gid); + ACE_NOTSUP_RETURN (-1); +# else + ACE_OSCALL_RETURN (::setgid (gid), int, -1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE gid_t +ACE_OS::getgid (void) +{ + ACE_OS_TRACE ("ACE_OS::getgid"); +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_getgid (), pace_gid_t, (pace_gid_t) -1); +# elif defined (VXWORKS) || defined (ACE_PSOS) + // getgid() is not supported: just one user anyways + return 0; +# elif defined (ACE_WIN32) || defined(CHORUS) + ACE_NOTSUP_RETURN (ACE_static_cast (gid_t, -1)); +# else + ACE_OSCALL_RETURN (::getgid (), gid_t, (gid_t) -1); +# endif /* ACE_HAS_PACE */ +} + +ACE_INLINE ACE_EXIT_HOOK +ACE_OS::set_exit_hook (ACE_EXIT_HOOK exit_hook) +{ + ACE_EXIT_HOOK old_hook = exit_hook_; + exit_hook_ = exit_hook; + return old_hook; +} + +ACE_INLINE int +ACE_OS::isatty (int handle) +{ +#if defined (ACE_HAS_PACE) + ACE_OSCALL_RETURN (::pace_isatty (handle), int, -1); +# elif defined (ACE_LACKS_ISATTY) + ACE_UNUSED_ARG (handle); + return 0; +# elif defined (ACE_WIN32) + ACE_OS_TRACE ("ACE_OS::isatty"); + return ::_isatty (handle); +# else + ACE_OS_TRACE ("ACE_OS::isatty"); + ACE_OSCALL_RETURN (::isatty (handle), int, -1); +# endif /* defined (ACE_LACKS_ISATTY) */ +} + +#if defined (ACE_WIN32) +ACE_INLINE int +ACE_OS::isatty (ACE_HANDLE handle) +{ +#if defined (ACE_LACKS_ISATTY) + ACE_UNUSED_ARG (handle); + return 0; +#else + int fd = ::_open_osfhandle ((long) handle, 0); + return ::_isatty (fd); +#endif /* ACE_LACKS_ISATTY */ +} + +ACE_INLINE void +ACE_OS::fopen_mode_to_open_mode_converter (ACE_TCHAR x, int &hmode) +{ + switch (x) + { + case ACE_LIB_TEXT ('r'): + if (ACE_BIT_DISABLED (hmode, _O_RDWR)) + { + ACE_CLR_BITS (hmode, _O_WRONLY); + ACE_SET_BITS (hmode, _O_RDONLY); + } + break; + case ACE_LIB_TEXT ('w'): + if (ACE_BIT_DISABLED (hmode, _O_RDWR)) + { + ACE_CLR_BITS (hmode, _O_RDONLY); + ACE_SET_BITS (hmode, _O_WRONLY); + } + ACE_SET_BITS (hmode, _O_CREAT | _O_TRUNC); + break; + case ACE_LIB_TEXT ('a'): + if (ACE_BIT_DISABLED (hmode, _O_RDWR)) + { + ACE_CLR_BITS (hmode, _O_RDONLY); + ACE_SET_BITS (hmode, _O_WRONLY); + } + ACE_SET_BITS (hmode, _O_CREAT | _O_APPEND); + break; + case ACE_LIB_TEXT ('+'): + ACE_CLR_BITS (hmode, _O_RDONLY | _O_WRONLY); + ACE_SET_BITS (hmode, _O_RDWR); + break; + case ACE_LIB_TEXT ('t'): + ACE_CLR_BITS (hmode, _O_BINARY); + ACE_SET_BITS (hmode, _O_TEXT); + break; + case ACE_LIB_TEXT ('b'): + ACE_CLR_BITS (hmode, _O_TEXT); + ACE_SET_BITS (hmode, _O_BINARY); + break; + } +} +#endif /* ACE_WIN32 */ + +// Return a dynamically allocated duplicate of , substituting the +// environment variable if . Note that the pointer is +// allocated with and must be freed by +// . + +ACE_INLINE ACE_TCHAR * +ACE_OS::strenvdup (const ACE_TCHAR *str) +{ +# if defined (ACE_LACKS_ENV) + ACE_UNUSED_ARG (str); + ACE_NOTSUP_RETURN (0); +#elif defined (ACE_HAS_WINCE) + // WinCE doesn't have environment variables so we just skip it. + return ACE_OS::strdup (str); +#else + ACE_TCHAR *temp = 0; + + if (str[0] == ACE_LIB_TEXT ('$') + && (temp = ACE_OS::getenv (&str[1])) != 0) + return ACE_OS::strdup (temp); + else + return ACE_OS::strdup (str); +#endif /* ACE_HAS_WINCE */ +} + +ACE_INLINE int +ACE_Countdown_Time::start (void) +{ + if (this->max_wait_time_ != 0) + { + this->start_time_ = ACE_OS::gettimeofday (); + this->stopped_ = 0; + } + return 0; +} + +ACE_INLINE int +ACE_Countdown_Time::stop (void) +{ + if (this->max_wait_time_ != 0 && this->stopped_ == 0) + { + ACE_Time_Value elapsed_time = + ACE_OS::gettimeofday () - this->start_time_; + + if (*this->max_wait_time_ > elapsed_time) + *this->max_wait_time_ -= elapsed_time; + else + { + // Used all of timeout. + *this->max_wait_time_ = ACE_Time_Value::zero; + // errno = ETIME; + } + this->stopped_ = 1; + } + return 0; +} + +ACE_INLINE int +ACE_Countdown_Time::update (void) +{ + return this->stop () == 0 && this->start (); +} + +#if defined (ACE_WIN32) +ACE_INLINE const OSVERSIONINFO & +ACE_OS::get_win32_versioninfo () +{ + return ACE_OS::win32_versioninfo_; +} + +ACE_INLINE HINSTANCE +ACE_OS::get_win32_resource_module () +{ + return ACE_OS::win32_resource_module_; +} + +ACE_INLINE void +ACE_OS::set_win32_resource_module (HINSTANCE instance) +{ + ACE_OS::win32_resource_module_ = instance; +} +#endif /* ACE_WIN32 */ diff --git a/ace/OS/OS_Dirent.cpp b/ace/OS/OS_Dirent.cpp new file mode 100644 index 00000000000..a14966fc7b3 --- /dev/null +++ b/ace/OS/OS_Dirent.cpp @@ -0,0 +1,235 @@ +// $Id$ + +#include "OS.h" +#include "OS_Dirent.h" +#include "OS_String.h" +#include "OS_Memory.h" + +#if 0 +#include "ace/Logging/Log_Msg.h" +#endif + +ACE_RCSID(ace, OS_Dirent, "$Id$") + +#if !defined (ACE_HAS_INLINED_OSCALLS) +# include "OS_Dirent.inl" +#endif /* ACE_HAS_INLINED_OS_CALLS */ + +ACE_DIR * +ACE_OS_Dirent::opendir_emulation (const ACE_TCHAR *filename) +{ +#if defined (ACE_WIN32) + ACE_DIR *dir; + ACE_TCHAR extra[3] = {0,0,0}; + +/* + Note: the semantics of the win32 function FindFirstFile take the + basename(filename) as a pattern to be matched within the dirname(filename). + This is contrary to the behavior of the posix function readdir which treats + basename(filename) as a directory to be opened and read. + + For this reason, we append a slash-star or backslash-star to the supplied + filename so the result is that FindFirstFile will do what we need. + + According to the documentation for FindFirstFile, either a '/' or a '\' may + be used as a directory name separator. + + Of course, it is necessary to ensure that this is only done if the trailing + filespec is not already there. + + Phil Mesnier +*/ + + size_t lastchar = ACE_OS_String::strlen (filename); + if (lastchar > 0) + { + if (filename[lastchar-1] != '*') + { + if (filename[lastchar-1] != '/' && filename[lastchar-1] != '\\') + ACE_OS_String::strcpy (extra, ACE_LIB_TEXT ("/*")); + else + ACE_OS_String::strcpy (extra, ACE_LIB_TEXT ("*")); + } + } + + ACE_NEW_RETURN (dir, ACE_DIR, 0); + ACE_NEW_RETURN (dir->directory_name_, + ACE_TCHAR[lastchar + ACE_OS_String::strlen (extra) + 1], + 0); + ACE_OS_String::strcpy (dir->directory_name_, filename); + if (extra[0]) + ACE_OS_String::strcat (dir->directory_name_, extra); + dir->current_handle_ = INVALID_HANDLE_VALUE; + dir->started_reading_ = 0; + dir->dirent_ = 0; + return dir; +#else /* ACE_WIN32 */ + ACE_UNUSED_ARG (filename); + ACE_NOTSUP_RETURN (0); +#endif /* ACE_WIN32 */ +} + +void +ACE_OS_Dirent::closedir_emulation (ACE_DIR *d) +{ +#if defined (ACE_WIN32) + if (d->current_handle_ != INVALID_HANDLE_VALUE) + ::FindClose (d->current_handle_); + + d->current_handle_ = INVALID_HANDLE_VALUE; + d->started_reading_ = 0; + ACE_OS_Memory::free (d->dirent_); +#else /* ACE_WIN32 */ + ACE_UNUSED_ARG (d); +#endif /* ACE_WIN32 */ +} + +dirent * +ACE_OS_Dirent::readdir_emulation (ACE_DIR *d) +{ +#if defined (ACE_WIN32) + ACE_OS_Memory::free (d->dirent_); + d->dirent_ = 0; + + if (!d->started_reading_) + { + d->current_handle_ = ACE_TEXT_FindFirstFile (d->directory_name_, + &(d->fdata_)); + + if (d->current_handle_ != INVALID_HANDLE_VALUE) + { + // Skip "." and ".." + int retval = 1; + while (*d->fdata_.cFileName == '.' + && retval + && d->fdata_.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) + retval = ACE_TEXT_FindNextFile (d->current_handle_, &d->fdata_); + if (retval == 0) + { + ::FindClose (d->current_handle_); + d->current_handle_ = INVALID_HANDLE_VALUE; + } + } + + d->started_reading_ = 1; + } + else + { + int retval = ACE_TEXT_FindNextFile (d->current_handle_, + &(d->fdata_)); + if (retval == 0) + { + // Make sure to close the handle explicitly to avoid a leak! + ::FindClose (d->current_handle_); + d->current_handle_ = INVALID_HANDLE_VALUE; + } + } + + if (d->current_handle_ != INVALID_HANDLE_VALUE) + { + d->dirent_ = (dirent *) + ACE_OS_Memory::malloc (sizeof (dirent) + + ((ACE_OS_String::strlen (d->fdata_.cFileName) + 1 + * sizeof (ACE_TCHAR)))); + ACE_OS_String::strcpy (d->dirent_->d_name, d->fdata_.cFileName); + d->dirent_->d_reclen = sizeof (dirent) + + (ACE_OS_String::strlen (d->dirent_->d_name) * sizeof (ACE_TCHAR)); + return d->dirent_; + } + else + return 0; +#else /* ACE_WIN32 */ + ACE_UNUSED_ARG (d); + ACE_NOTSUP_RETURN (0); +#endif /* ACE_WIN32 */ +} + +extern "C" +{ + typedef int (*ACE_SCANDIR_COMPARATOR) (const void *, const void *); +} + +int +ACE_OS_Dirent::scandir_emulation (const ACE_TCHAR *dirname, + dirent **namelist[], + int (*selector) (const dirent *entry), + int (*comparator) (const dirent **f1, + const dirent **f2)) +{ + ACE_DIR *dirp = ACE_OS_Dirent::opendir (dirname); + + if (dirp == 0) + return -1; + // A sanity check here. "namelist" had better not be zero. + else if (namelist == 0) + return -1; + + dirent **vector = 0; + dirent *dp; + int arena_size = 0; + + int nfiles = 0; + int fail = 0; + + // @@ This code shoulduse readdir_r() rather than readdir(). + for (dp = ACE_OS_Dirent::readdir (dirp); + dp != 0; + dp = ACE_OS_Dirent::readdir (dirp)) + { + if (selector && (*selector)(dp) == 0) + continue; + + // If we get here, we have a dirent that the user likes. + if (nfiles == arena_size) + { + dirent **newv; + if (arena_size == 0) + arena_size = 10; + else + arena_size *= 2; + + newv = (dirent **) ACE_OS_Memory::realloc (vector, + arena_size * sizeof (dirent *)); + if (newv == 0) + { + fail = 1; + break; + } + vector = newv; + } + + int dsize = + sizeof (dirent) + + ((ACE_OS_String::strlen (dp->d_name) + 1) * sizeof (ACE_TCHAR)); + dirent *newdp = (dirent *) ACE_OS_Memory::malloc (dsize); + + if (newdp == 0) + { + fail = 1; + break; + } + + vector[nfiles++] = (dirent *) ACE_OS_String::memcpy (newdp, dp, dsize); + } + + if (fail) + { + ACE_OS_Dirent::closedir (dirp); + while (nfiles-- > 0) + ACE_OS_Memory::free (vector[nfiles]); + ACE_OS_Memory::free (vector); + return -1; + } + + ACE_OS_Dirent::closedir (dirp); + + *namelist = vector; + + if (comparator) + ACE_OS::qsort (*namelist, + nfiles, + sizeof (dirent *), + (ACE_SCANDIR_COMPARATOR) comparator); + + return nfiles; +} diff --git a/ace/OS/OS_Dirent.h b/ace/OS/OS_Dirent.h new file mode 100644 index 00000000000..e4c257e6111 --- /dev/null +++ b/ace/OS/OS_Dirent.h @@ -0,0 +1,130 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file OS_Dirent.h + * + * $Id$ + * + * @author Doug Schmidt + * @author Jesper S. M|ller + * @author and a cast of thousands... + */ +//============================================================================= + +#ifndef ACE_OS_DIRENT_H +#define ACE_OS_DIRENT_H +#include "ace/pre.h" + +#include "ace/config-all.h" +#include "OS_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#if !defined (ACE_WIN32) && !defined (ACE_PSOS) && !defined (ACE_HAS_WINCE) +# include /**/ +# if !defined (ACE_LACKS_UNISTD_H) +# include /**/ // VxWorks needs this to compile +# endif /* !ACE_LACKS_UNISTD_H */ +# include /**/ +#endif /* !ACE_WIN32 && !ACE_PSOS */ + +// At least compile on some of the platforms without info yet. +# if !defined (ACE_HAS_DIRENT) +typedef int ACE_DIR; +struct dirent { +}; +# endif /* ACE_HAS_DIRENT */ + +#if defined (ACE_LACKS_STRUCT_DIR) +struct dirent { + unsigned short d_ino; + unsigned short d_off; + unsigned short d_reclen; + ACE_TCHAR d_name[1]; +}; + +struct ACE_DIR { + /// The name of the directory we are looking into + ACE_TCHAR *directory_name_; + + /// Remember the handle between calls. + HANDLE current_handle_; + + /// The struct for the results + dirent *dirent_; + + /// The struct for intermediate results. + ACE_TEXT_WIN32_FIND_DATA fdata_; + + /// A flag to remember if we started reading already. + int started_reading_; +}; +#elif defined (ACE_PSOS) && !defined (ACE_PSOS_DIAB_PPC) +// Create our own definition of the DIR struct, like what +// is available in the newer DIAB PPC header files +struct ACE_DIR +{ + /// The directory handle + XDIR xdir; + + /// The directory entry + struct dirent dirent; +}; +#else +typedef DIR ACE_DIR; +# endif /* ACE_LACKS_STRUCT_DIR */ + +#if defined rewinddir +# undef rewinddir +#endif /* rewinddir */ + +/** + * @class ACE_OS_Dirent + * + * @brief This class is a wrapper for the dirent.h operations + * + */ +class ACE_OS_Export ACE_OS_Dirent +{ +public: + static ACE_DIR *opendir (const ACE_TCHAR *filename); + static void closedir (ACE_DIR *); + static dirent *readdir (ACE_DIR *); + static int readdir_r (ACE_DIR *dirp, + dirent *entry, + dirent **result); + static long telldir (ACE_DIR *); + static void seekdir (ACE_DIR *, + long loc); + static void rewinddir (ACE_DIR *); + + static int scandir (const ACE_TCHAR *dirname, + dirent **namelist[], + int (*selector) (const dirent *filename), + int (*comparator) (const dirent **f1, + const dirent **f2)); +private: + // Win32 emulation functions + static ACE_DIR *opendir_emulation (const ACE_TCHAR *filename); + static int scandir_emulation (const ACE_TCHAR *dirname, + dirent **namelist[], + int (*selector)(const dirent *entry), + int (*comparator)(const dirent **f1, + const dirent**f2)); + static void closedir_emulation (ACE_DIR *); + static dirent *readdir_emulation (ACE_DIR *); +}; + +# if defined (ACE_HAS_INLINED_OSCALLS) +# if defined (ACE_INLINE) +# undef ACE_INLINE +# endif /* ACE_INLINE */ +# define ACE_INLINE inline +# include "OS_Dirent.inl" +# endif /* ACE_HAS_INLINED_OSCALLS */ + +#include "ace/post.h" +#endif /* ACE_OS_DIRENT_H */ diff --git a/ace/OS/OS_Dirent.inl b/ace/OS/OS_Dirent.inl new file mode 100644 index 00000000000..e6ab9dc82e1 --- /dev/null +++ b/ace/OS/OS_Dirent.inl @@ -0,0 +1,201 @@ +// -*- C++ -*- +// $Id$ + +#if defined (ACE_HAS_PACE) +#include /**/ "pace/dirent.h" +#endif /* ACE_HAS_PACE */ +ACE_INLINE ACE_DIR * +ACE_OS_Dirent::opendir (const ACE_TCHAR *filename) +{ +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + return pace_opendir (filename); +#elif defined (ACE_HAS_DIRENT) +# if defined (ACE_PSOS) + // The pointer to the buffer *must* be passed to + // to free it and avoid a memory leak. + ACE_DIR *dir; + u_long result; + ACE_NEW_RETURN (dir, ACE_DIR, 0); + result = ::open_dir (ACE_const_cast (ACE_TCHAR *, + filename), + &dir->xdir); + if (result == 0) + return dir; + else + { + errno = result; + return 0; + } +# else /* ! ACE_PSOS */ +# if defined (ACE_WIN32) + return ::ACE_OS_Dirent::opendir_emulation (filename); +# else /* ! ACE_WIN32 */ + // VxWorks' ::opendir () is declared with a non-const argument. + return ::opendir (ACE_const_cast (ACE_TCHAR *, filename)); +# endif /* ACE_WIN32 */ +# endif /* ACE_PSOS */ +#else + ACE_UNUSED_ARG (filename); + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE void +ACE_OS_Dirent::closedir (ACE_DIR *d) +{ +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + pace_closedir (d); +#elif defined (ACE_HAS_DIRENT) +# if defined (ACE_PSOS) + + u_long result = ::close_dir (&(d->xdir)); + delete d; + if (result != 0) + errno = result; + +# else /* ! ACE_PSOS */ + +# if defined (ACE_WIN32) + ACE_OS_Dirent::closedir_emulation (d); + delete [] d->directory_name_; + delete d; +# else /* ACE_WIN32 */ + ::closedir (d); +# endif /* ACE_WIN32 */ + +# endif /* ACE_PSOS */ +#else /* ACE_HAS_DIRENT */ + ACE_UNUSED_ARG (d); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE struct dirent * +ACE_OS_Dirent::readdir (ACE_DIR *d) +{ +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + return pace_readdir (d); +#elif defined (ACE_HAS_DIRENT) +# if defined (ACE_PSOS) + + u_long result = ::read_dir (&d->xdir, &d->dirent); + if (0 == result) + return &d->dirent; + else + { + errno = result; + return 0; + } + +# else /* ! ACE_PSOS */ +# if defined (ACE_WIN32) + return ACE_OS_Dirent::readdir_emulation (d); +# else /* defined (ACE_WIN32) */ + return ::readdir (d); +# endif /* defined (ACE_WIN32) */ +# endif /* ACE_PSOS */ +#else + ACE_UNUSED_ARG (d); + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS_Dirent::readdir_r (ACE_DIR *dirp, + struct dirent *entry, + struct dirent **result) +{ +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + return pace_readdir_r (dirp, entry, result); +# elif !defined (ACE_HAS_REENTRANT_FUNCTIONS) + ACE_UNUSED_ARG (entry); + // has better not be 0! + *result = ACE_OS_Dirent::readdir (dirp); + return 0; +# elif defined (ACE_HAS_DIRENT) && !defined (ACE_LACKS_READDIR_R) +# if (defined (sun) && (defined (_POSIX_PTHREAD_SEMANTICS) || \ + (_FILE_OFFSET_BITS == 64))) || \ + (!defined (sun) && (defined (ACE_HAS_PTHREADS_STD) || \ + defined (ACE_HAS_PTHREADS_DRAFT7) || \ + defined (__USE_POSIX) || \ + defined (HPUX_11))) +# if defined (__GNUG__) && defined (DIGITAL_UNIX) + return readdir_r (dirp, entry, result); +# else + return ::readdir_r (dirp, entry, result); +# endif /* defined (__GNUG__) && defined (DIGITAL_UNIX) */ +# else /* ! POSIX.1c - this is draft 4 or draft 6 */ +# if defined (HPUX_10) /* But HP 10.x doesn't follow the draft either */ + *result = entry; + return ::readdir_r (dirp, entry); +# else + // had better not be 0! + *result = ::readdir_r (dirp, entry); + return 0; +# endif /* HPUX_10 */ +# endif /* ! POSIX.1c */ +#else /* ! ACE_HAS_DIRENT || ACE_LACKS_READDIR_R */ + ACE_UNUSED_ARG (dirp); + ACE_UNUSED_ARG (entry); + ACE_UNUSED_ARG (result); + ACE_NOTSUP_RETURN (0); + +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE long +ACE_OS_Dirent::telldir (ACE_DIR *d) +{ +#if defined (ACE_HAS_DIRENT) && !defined (ACE_LACKS_TELLDIR) + return ::telldir (d); +#else /* ! ACE_HAS_DIRENT || ACE_LACKS_TELLDIR */ + ACE_UNUSED_ARG (d); + ACE_NOTSUP_RETURN (-1); +#endif /* ! ACE_HAS_DIRENT || ACE_LACKS_TELLDIR */ +} + +ACE_INLINE void +ACE_OS_Dirent::seekdir (ACE_DIR *d, long loc) +{ +#if defined (ACE_HAS_DIRENT) && !defined (ACE_LACKS_SEEKDIR) + ::seekdir (d, loc); +#else /* ! ACE_HAS_DIRENT || ACE_LACKS_SEEKDIR */ + ACE_UNUSED_ARG (d); + ACE_UNUSED_ARG (loc); +#endif /* ! ACE_HAS_DIRENT || ACE_LACKS_SEEKDIR */ +} + +ACE_INLINE void +ACE_OS_Dirent::rewinddir (ACE_DIR *d) +{ +#if defined (ACE_HAS_PACE) && !defined (ACE_WIN32) + pace_rewinddir (d); +#elif defined (ACE_HAS_DIRENT) +# if defined (ACE_LACKS_SEEKDIR) +# if defined (ACE_LACKS_REWINDDIR) + ACE_UNUSED_ARG (d); +# else /* ! defined (ACE_LACKS_REWINDDIR) */ + ::rewinddir (d); +# endif /* ! defined (ACE_LACKS_REWINDDIR) */ +# else /* ! ACE_LACKS_SEEKDIR */ + // We need to implement using since it's often + // defined as a macro... + ::seekdir (d, long (0)); +# endif /* ! ACE_LACKS_SEEKDIR */ +#else + ACE_UNUSED_ARG (d); +#endif /* ACE_HAS_DIRENT */ +} + +ACE_INLINE int +ACE_OS_Dirent::scandir (const ACE_TCHAR *dirname, + struct dirent **namelist[], + int (*selector)(const struct dirent *), + int (*comparator) (const struct dirent **f1, + const struct dirent **f2)) +{ +#if defined (ACE_HAS_SCANDIR) + return ::scandir (dirname, namelist, selector, comparator); +#else /* ! defined ( ACE_HAS_SCANDIR) */ + return ACE_OS_Dirent::scandir_emulation (dirname, namelist, selector, comparator); +#endif /* ACE_HAS_SCANDIR */ +} diff --git a/ace/OS/OS_Errno.cpp b/ace/OS/OS_Errno.cpp new file mode 100644 index 00000000000..4ae509f6e68 --- /dev/null +++ b/ace/OS/OS_Errno.cpp @@ -0,0 +1,33 @@ +// -*- C++ -*- +// $Id$ + +#include "OS_Errno.h" + +ACE_RCSID(ace, OS_Errno, "$Id$") + +#if !defined (ACE_HAS_INLINED_OSCALLS) +# include "OS_Errno.inl" +#endif /* ACE_HAS_INLINED_OS_CALLS */ + +#if defined (ACE_HAS_WINCE_BROKEN_ERRNO) + +ACE_CE_Errno *ACE_CE_Errno::instance_ = 0; +DWORD ACE_CE_Errno::errno_key_ = 0xffffffff; + +void +ACE_CE_Errno::init () +{ + ACE_NEW (ACE_CE_Errno::instance_, + ACE_CE_Errno ()); + ACE_CE_Errno::errno_key_ = TlsAlloc (); +} + +void +ACE_CE_Errno::fini () +{ + TlsFree (ACE_CE_Errno::errno_key_); + delete ACE_CE_Errno::instance_; + ACE_CE_Errno::instance_ = 0; +} + +#endif /* ACE_HAS_WINCE_BROKEN_ERRNO */ diff --git a/ace/OS/OS_Errno.h b/ace/OS/OS_Errno.h new file mode 100644 index 00000000000..4adfef97762 --- /dev/null +++ b/ace/OS/OS_Errno.h @@ -0,0 +1,143 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file OS_Errno.h + * + * $Id$ + * + * @author (Originally in OS.h)Doug Schmidt + */ +//============================================================================= + +#ifndef ACE_OS_ERRNO_H +#define ACE_OS_ERRNO_H +#include "ace/pre.h" + +#include "ace/config.h" +#include "OS_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#if defined (ACE_HAS_H_ERRNO) +void herror (const char *str); +#endif /* ACE_HAS_H_ERRNO */ + +#if !defined (ACE_HAS_WINCE) +# include /**/ +#endif /* ACE_HAS_WINCE */ + +#if !defined (ACE_WIN32) && !defined (ACE_PSOS) && defined (ACE_LACKS_T_ERRNO) +extern int t_errno; +#endif /* ACE_WIN32 && !ACE_PSOS && ACE_LACKS_T_ERRNO */ + +#if !defined (ENOSYS) +# define ENOSYS EFAULT /* Operation not supported or unknown error. */ +#endif /* !ENOSYS */ + +#if !defined (ENOTSUP) +# define ENOTSUP ENOSYS /* Operation not supported. */ +#endif /* !ENOTSUP */ + +#if defined (ACE_HAS_WINCE_BROKEN_ERRNO) +/** + * @class ACE_CE_Errno + * + * Some versions of CE don't support and some versions' + * implementations are busted. So we implement our own. + * Our implementation takes up one Tls key, however, it does not + * allocate memory fromt the heap so there's no problem with cleanin + * up the errno when a thread exit. + */ +class ACE_OS_Export ACE_CE_Errno +{ +public: + ACE_CE_Errno () {} + static void init (); + static void fini (); + static ACE_CE_Errno *instance (); + + operator int (void) const; + int operator= (int); + +private: + static ACE_CE_Errno *instance_; + static DWORD errno_key_; +}; + +# define errno (* (ACE_CE_Errno::instance ())) +#endif /* ACE_HAS_WINCE_BROKEN_ERRNO */ + +#if defined (ACE_HAS_WINCE_BROKEN_ERRNO) +# define ACE_ERRNO_TYPE ACE_CE_Errno +#else +# define ACE_ERRNO_TYPE int +#endif /* ACE_HAS_WINCE */ + +/** + * @class ACE_Errno_Guard + * + * @brief Provides a wrapper to improve performance when thread-specific + * errno must be saved and restored in a block of code. + * + * The typical use-case for this is the following: + * int error = errno; + * call_some_function_that_might_change_errno (); + * errno = error; + * This can be replaced with + * { + * ACE_Errno_Guard guard (errno); + * call_some_function_that_might_change_errno (); + * } + * This implementation is more elegant and more efficient since it + * avoids an unnecessary second access to thread-specific storage + * by caching a pointer to the value of errno in TSS. + */ +class ACE_OS_Export ACE_Errno_Guard +{ +public: + /// Stash the value of into and initialize the + /// to the address of . + ACE_Errno_Guard (ACE_ERRNO_TYPE &errno_ref, + int error); + + /// Stash the value of into and initialize the + /// to the address of . + ACE_Errno_Guard (ACE_ERRNO_TYPE &errno_ref); + + /// Reset the value of to . + ~ACE_Errno_Guard (void); + +#if defined (ACE_HAS_WINCE_BROKEN_ERRNO) + /// Assign to . + int operator= (const ACE_ERRNO_TYPE &errno_ref); +#endif /* ACE_HAS_WINCE_BROKEN_ERRNO */ + + /// Assign to . + int operator= (int error); + + /// Compare with for equality. + int operator== (int error); + + /// Compare with for inequality. + int operator!= (int error); + +private: +#if defined (ACE_MT_SAFE) + ACE_ERRNO_TYPE *errno_ptr_; +#endif /* ACE_MT_SAFE */ + int error_; +}; + +#if defined (ACE_HAS_INLINED_OSCALLS) +# if defined (ACE_INLINE) +# undef ACE_INLINE +# endif /* ACE_INLINE */ +# define ACE_INLINE inline +# include "OS_Errno.inl" +#endif /* ACE_HAS_INLINED_OSCALLS */ + +#include "ace/post.h" +#endif /* ACE_OS_ERRNO_H */ diff --git a/ace/OS/OS_Errno.inl b/ace/OS/OS_Errno.inl new file mode 100644 index 00000000000..1fb222075be --- /dev/null +++ b/ace/OS/OS_Errno.inl @@ -0,0 +1,87 @@ +// -*- C++ -*- +// $Id$ + +#if defined (ACE_HAS_WINCE_BROKEN_ERRNO) + +ACE_INLINE ACE_CE_Errno * +ACE_CE_Errno::instance () +{ + // This should be inlined. + return ACE_CE_Errno::instance_; +} + +ACE_INLINE +ACE_CE_Errno::operator int (void) const +{ + return (int) TlsGetValue (ACE_CE_Errno::errno_key_); +} + +ACE_INLINE int +ACE_CE_Errno::operator= (int x) +{ + // error checking? + TlsSetValue (ACE_CE_Errno::errno_key_, (void *) x); + return x; +} + +#endif /* ACE_HAS_WINCE_BROKEN_ERRNO */ + +ACE_INLINE +ACE_Errno_Guard::ACE_Errno_Guard (ACE_ERRNO_TYPE &errno_ref, + int error) + : +#if defined (ACE_MT_SAFE) + errno_ptr_ (&errno_ref), +#endif /* ACE_MT_SAFE */ + error_ (error) +{ +#if !defined(ACE_MT_SAFE) + ACE_UNUSED_ARG (errno_ref); +#endif /* ACE_MT_SAFE */ +} + +ACE_INLINE +ACE_Errno_Guard::ACE_Errno_Guard (ACE_ERRNO_TYPE &errno_ref) + : +#if defined (ACE_MT_SAFE) + errno_ptr_ (&errno_ref), +#endif /* ACE_MT_SAFE */ + error_ (errno_ref) +{ +} + +ACE_INLINE +ACE_Errno_Guard::~ACE_Errno_Guard (void) +{ +#if defined (ACE_MT_SAFE) + *errno_ptr_ = this->error_; +#else + errno = this->error_; +#endif /* ACE_MT_SAFE */ +} + +#if defined (ACE_HAS_WINCE_BROKEN_ERRNO) +ACE_INLINE int +ACE_Errno_Guard::operator= (const ACE_ERRNO_TYPE &error) +{ + return this->error_ = error; +} +#endif /* ACE_HAS_WINCE_BROKEN_ERRNO */ + +ACE_INLINE int +ACE_Errno_Guard::operator= (int error) +{ + return this->error_ = error; +} + +ACE_INLINE int +ACE_Errno_Guard::operator== (int error) +{ + return this->error_ == error; +} + +ACE_INLINE int +ACE_Errno_Guard::operator!= (int error) +{ + return this->error_ != error; +} diff --git a/ace/OS/OS_Export.h b/ace/OS/OS_Export.h new file mode 100644 index 00000000000..bc6841996c8 --- /dev/null +++ b/ace/OS/OS_Export.h @@ -0,0 +1,46 @@ +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by +// generate_export_file.pl +// ------------------------------ +#if !defined (ACE_OS_EXPORT_H) +#define ACE_OS_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) +# if !defined (ACE_OS_HAS_DLL) +# define ACE_OS_HAS_DLL 0 +# endif /* ! ACE_OS_HAS_DLL */ +#else +# if !defined (ACE_OS_HAS_DLL) +# define ACE_OS_HAS_DLL 1 +# endif /* ! ACE_OS_HAS_DLL */ +#endif /* ACE_AS_STATIC_LIB */ + +#if defined (ACE_OS_HAS_DLL) +# if (ACE_OS_HAS_DLL == 1) +# if defined (ACE_OS_BUILD_DLL) +# define ACE_OS_Export ACE_Proper_Export_Flag +# define ACE_OS_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define ACE_OS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else +# define ACE_OS_Export ACE_Proper_Import_Flag +# define ACE_OS_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define ACE_OS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* ACE_OS_BUILD_DLL */ +# else +# define ACE_OS_Export +# define ACE_OS_SINGLETON_DECLARATION(T) +# define ACE_OS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* ! ACE_OS_HAS_DLL == 1 */ +#else +# define ACE_OS_Export +# define ACE_OS_SINGLETON_DECLARATION(T) +# define ACE_OS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* ACE_OS_HAS_DLL */ + +#endif /* ACE_OS_EXPORT_H */ + +// End of auto generated file. diff --git a/ace/OS/OS_Log_Msg_Attributes.cpp b/ace/OS/OS_Log_Msg_Attributes.cpp new file mode 100644 index 00000000000..62bbfe3adda --- /dev/null +++ b/ace/OS/OS_Log_Msg_Attributes.cpp @@ -0,0 +1,9 @@ +// $Id$ + +#include "OS_Log_Msg_Attributes.h" + +#if !defined (ACE_HAS_INLINED_OSCALLS) +# include "OS_Log_Msg_Attributes.inl" +#endif /* ACE_HAS_INLINED_OS_CALLS */ + +ACE_RCSID(ace, OS_Log_Msg_Attributes, "$Id$") diff --git a/ace/OS/OS_Log_Msg_Attributes.h b/ace/OS/OS_Log_Msg_Attributes.h new file mode 100644 index 00000000000..094850a7012 --- /dev/null +++ b/ace/OS/OS_Log_Msg_Attributes.h @@ -0,0 +1,89 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file OS_Log_Msg_Attributes.h + * + * $Id$ + * + * @author Carlos O'Ryan + */ +//============================================================================= + + +#ifndef ACE_OS_LOG_MSG_ATTRIBUTES_H +#define ACE_OS_LOG_MSG_ATTRIBUTES_H +#include "ace/pre.h" + +#include "ace/config-all.h" +#include "ace/streams.h" +#include /**/ // LynxOS requires this before stdio.h +#include /**/ + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#if !defined (ACE_OSTREAM_TYPE) +# if defined (ACE_LACKS_IOSTREAM_TOTALLY) +# define ACE_OSTREAM_TYPE FILE +# else /* ! ACE_LACKS_IOSTREAM_TOTALLY */ +# define ACE_OSTREAM_TYPE ostream +# endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */ +#endif /* ! ACE_OSTREAM_TYPE */ + + +#include "OS_Export.h" + +/// The attributes required by ACE_Log_Msg. +/** + * When a new thread is created the TSS resources for the Log_Msg + * class in the new thread may be inherited by the creator thread. + * The base_attributes are encapsulated in this class to simplify their + * manipulation and destruction. + * + * The contents of the class must be made available to the OS layer, + * because they are part of the thread descriptor. + */ +class ACE_OS_Export ACE_OS_Log_Msg_Attributes +{ +public: + /// Constructor + ACE_OS_Log_Msg_Attributes (void); + +protected: + friend class ACE_Log_Msg; + + /// Ostream where the new TSS Log_Msg will use. + ACE_OSTREAM_TYPE *ostream_; + + /// Priority_mask to be used in new TSS Log_Msg. + unsigned long priority_mask_; + + /// Are we allowing tracing in this thread? + int tracing_enabled_; + + /// Indicates whether we should restart system calls that are + /// interrupted. + int restart_; + + /// Depth of the nesting for printing traces. + int trace_depth_; + +# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) + /// Structured exception handling Callbacks, only used under Win32 + ACE_SEH_EXCEPT_HANDLER seh_except_selector_; + ACE_SEH_EXCEPT_HANDLER seh_except_handler_; +# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ +}; + +# if defined (ACE_HAS_INLINED_OSCALLS) +# if defined (ACE_INLINE) +# undef ACE_INLINE +# endif /* ACE_INLINE */ +# define ACE_INLINE inline +# include "OS_Log_Msg_Attributes.inl" +# endif /* ACE_HAS_INLINED_OSCALLS */ + +#include "ace/post.h" +#endif /* ACE_OS_LOG_MSG_ATTRIBUTES_H */ diff --git a/ace/OS/OS_Log_Msg_Attributes.inl b/ace/OS/OS_Log_Msg_Attributes.inl new file mode 100644 index 00000000000..d79e7fe90f8 --- /dev/null +++ b/ace/OS/OS_Log_Msg_Attributes.inl @@ -0,0 +1,6 @@ +// $Id$ + +ACE_INLINE +ACE_OS_Log_Msg_Attributes::ACE_OS_Log_Msg_Attributes (void) +{ +} diff --git a/ace/OS/OS_Memory.cpp b/ace/OS/OS_Memory.cpp new file mode 100644 index 00000000000..8eb3ab2b308 --- /dev/null +++ b/ace/OS/OS_Memory.cpp @@ -0,0 +1,13 @@ +// $Id$ + +#include "OS_Memory.h" + +ACE_RCSID(ace, OS_Memory, "$Id$") + +#if !defined (ACE_HAS_INLINED_OSCALLS) +# include "OS_Memory.inl" +#else /* !ACE_HAS_INLINED_OSCALLS */ +#if defined (__hpux) && !defined (__GNUG__) +static int shut_up_aCC = 0; +#endif /* HPUX && !g++ */ +#endif /* !ACE_HAS_INLINED_OS_CALLS */ diff --git a/ace/OS/OS_Memory.h b/ace/OS/OS_Memory.h new file mode 100644 index 00000000000..cdd0833b626 --- /dev/null +++ b/ace/OS/OS_Memory.h @@ -0,0 +1,123 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file OS_Memory.h + * + * $Id$ + * + * @author Doug Schmidt + * @author Jesper S. M|ller + * @author and a cast of thousands... + */ +//============================================================================= + +#ifndef ACE_OS_MEMORY_H +#define ACE_OS_MEMORY_H +#include "ace/pre.h" + +#include "ace/config-all.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "OS_Export.h" +#if defined (ACE_HAS_PACE) +# include /**/ "pace/stdlib.h" +#endif /* ACE_HAS_PACE */ +#include /**/ + +# if !defined (ACE_MALLOC_ALIGN) +# define ACE_MALLOC_ALIGN ((int) sizeof (long)) +# endif /* ACE_MALLOC_ALIGN */ + +# if !defined (ACE_HAS_POSITION_INDEPENDENT_POINTERS) +# define ACE_HAS_POSITION_INDEPENDENT_POINTERS 1 +# endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS */ + +// Allow an installation to replace the lowest-level allocation +// functions without changing the source of ACE. +// +// To do this, simple #define ACE_*_FUNC macros in config.h to +// the names of the site-specific functions, e.g., +// +// #define ACE_MALLOC_FUNC dlmalloc +// #define ACE_CALLOC_FUNC dlcalloc +// #define ACE_FREE_FUNC dlfree +// #define ACE_REALLOC_FUNC dlrealloc +// +// For completeness' sake, you should probably put +// #define ACE_HAS_STRDUP_EMULATION +// too, so that you guarantee that strdup() calls your desired mallocator +// and not the system mallocator. +// +# if defined (ACE_HAS_PACE) +# if !defined (ACE_MALLOC_FUNC) +# define ACE_MALLOC_FUNC pace_malloc +# endif +# if !defined (ACE_CALLOC_FUNC) +# define ACE_CALLOC_FUNC pace_calloc +# endif +# if !defined (ACE_FREE_FUNC) +# define ACE_FREE_FUNC pace_free +# endif +# if !defined (ACE_REALLOC_FUNC) +# define ACE_REALLOC_FUNC pace_realloc +# endif + +# if defined (ACE_HAS_OLD_MALLOC) +typedef char *ACE_MALLOC_T; +# else +typedef void *ACE_MALLOC_T; +# endif /* ACE_HAS_OLD_MALLOC */ + +# else + +# if !defined (ACE_MALLOC_FUNC) +# define ACE_MALLOC_FUNC ::malloc +# endif +# if !defined (ACE_CALLOC_FUNC) +# define ACE_CALLOC_FUNC ::calloc +# endif +# if !defined (ACE_FREE_FUNC) +# define ACE_FREE_FUNC ::free +# endif +# if !defined (ACE_REALLOC_FUNC) +# define ACE_REALLOC_FUNC ::realloc +# endif + +# if defined (ACE_HAS_OLD_MALLOC) +typedef char *ACE_MALLOC_T; +# else +typedef void *ACE_MALLOC_T; +# endif /* ACE_HAS_OLD_MALLOC */ +#endif /* ACE_HAS_PACE */ + +/** + * @class ACE_OS_Memory + * + * @brief This class is a wrapper for dynamic memory operations. + * + */ +class ACE_OS_Export ACE_OS_Memory +{ +public: + // = A set of wrappers for memory managment. + static void *sbrk (int brk); + static void *calloc (size_t elements, size_t sizeof_elements); + static void *malloc (size_t); + static void *realloc (void *, size_t); + static void free (void *); +}; + +# if defined (ACE_HAS_INLINED_OSCALLS) +# if defined (ACE_INLINE) +# undef ACE_INLINE +# endif /* ACE_INLINE */ +# define ACE_INLINE inline +# include "OS_Memory.inl" +# endif /* ACE_HAS_INLINED_OSCALLS */ + +#include "ace/post.h" +#endif /* ACE_OS_MEMORY_H */ diff --git a/ace/OS/OS_Memory.inl b/ace/OS/OS_Memory.inl new file mode 100644 index 00000000000..510a281346c --- /dev/null +++ b/ace/OS/OS_Memory.inl @@ -0,0 +1,50 @@ +// $Id$ + +#if ! defined (ACE_PSOS_DIAB_MIPS) +# include /**/ +#endif /* ! ACE_PSOS_DIAB_MIPS */ + +#if !defined (ACE_LACKS_UNISTD_H) && !defined (ACE_PSOS) +# include /**/ +#endif /* !ACE_LACKS_UNISTD_H && !ACE_PSOS */ + +ACE_INLINE void * +ACE_OS_Memory::sbrk (int brk) +{ +#if defined (ACE_LACKS_SBRK) + ACE_UNUSED_ARG (brk); + ACE_NOTSUP_RETURN (0); +#else + ACE_OSCALL_RETURN (::sbrk (brk), void *, 0); +#endif /* VXWORKS */ +} + +ACE_INLINE void * +ACE_OS_Memory::malloc (size_t nbytes) +{ + return ACE_MALLOC_FUNC (nbytes); +} + +ACE_INLINE void * +ACE_OS_Memory::calloc (size_t elements, size_t sizeof_elements) +{ +#if !defined (ACE_HAS_WINCE) + return ACE_CALLOC_FUNC (elements, sizeof_elements); +#else + // @@ This will probably not work since it doesn't consider + // alignment properly. + return ACE_MALLOC_FUNC (elements * sizeof_elements); +#endif /* ACE_HAS_WINCE */ +} + +ACE_INLINE void * +ACE_OS_Memory::realloc (void *ptr, size_t nbytes) +{ + return ACE_REALLOC_FUNC (ACE_MALLOC_T (ptr), nbytes); +} + +ACE_INLINE void +ACE_OS_Memory::free (void *ptr) +{ + ACE_FREE_FUNC (ACE_MALLOC_T (ptr)); +} diff --git a/ace/OS/OS_QoS.cpp b/ace/OS/OS_QoS.cpp new file mode 100644 index 00000000000..a6cca321436 --- /dev/null +++ b/ace/OS/OS_QoS.cpp @@ -0,0 +1,471 @@ +//============================================================================= +///** +// * @file OS_QoS.cpp +// * +// * $Id$ +// * +// * @brief Contains OS specific data structures for QoS networking. +// * +// * @author Craig Rodrigues +// */ +//============================================================================= + +#include "OS_QoS.h" + +ACE_Flow_Spec::ACE_Flow_Spec (u_long token_rate, + u_long token_bucket_size, + u_long peak_bandwidth, + u_long latency, + u_long delay_variation, + ACE_SERVICE_TYPE service_type, + u_long max_sdu_size, + u_long minimum_policed_size, + int ttl, + int priority) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + this->TokenRate = token_rate; + this->TokenBucketSize = token_bucket_size; + this->PeakBandwidth = peak_bandwidth; + this->Latency = latency; + this->DelayVariation = delay_variation; +#if defined(ACE_HAS_WINSOCK2_GQOS) + this->ServiceType = service_type; + this->MaxSduSize = max_sdu_size; + this->MinimumPolicedSize = minimum_policed_size; +#else + ACE_UNUSED_ARG (service_type); + ACE_UNUSED_ARG (max_sdu_size); + ACE_UNUSED_ARG (minimum_policed_size); +#endif /* ACE_HAS_WINSOCK2_GQOS */ + ACE_UNUSED_ARG (ttl); + ACE_UNUSED_ARG (priority); +#else + + this->token_rate_ = token_rate; + this->token_bucket_size_ = token_bucket_size; + this->peak_bandwidth_ = peak_bandwidth; + this->latency_ = latency; + this->delay_variation_ = delay_variation; + this->service_type_ = service_type; + this->max_sdu_size_ = max_sdu_size; + this->minimum_policed_size_ = minimum_policed_size; + this->ttl_ = ttl; + this->priority_ = priority; + +#endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */ +} + +ACE_Flow_Spec::ACE_Flow_Spec (void) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \ + defined (ACE_HAS_WINSOCK2_GQOS) + this->TokenRate = 0; + this->TokenBucketSize = 0; + this->PeakBandwidth = 0; + this->Latency = 0; + this->DelayVariation = 0; +#if defined(ACE_HAS_WINSOCK2_GQOS) + this->ServiceType = 0; + this->MaxSduSize = 0; + this->MinimumPolicedSize = 0; +#endif /* ACE_HAS_WINSOCK2_GQOS */ +#else + + this->token_rate_ = 0; + this->token_bucket_size_ = 0; + this->peak_bandwidth_ = 0; + this->latency_ = 0; + this->delay_variation_ = 0; + this->service_type_ = 0; + this->max_sdu_size_ = 0; + this->minimum_policed_size_ = 0; + this->ttl_ = 0; + this->priority_ = 0; + +#endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) */ +} + +u_long +ACE_Flow_Spec::token_rate (void) const +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + return this->TokenRate; +#else + return this->token_rate_; +#endif /* ACE_HAS_WINSOCK2 */ +} + +void +ACE_Flow_Spec::token_rate (u_long tr) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + this->TokenRate = tr; +#else + this->token_rate_ = tr; +#endif /* ACE_HAS_WINSOCK2 */ +} + +u_long +ACE_Flow_Spec::token_bucket_size (void) const +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + return this->TokenBucketSize; +#else + return this->token_bucket_size_; +#endif /* ACE_HAS_WINSOCK2 */ +} + +void +ACE_Flow_Spec::token_bucket_size (u_long tbs) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + this->TokenBucketSize = tbs; +#else + this->token_bucket_size_ = tbs; +#endif /* ACE_HAS_WINSOCK2 */ +} + +u_long +ACE_Flow_Spec::peak_bandwidth (void) const +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + return this->PeakBandwidth; +#else + return this->peak_bandwidth_; +#endif /* ACE_HAS_WINSOCK2 */ +} + +void +ACE_Flow_Spec::peak_bandwidth (u_long pb) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + this->PeakBandwidth = pb; +#else + this->peak_bandwidth_ = pb; +#endif /* ACE_HAS_WINSOCK2 */ +} + +u_long +ACE_Flow_Spec::latency (void) const +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + return this->Latency; +#else + return this->latency_; +#endif /* ACE_HAS_WINSOCK2 */ +} + +void +ACE_Flow_Spec::latency (u_long l) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + this->Latency = l; +#else + this->latency_ = l; +#endif /* ACE_HAS_WINSOCK2 */ +} + +u_long +ACE_Flow_Spec::delay_variation (void) const +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + return this->DelayVariation; +#else + return this->delay_variation_; +#endif /* ACE_HAS_WINSOCK2 */ +} +void +ACE_Flow_Spec::delay_variation (u_long dv) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + this->DelayVariation = dv; +#else + this->delay_variation_ = dv; +#endif /* ACE_HAS_WINSOCK2 */ +} + +ACE_SERVICE_TYPE +ACE_Flow_Spec::service_type (void) const +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \ + defined (ACE_HAS_WINSOCK2_GQOS) + return this->ServiceType; +#else + return this->service_type_; +#endif /* ACE_HAS_WINSOCK2 */ +} + +void +ACE_Flow_Spec::service_type (ACE_SERVICE_TYPE st) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \ + defined (ACE_HAS_WINSOCK2_GQOS) + this->ServiceType = st; +#else + this->service_type_ = st; +#endif /* ACE_HAS_WINSOCK2 */ +} + +u_long +ACE_Flow_Spec::max_sdu_size (void) const +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \ + defined (ACE_HAS_WINSOCK2_GQOS) + return this->MaxSduSize; +#else + return this->max_sdu_size_; +#endif /* ACE_HAS_WINSOCK2 */ +} + +void +ACE_Flow_Spec::max_sdu_size (u_long mss) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \ + defined (ACE_HAS_WINSOCK2_GQOS) + this->MaxSduSize = mss; +#else + this->max_sdu_size_ = mss; +#endif /* ACE_HAS_WINSOCK2 */ +} + +u_long +ACE_Flow_Spec::minimum_policed_size (void) const +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \ + defined (ACE_HAS_WINSOCK2_GQOS) + return this->MinimumPolicedSize; +#else + return this->minimum_policed_size_; +#endif /* ACE_HAS_WINSOCK2 */ +} + +void +ACE_Flow_Spec::minimum_policed_size (u_long mps) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \ + defined (ACE_HAS_WINSOCK2_GQOS) + this->MinimumPolicedSize = mps; +#else + this->minimum_policed_size_ = mps; +#endif /* ACE_HAS_WINSOCK2 */ +} + +int +ACE_Flow_Spec::ttl (void) const +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \ + defined (ACE_HAS_WINSOCK2_GQOS) + ACE_NOTSUP_RETURN (-1); +#else + return this->ttl_; +#endif /* ACE_HAS_WINSOCK2 */ +} + +void +ACE_Flow_Spec::ttl (int t) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \ + defined (ACE_HAS_WINSOCK2_GQOS) + ACE_UNUSED_ARG (t); + // TBD... +#else + this->ttl_ = t; +#endif /* ACE_HAS_WINSOCK2 */ +} + +int +ACE_Flow_Spec::priority (void) const +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \ + defined (ACE_HAS_WINSOCK2_GQOS) + ACE_NOTSUP_RETURN (-1); +#else + return this->priority_; +#endif /* ACE_HAS_WINSOCK2 */ +} + +void +ACE_Flow_Spec::priority (int p) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \ + defined (ACE_HAS_WINSOCK2_GQOS) + ACE_UNUSED_ARG (p); + // TBD... +#else + this->priority_ = p; +#endif /* ACE_HAS_WINSOCK2 */ +} + +ACE_QoS::ACE_QoS (void) +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) +#else + : sending_flowspec_ (0), + receiving_flowspec_ (0) +#endif /* ACE_HAS_WINSOCK2 */ +{ +} + +ACE_Flow_Spec* +ACE_QoS::sending_flowspec (void) const +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + return &((ACE_Flow_Spec &) this->SendingFlowspec); +#else + return this->sending_flowspec_; +#endif /* ACE_HAS_WINSOCK2 */ +} + +void +ACE_QoS::sending_flowspec (ACE_Flow_Spec *fs) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + this->SendingFlowspec = (FLOWSPEC) (*fs); +#else + this->sending_flowspec_ = fs; +#endif /* ACE_HAS_WINSOCK2 */ +} + +ACE_Flow_Spec* +ACE_QoS::receiving_flowspec (void) const +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + return &((ACE_Flow_Spec &) this->ReceivingFlowspec); +#else + return receiving_flowspec_; +#endif /* ACE_HAS_WINSOCK2 */ +} + +void +ACE_QoS::receiving_flowspec (ACE_Flow_Spec *fs) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + this->ReceivingFlowspec = (FLOWSPEC) (*fs); +#else + this->receiving_flowspec_ = fs; +#endif /* ACE_HAS_WINSOCK2 */ +} + +iovec +ACE_QoS::provider_specific (void) const +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + return (iovec&) this->ProviderSpecific; +#else + ACE_NOTSUP_RETURN (iovec ()); +#endif /* ACE_HAS_WINSOCK2 */ +} + +void +ACE_QoS::provider_specific (const iovec &ps) +{ +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + this->ProviderSpecific = (WSABUF) ((iovec &) ps); +#else + ACE_UNUSED_ARG (ps); +#endif /* ACE_HAS_WINSOCK2 */ +} + +ACE_QoS_Params::ACE_QoS_Params (iovec *caller_data, + iovec *callee_data, + ACE_QoS *socket_qos, + ACE_QoS *group_socket_qos, + u_long flags) + : caller_data_ (caller_data), + callee_data_ (callee_data), + socket_qos_ (socket_qos), + group_socket_qos_ (group_socket_qos), + flags_ (flags) +{ +} + +iovec * +ACE_QoS_Params::caller_data (void) const +{ + return this->caller_data_; +} + +void +ACE_QoS_Params::caller_data (iovec *cd) +{ + this->caller_data_ = cd; +} + +iovec * +ACE_QoS_Params::callee_data (void) const +{ + return this->callee_data_; +} + +void +ACE_QoS_Params::callee_data (iovec *cd) +{ + this->callee_data_ = cd; +} + +ACE_QoS * +ACE_QoS_Params::socket_qos (void) const +{ + return this->socket_qos_; +} + +void +ACE_QoS_Params::socket_qos (ACE_QoS *sq) +{ + this->socket_qos_ = sq; +} + +ACE_QoS * +ACE_QoS_Params::group_socket_qos (void) const +{ + return this->group_socket_qos_; +} + +void +ACE_QoS_Params::group_socket_qos (ACE_QoS *gsq) +{ + this->group_socket_qos_ = gsq; +} + +u_long +ACE_QoS_Params::flags (void) const +{ + return this->flags_; +} + +void +ACE_QoS_Params::flags (u_long f) +{ + this->flags_ = f; +} + +ACE_Accept_QoS_Params::ACE_Accept_QoS_Params (ACE_QOS_CONDITION_FUNC qos_condition_callback, + u_long callback_data) + : qos_condition_callback_ (qos_condition_callback), + callback_data_ (callback_data) +{ +} + +ACE_QOS_CONDITION_FUNC +ACE_Accept_QoS_Params::qos_condition_callback (void) const +{ + return this->qos_condition_callback_; +} + +void +ACE_Accept_QoS_Params::qos_condition_callback (ACE_QOS_CONDITION_FUNC qcc) +{ + this->qos_condition_callback_ = qcc; +} + +u_long +ACE_Accept_QoS_Params::callback_data (void) const +{ + return this->callback_data_; +} + +void +ACE_Accept_QoS_Params::callback_data (u_long cd) +{ + this->callback_data_ = cd; +} diff --git a/ace/OS/OS_QoS.h b/ace/OS/OS_QoS.h new file mode 100644 index 00000000000..93d6b29d4a4 --- /dev/null +++ b/ace/OS/OS_QoS.h @@ -0,0 +1,386 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file OS_QoS.h + * + * $Id$ + * + * @brief Contains OS specific data structures for QoS networking. + * + * @author Craig Rodrigues + */ +//============================================================================= + +#ifndef ACE_OS_QOS_H +#define ACE_OS_QOS_H +#include "ace/pre.h" + +#include "OS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) +#if defined (ACE_HAS_WINSOCK2_GQOS) +typedef SERVICETYPE ACE_SERVICE_TYPE; +#else +typedef u_long ACE_SERVICE_TYPE; +#endif /* ACE_HAS_WINSOCK2_GQOS */ + + +#define ACE_OVERLAPPED_SOCKET_FLAG WSA_FLAG_OVERLAPPED + +#define ACE_XP1_QOS_SUPPORTED XP1_QOS_SUPPORTED +#define ACE_XP1_SUPPORT_MULTIPOINT XP1_SUPPORT_MULTIPOINT + +#define ACE_BASEERR WSABASEERR +#define ACE_ENOBUFS WSAENOBUFS +#define ACE_FROM_PROTOCOL_INFO FROM_PROTOCOL_INFO +#define ACE_FLAG_MULTIPOINT_C_ROOT WSA_FLAG_MULTIPOINT_C_ROOT +#define ACE_FLAG_MULTIPOINT_C_LEAF WSA_FLAG_MULTIPOINT_C_LEAF +#define ACE_FLAG_MULTIPOINT_D_ROOT WSA_FLAG_MULTIPOINT_D_ROOT +#define ACE_FLAG_MULTIPOINT_D_LEAF WSA_FLAG_MULTIPOINT_D_LEAF + +#define ACE_QOS_NOT_SPECIFIED QOS_NOT_SPECIFIED +#define ACE_SERVICETYPE_NOTRAFFIC SERVICETYPE_NOTRAFFIC +#define ACE_SERVICETYPE_CONTROLLEDLOAD SERVICETYPE_CONTROLLEDLOAD +#define ACE_SERVICETYPE_GUARANTEED SERVICETYPE_GUARANTEED + +#define ACE_JL_SENDER_ONLY JL_SENDER_ONLY +#define ACE_JL_BOTH JL_BOTH + +#define ACE_SIO_GET_QOS SIO_GET_QOS +#define ACE_SIO_MULTIPOINT_LOOPBACK SIO_MULTIPOINT_LOOPBACK +#define ACE_SIO_MULTICAST_SCOPE SIO_MULTICAST_SCOPE +#define ACE_SIO_SET_QOS SIO_SET_QOS + +#else +typedef u_long ACE_SERVICE_TYPE; + +#define ACE_OVERLAPPED_SOCKET_FLAG 0 +#define ACE_XP1_QOS_SUPPORTED 0x00002000 +#define ACE_XP1_SUPPORT_MULTIPOINT 0x00000400 + +#define ACE_BASEERR 10000 +#define ACE_ENOBUFS (ACE_BASEERR+55) + +#define ACE_FROM_PROTOCOL_INFO (-1) + +#define ACE_FLAG_MULTIPOINT_C_ROOT 0x02 +#define ACE_FLAG_MULTIPOINT_C_LEAF 0x04 +#define ACE_FLAG_MULTIPOINT_D_ROOT 0x08 +#define ACE_FLAG_MULTIPOINT_D_LEAF 0x10 + +#define ACE_QOS_NOT_SPECIFIED 0xFFFFFFFF +#define ACE_SERVICETYPE_NOTRAFFIC 0x00000000 /* No data in this */ + /* direction. */ +#define ACE_SERVICETYPE_CONTROLLEDLOAD 0x00000001 /* Controlled Load. */ +#define ACE_SERVICETYPE_GUARANTEED 0x00000003 /* Guaranteed. */ + +#define ACE_JL_SENDER_ONLY 0x01 +#define ACE_JL_BOTH 0x04 + +#define ACE_SIO_GET_QOS (0x40000000 | 0x08000000 | 7) +#define ACE_SIO_MULTIPOINT_LOOPBACK (0x08000000 | 9) +#define ACE_SIO_MULTICAST_SCOPE (0x08000000 | 10) +#define ACE_SIO_SET_QOS (0x08000000 | 11) + +#endif /* ACE_HAS_WINSOCK2 && ACE_HAS_WINSOCK2 != 0 */ + + + + +/** + * @class ACE_Flow_Spec + * + * @brief Wrapper class that defines the flow spec QoS information, + * which is used by IntServ (RSVP) and DiffServ. + */ +class ACE_OS_Export ACE_Flow_Spec +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + : public FLOWSPEC +#endif /* ACE_HAS_WINSOCK2 */ +{ +public: + /// Default constructor. + ACE_Flow_Spec (void); + + /// Constructor that initializes all the fields. + ACE_Flow_Spec (u_long token_rate, + u_long token_bucket_size, + u_long peak_bandwidth, + u_long latency, + u_long delay_variation, + ACE_SERVICE_TYPE service_type, + u_long max_sdu_size, + u_long minimum_policed_size, + int ttl, + int priority); + + /// Get the token rate in bytes/sec. + u_long token_rate (void) const; + + /// Set the token rate in bytes/sec. + void token_rate (u_long tr); + + /// Get the token bucket size in bytes. + u_long token_bucket_size (void) const; + + /// Set the token bucket size in bytes. + void token_bucket_size (u_long tbs); + + /// Get the PeakBandwidth in bytes/sec. + u_long peak_bandwidth (void) const; + + /// Set the PeakBandwidth in bytes/sec. + void peak_bandwidth (u_long pb); + + /// Get the latency in microseconds. + u_long latency (void) const; + + /// Set the latency in microseconds. + void latency (u_long l); + + /// Get the delay variation in microseconds. + u_long delay_variation (void) const; + + /// Set the delay variation in microseconds. + void delay_variation (u_long dv); + + /// Get the service type. + ACE_SERVICE_TYPE service_type (void) const; + + /// Set the service type. + void service_type (ACE_SERVICE_TYPE st); + + /// Get the maximum SDU size in bytes. + u_long max_sdu_size (void) const; + + /// Set the maximum SDU size in bytes. + void max_sdu_size (u_long mss); + + /// Get the minimum policed size in bytes. + u_long minimum_policed_size (void) const; + + /// Set the minimum policed size in bytes. + void minimum_policed_size (u_long mps); + + /// Get the time-to-live. + int ttl (void) const; + + /// Set the time-to-live. + void ttl (int t); + + /// Get the priority. + int priority (void) const; + + /// Set the priority. + void priority (int p); + +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \ + defined (ACE_HAS_WINSOCK2_GQOS) +#else +private: + u_long token_rate_; + u_long token_bucket_size_; + u_long peak_bandwidth_; + u_long latency_; + u_long delay_variation_; + ACE_SERVICE_TYPE service_type_; + u_long max_sdu_size_; + u_long minimum_policed_size_; + int ttl_; + int priority_; +#endif /* defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) && \ + defined (ACE_HAS_WINSOCK2_GQOS) */ +}; + +/** + * @class ACE_QoS + * + * @brief Wrapper class that holds the sender and receiver flow spec + * information, which is used by IntServ (RSVP) and DiffServ. + */ +class ACE_OS_Export ACE_QoS +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) + : public QOS +#endif /* ACE_HAS_WINSOCK2 */ +{ +public: + /// Constructor + ACE_QoS (void); + + /// Get the flow spec for data sending. + ACE_Flow_Spec *sending_flowspec (void) const; + + /// Set the flow spec for data sending. + void sending_flowspec (ACE_Flow_Spec *fs); + + /// Get the flow spec for data receiving. + ACE_Flow_Spec *receiving_flowspec (void) const; + + /// Set the flow spec for data receiving. + void receiving_flowspec (ACE_Flow_Spec *fs); + + /// Get the provider specific information. + iovec provider_specific (void) const; + + /// Set the provider specific information. + void provider_specific (const iovec &ps); + +#if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) +#else +private: + + ACE_Flow_Spec *sending_flowspec_; + ACE_Flow_Spec *receiving_flowspec_; +#endif + +}; + +/** + * @class ACE_QoS_Params + * + * @brief Wrapper class that simplifies the information passed to the QoS + * enabled and methods. + */ +class ACE_OS_Export ACE_QoS_Params +{ +public: + /** + * Initialize the data members. The is a pointer to + * the user data that is to be transferred to the peer during + * connection establishment. The is a pointer to the + * user data that is to be transferred back from the peer during + * connection establishment. The_ is a pointer to the + * flow specifications for the socket, one for each direction. The + * is a pointer to the flow speicfications for + * the socket group, if applicable. The_ indicate if we're a + * sender, receiver, or both. + */ + ACE_QoS_Params (iovec *caller_data = 0, + iovec *callee_data = 0, + ACE_QoS *socket_qos = 0, + ACE_QoS *group_socket_qos = 0, + u_long flags = 0); + + /// Get caller data. + iovec *caller_data (void) const; + + /// Set caller data. + void caller_data (iovec *); + + /// Get callee data. + iovec *callee_data (void) const; + + /// Set callee data. + void callee_data (iovec *); + + /// Get socket qos. + ACE_QoS *socket_qos (void) const; + + /// Set socket qos. + void socket_qos (ACE_QoS *); + + /// Get group socket qos. + ACE_QoS *group_socket_qos (void) const; + + /// Set group socket qos. + void group_socket_qos (ACE_QoS *); + + /// Get flags. + u_long flags (void) const; + + /// Set flags. + void flags (u_long); + +private: + /// A pointer to the user data that is to be transferred to the peer + /// during connection establishment. + iovec *caller_data_; + + /// A pointer to the user data that is to be transferred back from + /// the peer during connection establishment. + iovec *callee_data_; + + /// A pointer to the flow speicfications for the socket, one for each + /// direction. + ACE_QoS *socket_qos_; + + /// A pointer to the flow speicfications for the socket group, if + /// applicable. + ACE_QoS *group_socket_qos_; + + /// Flags that indicate if we're a sender, receiver, or both. + u_long flags_; +}; + +// Callback function that's used by the QoS-enabled +// method. +typedef int (*ACE_QOS_CONDITION_FUNC) (iovec *caller_id, + iovec *caller_data, + ACE_QoS *socket_qos, + ACE_QoS *group_socket_qos, + iovec *callee_id, + iovec *callee_data, + ACE_SOCK_GROUP *g, + u_long callbackdata); + + +/** + * @class ACE_Accept_QoS_Params + * + * @brief Wrapper class that simplifies the information passed to the QoS + * enabled method. + */ +class ACE_OS_Export ACE_Accept_QoS_Params +{ +public: + /** + * Initialize the data members. The is the + * address of an optional, application-supplied condition function + * that will make an accept/reject decision based on the caller + * information pass in as parameters, and optionally create or join + * a socket group by assinging an appropriate value to the result + * parameter of this function. The data is + * passed back to the application as a condition function parameter, + * i.e., it is an Asynchronous Completion Token (ACT). + */ + ACE_Accept_QoS_Params (ACE_QOS_CONDITION_FUNC qos_condition_callback = 0, + u_long callback_data = 0); + + /// Get QoS condition callback. + ACE_QOS_CONDITION_FUNC qos_condition_callback (void) const; + + /// Set QoS condition callback. + void qos_condition_callback (ACE_QOS_CONDITION_FUNC qcc); + + /// Get callback data. + u_long callback_data (void) const; + + /// Set callback data. + void callback_data (u_long cd); + +private: + /** + * This is the address of an optional, application-supplied + * condition function that will make an accept/reject decision based + * on the caller information pass in as parameters, and optionally + * create or join a socket group by assinging an appropriate value + * to the result parameter of this function. + */ + ACE_QOS_CONDITION_FUNC qos_condition_callback_; + + /** + * This data is passed back to the application as a condition + * function parameter, i.e., it is an Asynchronous Completion Token + * (ACT). + */ + u_long callback_data_; +}; + + +#include "ace/post.h" +#endif /* ACE_OS_QOS_H */ diff --git a/ace/OS/OS_String.cpp b/ace/OS/OS_String.cpp new file mode 100644 index 00000000000..2d1350f5372 --- /dev/null +++ b/ace/OS/OS_String.cpp @@ -0,0 +1,1023 @@ +//============================================================================= +/** + * @file OS_String.cpp + * + * $Id$ + * + * @brief Contains definitions for class ACE_OS_String. + */ +//============================================================================= + +#include "OS_String.h" +#include "OS_Memory.h" + +ACE_RCSID (ace, OS_String, "$Id$") + +#if !defined (ACE_HAS_INLINED_OSCALLS) +# include "OS_String.inl" +#endif /* ACE_HAS_INLINED_OS_CALLS */ + +#if defined (ACE_LACKS_WCSDUP_PROTOTYPE) +extern "C" wchar_t *wcsdup __P ((__const wchar_t *__s)); +#endif /* ACE_LACKS_WCSDUP_PROTOTYPE */ + + +const char * +ACE_OS_String::strnstr (const char *s1, const char *s2, size_t len2) +{ + // Substring length + size_t len1 = ACE_OS_String::strlen (s1); + + // Check if the substring is longer than the string being searched. + if (len2 > len1) + return 0; + + // Go upto + size_t len = len1 - len2; + + for (size_t i = 0; i <= len; i++) + { + if (ACE_OS_String::memcmp (s1 + i, s2, len2) == 0) + // Found a match! Return the index. + return s1 + i; + } + + return 0; +} + +const ACE_WCHAR_T * +ACE_OS_String::strnstr (const ACE_WCHAR_T *s1, const ACE_WCHAR_T *s2, size_t len2) +{ + // Substring length + size_t len1 = ACE_OS_String::strlen (s1); + + // Check if the substring is longer than the string being searched. + if (len2 > len1) + return 0; + + // Go upto + size_t len = len1 - len2; + + for (size_t i = 0; i <= len; i++) + { + if (ACE_OS_String::memcmp (s1 + i, s2, len2 * sizeof (ACE_WCHAR_T)) == 0) + // Found a match! Return the index. + return s1 + i; + } + + return 0; +} + +char * +ACE_OS_String::strdup (const char *s) +{ +#if defined (ACE_HAS_STRDUP_EMULATION) + char *t = (char *) ACE_OS_Memory::malloc (ACE_OS_String::strlen (s) + 1); + if (t == 0) + return 0; + + return ACE_OS_String::strcpy (t, s); +#else + return ::strdup (s); +#endif /* ACE_HAS_STRDUP_EMULATION */ +} + +#if defined (ACE_HAS_WCHAR) +wchar_t * +ACE_OS_String::strdup (const wchar_t *s) +{ +# if defined (ACE_LACKS_WCSDUP) + wchar_t *buffer = + (wchar_t *) ACE_OS_Memory::malloc ((ACE_OS_String::strlen (s) + 1) + * sizeof (wchar_t)); + if (buffer == 0) + return 0; + + return ACE_OS_String::strcpy (buffer, s); +# elif defined (ACE_WCSDUP_EQUIVALENT) + return ACE_WCSDUP_EQUIVALENT (s); +# else /* ACE_LACKS_WCSDUP */ +# if defined (__MINGW32__) + return ::wcsdup (ACE_const_cast(wchar_t*, s)); +# else /* __MINGW32__ */ + return ::wcsdup (s); +# endif /* __MINGW32__ */ +# endif /* ACE_LACKS_WCSDUP */ +} +#endif /* ACE_HAS_WCHAR */ + +#if defined (ACE_LACKS_STRERROR) +/** + * Just returns "Unknown Error" all the time. + */ +char * +ACE_OS_String::strerror_emulation (int errnum) +{ + return "Unknown Error"; +} +#endif /* ACE_LACKS_STRERROR */ + +#if defined (ACE_LACKS_STRCHR) +char * +ACE_OS_String::strchr_emulation (char *s, int c) +{ + for (;;++s) + { + if (*s == c) + return s; + if (*s == 0) + return 0; + } +} + +const char * +ACE_OS_String::strchr_emulation (const char *s, int c) +{ + for (;;++s) + { + if (*s == c) + return s; + if (*s == 0) + return 0; + } +} +#endif /* ACE_LACKS_STRCHR */ + +const char * +ACE_OS_String::strnchr (const char *s, int c, size_t len) +{ + for (size_t i = 0; i < len; i++) + if (s[i] == c) + return s + i; + + return 0; +} + +const ACE_WCHAR_T * +ACE_OS_String::strnchr (const ACE_WCHAR_T *s, ACE_WINT_T c, size_t len) +{ + for (size_t i = 0; i < len; i++) + if (s[i] == ACE_static_cast(ACE_WCHAR_T, c)) + return s + i; + + return 0; +} + +#if defined (ACE_LACKS_STRRCHR) +char * +ACE_OS_String::strrchr_emulation (char *s, int c) +{ + char *p = s + ACE_OS_String::strlen (s); + + while (*p != c) + if (p == s) + return 0; + else + p--; + + return p; +} + +const char * +ACE_OS_String::strrchr_emulation (const char *s, int c) +{ + const char *p = s + ACE_OS_String::strlen (s); + + while (*p != c) + if (p == s) + return 0; + else + p--; + + return p; +} +#endif /* ACE_LACKS_STRRCHR */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSRCHR) +const wchar_t * +ACE_OS_String::wcsrchr_emulation (const wchar_t *s, wint_t c) +{ + const wchar_t *p = s + ACE_OS_String::strlen (s); + + while (*p != ACE_static_cast (wchar_t, c)) + if (p == s) + return 0; + else + p--; + + return p; +} + +wchar_t * +ACE_OS_String::wcsrchr_emulation (wchar_t *s, wint_t c) +{ + wchar_t *p = s + ACE_OS_String::strlen (s); + + while (*p != ACE_static_cast(wchar_t, c)) + if (p == s) + return 0; + else + p--; + + return p; +} +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSRCHR */ + +char * +ACE_OS_String::strecpy (char *s, const char *t) +{ + register char *dscan = s; + register const char *sscan = t; + + while ((*dscan++ = *sscan++) != '\0') + continue; + + return dscan; +} + +#if defined (ACE_HAS_WCHAR) +wchar_t * +ACE_OS_String::strecpy (wchar_t *s, const wchar_t *t) +{ + register wchar_t *dscan = s; + register const wchar_t *sscan = t; + + while ((*dscan++ = *sscan++) != ACE_TEXT_WIDE ('\0')) + continue; + + return dscan; +} +#endif /* ACE_HAS_WCHAR */ + +#if defined (ACE_LACKS_STRCSPN) +size_t +ACE_OS_String::strcspn_emulation (const char *s, const char *reject) +{ + const char *scan; + const char *rej_scan; + int count = 0; + + for (scan = s; *scan; scan++) + { + + for (rej_scan = reject; *rej_scan; rej_scan++) + if (*scan == *rej_scan) + return count; + + count++; + } + + return count; +} +#endif /* ACE_LACKS_STRCSPN */ + +#if defined (ACE_LACKS_STRCASECMP) +int +ACE_OS_String::strcasecmp_emulation (const char *s, const char *t) +{ + const char *scan1 = s; + const char *scan2 = t; + + while (*scan1 != 0 + && ACE_OS_String::to_lower (*scan1) + == ACE_OS_String::to_lower (*scan2)) + { + ++scan1; + ++scan2; + } + + // The following case analysis is necessary so that characters which + // look negative collate low against normal characters but high + // against the end-of-string NUL. + + if (*scan1 == '\0' && *scan2 == '\0') + return 0; + else if (*scan1 == '\0') + return -1; + else if (*scan2 == '\0') + return 1; + else + return ACE_OS_String::to_lower (*scan1) - ACE_OS_String::to_lower (*scan2); +} +#endif /* ACE_LACKS_STRCASECMP */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSICMP) +int +ACE_OS_String::wcsicmp_emulation (const wchar_t *s, const wchar_t *t) +{ + const wchar_t *scan1 = s; + const wchar_t *scan2 = t; + + while (*scan1 != 0 + && ACE_OS_String::to_lower (*scan1) + == ACE_OS_String::to_lower (*scan2)) + { + ++scan1; + ++scan2; + } + + // The following case analysis is necessary so that characters which + // look negative collate low against normal characters but high + // against the end-of-string NUL. + + if (*scan1 == '\0' && *scan2 == '\0') + return 0; + else if (*scan1 == '\0') + return -1; + else if (*scan2 == '\0') + return 1; + else + return ACE_OS_String::to_lower (*scan1) - ACE_OS_String::to_lower (*scan2); +} +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSICMP */ + +#if defined (ACE_LACKS_STRCASECMP) +int +ACE_OS_String::strncasecmp_emulation (const char *s, + const char *t, + size_t len) +{ + const char *scan1 = s; + const char *scan2 = t; + size_t count = 0; + + while (count++ < len + && *scan1 != 0 + && ACE_OS_String::to_lower (*scan1) + == ACE_OS_String::to_lower (*scan2)) + { + ++scan1; + ++scan2; + } + + if (count > len) + return 0; + + // The following case analysis is necessary so that characters which + // look negative collate low against normal characters but high + // against the end-of-string NUL. + + if (*scan1 == '\0' && *scan2 == '\0') + return 0; + else if (*scan1 == '\0') + return -1; + else if (*scan2 == '\0') + return 1; + else + return ACE_OS_String::to_lower (*scan1) - ACE_OS_String::to_lower (*scan2); +} +#endif /* ACE_LACKS_STRCASECMP */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSNICMP) +int +ACE_OS_String::wcsnicmp_emulation (const wchar_t *s, + const wchar_t *t, + size_t len) +{ + const wchar_t *scan1 = s; + const wchar_t *scan2 = t; + size_t count = 0; + + while (count++ < len + && *scan1 != 0 + && ACE_OS_String::to_lower (*scan1) + == ACE_OS_String::to_lower (*scan2)) + { + ++scan1; + ++scan2; + } + + if (count > len) + return 0; + + // The following case analysis is necessary so that characters which + // look negative collate low against normal characters but high + // against the end-of-string NUL. + + if (*scan1 == '\0' && *scan2 == '\0') + return 0; + else if (*scan1 == '\0') + return -1; + else if (*scan2 == '\0') + return 1; + else + return ACE_OS_String::to_lower (*scan1) - ACE_OS_String::to_lower (*scan2); +} +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSNICMP */ + +#if !defined (ACE_HAS_REENTRANT_FUNCTIONS) +char * +ACE_OS_String::strtok_r_emulation (char *s, const char *tokens, char **lasts) +{ + if (s == 0) + s = *lasts; + else + *lasts = s; + if (*s == 0) // We have reached the end + return 0; + int l_org = ACE_OS_String::strlen (s); + s = ::strtok (s, tokens); + if (s == 0) + return 0; + int l_sub = ACE_OS_String::strlen (s); + *lasts = s + l_sub; + if (l_sub != l_org) + *lasts += 1; + return s ; +} +#endif /* !ACE_HAS_REENTRANT_FUNCTIONS */ + +#if !defined (ACE_HAS_MEMCHR) +const void * +ACE_OS_String::memchr_emulation (const void *s, int c, size_t len) +{ + const unsigned char *t = (const unsigned char *) s; + const unsigned char *e = (const unsigned char *) s + len; + + while (t < e) + if (((int) *t) == c) + return t; + else + t++; + + return 0; +} +#endif /*ACE_HAS_MEMCHR*/ + +#if !defined (ACE_HAS_ITOA) +char * +ACE_OS_String::itoa_emulation (int value, char *string, int radix) +{ + char *e = string; + char *b = string; + + // Short circuit if 0 + + if (value == 0) + { + string[0] = '0'; + string[1] = 0; + return string; + } + + // If negative and base 10, print a - and then do the + // number. + + if (value < 0 && radix == 10) + { + string[0] = '-'; + b++; + } + + // Convert to base , but in reverse order + + while (value != 0) + { + int mod = value % radix; + value = value / radix; + + *e++ = (mod < 10) ? '0' + mod : 'a' + mod - 10; + } + + *e-- = 0; + + // Now reverse the string to get the correct result + + while (e > b) + { + char temp = *e; + *e = *b; + *b = temp; + ++b; + --e; + } + + return string; +} +#endif /* !ACE_HAS_ITOA */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_ITOW) +wchar_t * +ACE_OS_String::itow_emulation (int value, wchar_t *string, int radix) +{ + wchar_t *e = string; + wchar_t *b = string; + + // Short circuit if 0 + + if (value == 0) + { + string[0] = '0'; + string[1] = 0; + return string; + } + + // If negative and base 10, print a - and then do the + // number. + + if (value < 0 && radix == 10) + { + string[0] = '-'; + b++; + } + + // Convert to base , but in reverse order + + while (value != 0) + { + int mod = value % radix; + value = value / radix; + + *e++ = (mod < 10) ? '0' + mod : 'a' + mod - 10; + } + + *e-- = 0; + + // Now reverse the string to get the correct result + + while (e > b) + { + wchar_t temp = *e; + *e = *b; + *b = temp; + ++b; + --e; + } + + return string; +} +#endif /* ACE_HAS_WCHAR && ACE_LACKS_ITOW */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCSPN) +size_t +ACE_OS_String::wcscspn_emulation (const wchar_t *s, const wchar_t *reject) +{ + const wchar_t *scan; + const wchar_t *rej_scan; + int count = 0; + + for (scan = s; *scan; scan++) + { + + for (rej_scan = reject; *rej_scan; rej_scan++) + if (*scan == *rej_scan) + return count; + + count++; + } + + return count; +} +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCSPN */ + +// The following wcs*_emulation methods were created based on BSD code: +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * James W. Williams of NASA Goddard Space Flight Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + + + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCAT) +wchar_t * +ACE_OS_String::wcscat_emulation (wchar_t *destination, + const wchar_t *source) +{ + wchar_t *save = destination; + + for (; *destination; ++destination); + while ((*destination++ = *source++)); + return save; +} +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCAT */ + +#if defined (ACE_LACKS_STRSPN) +size_t +ACE_OS_String::strspn_emulation (const char *string, + const char *charset) +{ + const char *p = string; + const char *spanp; + wchar_t c, sc; + + // Skip any characters in charset, excluding the terminating \0. +cont: + c = *p++; + for (spanp = charset; (sc = *spanp++) != 0;) + if (sc == c) + goto cont; + return (p - 1 - string); +} +#endif /* ACE_LACKS_STRSPN */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSSPN) +size_t +ACE_OS_String::wcsspn_emulation (const wchar_t *string, + const wchar_t *charset) +{ + const wchar_t *p = string; + const wchar_t *spanp; + wchar_t c, sc; + + // Skip any characters in charset, excluding the terminating \0. +cont: + c = *p++; + for (spanp = charset; (sc = *spanp++) != 0;) + if (sc == c) + goto cont; + return (p - 1 - string); +} +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSSPN */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSSTR) +wchar_t * +ACE_OS_String::wcsstr_emulation (const wchar_t *string, + const wchar_t *charset) +{ + wchar_t c, sc; + size_t len; + + if ((c = *charset++) != 0) + { + len = strlen(charset); + do + { + do + { + if ((sc = *string++) == 0) + return NULL; + } while (sc != c); + } while (strncmp(string, charset, len) != 0); + string--; + } + + return ACE_const_cast (wchar_t *, string); +} +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSSTR */ + +#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSLEN) +size_t +ACE_OS_String::wcslen_emulation (const ACE_WCHAR_T *string) +{ + const ACE_WCHAR_T *s; + + for (s = string; *s; ++s); + return s - string; +} +#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSLEN */ + +#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCPY) +ACE_WCHAR_T * +ACE_OS_String::wcsncpy_emulation (ACE_WCHAR_T *destination, + const ACE_WCHAR_T *source, + size_t len) +{ + if (len != 0) + { + ACE_WCHAR_T *d = destination; + const ACE_WCHAR_T *s = source; + + do + { + if ((*d++ = *s++) == 0) + { + // NUL pad the remaining n-1 bytes + while (--len != 0) + *d++ = 0; + break; + } + } while (--len != 0); + } + + return destination; +} +#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCPY */ + +#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSCMP) +int +ACE_OS_String::wcscmp_emulation (const ACE_WCHAR_T *string1, + const ACE_WCHAR_T *string2) +{ + while (*string1 == *string2++) + if (*string1++ == 0) + return (0); + return (*string1 - *--string2); +} +#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSCMP */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCPY) +wchar_t * +ACE_OS_String::wcscpy_emulation (wchar_t *destination, + const wchar_t *source) +{ + wchar_t *save = destination; + + for (; (*destination = *source); ++source, ++destination); + return save; +} +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCPY */ + +#if defined (ACE_LACKS_STRPBRK) +char * +ACE_OS_String::strpbrk_emulation (const char *string, + const char *charset) +{ + const char *scanp; + int c, sc; + + while ((c = *string++) != 0) + { + for (scanp = charset; (sc = *scanp++) != 0;) + if (sc == c) + return ACE_const_cast (char *, string - 1); + } + + return NULL; +} +#endif /* ACE_LACKS_STRPBRK */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSPBRK) +wchar_t * +ACE_OS_String::wcspbrk_emulation (const wchar_t *string, + const wchar_t *charset) +{ + const wchar_t *scanp; + int c, sc; + + while ((c = *string++) != 0) + { + for (scanp = charset; (sc = *scanp++) != 0;) + if (sc == c) + return ACE_const_cast (wchar_t *, string - 1); + } + + return NULL; +} +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSPBRK */ + +#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCAT) +ACE_WCHAR_T * +ACE_OS_String::wcsncat_emulation (ACE_WCHAR_T *destination, + const ACE_WCHAR_T *source, + size_t count) +{ + if (count != 0) + { + ACE_WCHAR_T *d = destination; + const ACE_WCHAR_T *s = source; + + while (*d != 0) + d++; + + do + { + if ((*d = *s++) == 0) + break; + + d++; + } while (--count != 0); + + *d = 0; + } + + return destination; +} +#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSCAT */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCHR) +wchar_t * +ACE_OS_String::wcschr_emulation (const wchar_t *string, wint_t c) +{ + for (;*string ; ++string) + if (*string == ACE_static_cast (wchar_t, c)) + return ACE_const_cast (wchar_t *, string); + + return NULL; +} +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCHR */ + +#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCMP) +int +ACE_OS_String::wcsncmp_emulation (const ACE_WCHAR_T *s1, + const ACE_WCHAR_T *s2, + size_t len) +{ + if (len == 0) + return 0; + + do + { + if (*s1 != *s2++) + return (*s1 - *--s2); + if (*s1++ == 0) + break; + } while (--len != 0); + + return 0; +} +#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCMP */ + +#if defined (ACE_LACKS_STRTOL) +long +ACE_OS_String::strtol_emulation (const char *nptr, char **endptr, int base) +{ + register const char *s = nptr; + register unsigned long acc; + register int c; + register unsigned long cutoff; + register int neg = 0, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; + cutlim = cutoff % (unsigned long)base; + cutoff /= (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? LONG_MIN : LONG_MAX; + errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = any ? (char *)s - 1 : (char *)nptr; + return (acc); +} +#endif /* ACE_LACKS_STRTOL */ + +#if defined (ACE_LACKS_STRTOUL) +unsigned long +ACE_OS_String::strtoul_emulation (const char *nptr, + char **endptr, + register int base) +{ + register const char *s = nptr; + register unsigned long acc; + register int c; + register unsigned long cutoff; + register int neg = 0, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; + cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = any ? (char *)s - 1 : (char *)nptr; + return (acc); +} +#endif /* ACE_LACKS_STRTOUL */ + +char * +ACE_OS_String::strsncpy (char *dst, const char *src, size_t maxlen) +{ + register char *rdst = dst; + register const char *rsrc = src; + register size_t rmaxlen = maxlen; + + if (rmaxlen > 0) + { + *rdst = '\0'; + if (rsrc != 0) + strncat (rdst, rsrc, --rmaxlen); + } + return dst; +} + +ACE_WCHAR_T * +ACE_OS_String::strsncpy (ACE_WCHAR_T *dst, const ACE_WCHAR_T *src, size_t maxlen) +{ + register ACE_WCHAR_T *rdst = dst; + register const ACE_WCHAR_T *rsrc = src; + register size_t rmaxlen = maxlen; + + if (rmaxlen > 0) + { + *rdst = ACE_TEXT_WIDE ('\0'); + if (rsrc != 0) + strncat (rdst, rsrc ,--rmaxlen); + } + return dst; +} diff --git a/ace/OS/OS_String.h b/ace/OS/OS_String.h new file mode 100644 index 00000000000..701622c4386 --- /dev/null +++ b/ace/OS/OS_String.h @@ -0,0 +1,596 @@ +// -*- C++ -*- +//============================================================================= +/** + * @file OS_String.h + * + * $Id$ + * + * @brief Contains definition of class ACE_OS_String. + * + * @author Doug Schmidt + * @author Jesper S. M|ller + * @author and a cast of thousands... + */ +//============================================================================= + +#ifndef ACE_OS_STRING_H +#define ACE_OS_STRING_H +#include "ace/pre.h" + +#include "ace/config-all.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "Basic_Types.h" +#include /**/ + +#if defined (ACE_USES_STD_NAMESPACE_FOR_STDC_LIB) && \ + (ACE_USES_STD_NAMESPACE_FOR_STDC_LIB != 0) +using std::size_t; +using std::wint_t; +#endif /* ACE_USES_STD_NAMESPACE_FOR_STDC_LIB */ + +/** + * @class ACE_OS_String + * + * @brief This class includes functions available in string.h and ctype.h. + */ +class ACE_OS_Export ACE_OS_String +{ +public: + /** @name Functions from + * + * Included are the functions defined in and their + * equivalents. + * + * @todo To be complete, we should add strcoll, and strxfrm. + */ + //@{ + + /// Finds characters in a buffer (const void version). + static const void *memchr (const void *s, int c, size_t len); + + /// Finds characters in a buffer (void version). + static void *memchr (void *s, int c, size_t len); + + /// Compares two buffers. + static int memcmp (const void *t, const void *s, size_t len); + + /// Copies one buffer to another. + static void *memcpy (void *t, const void *s, size_t len); + + /// Moves one buffer to another. + static void *memmove (void *t, const void *s, size_t len); + + /// Fills a buffer with a character value. + static void *memset (void *s, int c, size_t len); + + /// Appends a string to another string (char version). + static char *strcat (char *s, const char *t); + +#if defined (ACE_HAS_WCHAR) + /// Appends a string to another string (wchar_t version). + static wchar_t *strcat (wchar_t *s, const wchar_t *t); +#endif /* ACE_HAS_WCHAR */ + + /// Finds the first occurance of a character in a string (const char + /// version). + static const char *strchr (const char *s, int c); + +#if defined (ACE_HAS_WCHAR) + /// Finds the first occurance of a character in a string (const wchar_t + /// version). + static const wchar_t *strchr (const wchar_t *s, wint_t c); +#endif /* ACE_HAS_WCHAR */ + + /// Finds the first occurance of a character in a string (char version). + static char *strchr (char *s, int c); + +#if defined (ACE_HAS_WCHAR) + /// Finds the first occurance of a character in a string (wchar_t version). + static wchar_t *strchr (wchar_t *s, wint_t c); +#endif /* ACE_HAS_WCHAR */ + + /// Compares two strings (char version). + static int strcmp (const char *s, const char *t); + + /// Compares two strings (wchar_t version). + static int strcmp (const ACE_WCHAR_T *s, const ACE_WCHAR_T *t); + + /// Copies a string (char version). + static char *strcpy (char *s, const char *t); + +#if defined (ACE_HAS_WCHAR) + /// Copies a string (wchar_t version). + static wchar_t *strcpy (wchar_t *s, const wchar_t *t); +#endif /* ACE_HAS_WCHAR */ + + /// Searches for the first substring without any of the specified + /// characters and returns the size of the substring (char version). + static size_t strcspn (const char *s, const char *reject); + +#if defined (ACE_HAS_WCHAR) + /// Searches for the first substring without any of the specified + /// characters and returns the size of the substring (wchar_t version). + static size_t strcspn (const wchar_t *s, const wchar_t *reject); +#endif /* ACE_HAS_WCHAR */ + + /// Returns a system error message. + static char *strerror (int errnum); + + /// Finds the length of a string (char version). + static size_t strlen (const char *s); + + /// Finds the length of a string (ACE_WCHAR_T version). + static size_t strlen (const ACE_WCHAR_T *s); + + /// Appends part of a string to another string (char version). + static char *strncat (char *s, const char *t, size_t len); + + /// Appends part of a string to another string (wchar_t version). + static ACE_WCHAR_T *strncat (ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len); + + /// Compares two arrays (char version). + static int strncmp (const char *s, const char *t, size_t len); + + /// Compares two arrays (wchar_t version). + static int strncmp (const ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len); + + /// Copies an array (char version) + static char *strncpy (char *s, const char *t, size_t len); + + /// Copies an array (ACE_WCHAR_T version) + static ACE_WCHAR_T *strncpy (ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len); + + /// Searches for characters in a string (const char version). + static const char *strpbrk (const char *s1, const char *s2); + +#if defined (ACE_HAS_WCHAR) + /// Searches for characters in a string (const wchar_t version). + static const wchar_t *strpbrk (const wchar_t *s1, const wchar_t *s2); +#endif /* ACE_HAS_WCHAR */ + + /// Searches for characters in a string (char version). + static char *strpbrk (char *s1, const char *s2); + +#if defined (ACE_HAS_WCHAR) + /// Searches for characters in a string (wchar_t version). + static wchar_t *strpbrk (wchar_t *s1, const wchar_t *s2); +#endif /* ACE_HAS_WCHAR */ + + /// Finds the last occurance of a character in a string (const char + /// version). + static const char *strrchr (const char *s, int c); + +#if defined (ACE_HAS_WCHAR) + /// Finds the last occurance of a character in a string (const wchar_t + /// version). + static const wchar_t *strrchr (const wchar_t *s, wint_t c); +#endif /* ACE_HAS_WCHAR */ + + /// Finds the last occurance of a character in a string (char version). + static char *strrchr (char *s, int c); + +#if defined (ACE_HAS_WCHAR) + /// Finds the last occurance of a character in a string (wchar_t version). + static wchar_t *strrchr (wchar_t *s, wint_t c); +#endif /* ACE_HAS_WCHAR */ + + /// Searches for the first substring containing only the specified + /// characters and returns the size of the substring (char version). + static size_t strspn (const char *s1, const char *s2); + +#if defined (ACE_HAS_WCHAR) + /// Searches for the first substring containing only the specified + /// characters and returns the size of the substring (wchar_t version). + static size_t strspn (const wchar_t *s1, const wchar_t *s2); +#endif /* ACE_HAS_WCHAR */ + + /// Finds the first occurance of a substring in a string (const char + /// version). + static const char *strstr (const char *s, const char *t); + +#if defined (ACE_HAS_WCHAR) + /// Finds the first occurance of a substring in a string (const wchar_t + /// version). + static const wchar_t *strstr (const wchar_t *s, const wchar_t *t); +#endif /* ACE_HAS_WCHAR */ + + /// Finds the first occurance of a substring in a string (char version). + static char *strstr (char *s, const char *t); + +#if defined (ACE_HAS_WCHAR) + /// Finds the first occurance of a substring in a string (wchar_t version). + static wchar_t *strstr (wchar_t *s, const wchar_t *t); +#endif /* ACE_HAS_WCHAR */ + + /// Finds the next token in a string (char version). + static char *strtok (char *s, const char *tokens); + +#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOK) + /// Finds the next token in a string (wchar_t version). + static wchar_t *strtok (wchar_t *s, const wchar_t *tokens); +#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOK */ + + //@} + + /** @name Functions from + * + * Included are the functions defined in and their + * equivalents. + * + * Since they are often implemented as macros, we don't use the same name + * here. Instead, we change by prepending "ace_" (with the exception of + * to_lower). + * + * @todo To be complete, we should add: isalnum, isalpha, iscntrl + * isdigit, isgraph, islower, ispunct, isupper, isxdigit, and toupper. + */ + //@{ + + /// Returns true if the character is a printable character. + static int ace_isprint (const ACE_TCHAR c); + + /// Returns true if the character is a space character. + static int ace_isspace (const ACE_TCHAR c); + + /// Converts a character to lower case (char version). + static int to_lower (int c); + +#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_TOWLOWER) + /// Converts a character to lower case (wchar_t version). + static wint_t to_lower (wint_t c); +#endif /* ACE_HAS_WCHAR && !ACE_LACKS_TOWLOWER */ + + //@} + + /** @name Non-standard functions + * + * These functions aren't in the standard. + * + */ + //@{ + + /// Converts an integer to a string. + static char *itoa (int value, char *string, int radix); + +#if defined (ACE_HAS_WCHAR) + /// Converts an integer to a string. + static wchar_t *itoa (int value, wchar_t *string, int radix); +#endif /* ACE_HAS_WCHAR */ + + /// Compares two strings (case insensitive const char version). + static int strcasecmp (const char *s, const char *t); + +#if defined (ACE_HAS_WCHAR) + /// Compares two strings (case insensitive const wchar_t version). + static int strcasecmp (const wchar_t *s, const wchar_t *t); +#endif /* ACE_HAS_WCHAR */ + + /// Finds the first occurance of a character in an array (const char + /// version). + static const char *strnchr (const char *s, int c, size_t len); + + /// Finds the first occurance of a character in an array (const ACE_WCHAR_T + /// version). + static const ACE_WCHAR_T *strnchr (const ACE_WCHAR_T *s, ACE_WINT_T c, size_t len); + + /// Finds the first occurance of a character in an array (char version). + static char *strnchr (char *s, int c, size_t len); + + /// Finds the first occurance of a character in an array (ACE_WCHAR_T version). + static ACE_WCHAR_T *strnchr (ACE_WCHAR_T *s, ACE_WINT_T c, size_t len); + + /// Compares two arrays (case insensitive const char version). + static int strncasecmp (const char *s, const char *t, size_t len); + +#if defined (ACE_HAS_WCHAR) + /// Compares two arrays (case insensitive const wchar_t version). + static int strncasecmp (const wchar_t *s, const wchar_t *t, size_t len); +#endif /* ACE_HAS_WCHAR */ + + /// Copies a string, but returns a pointer to the end of the + /// copied region (char version). + static char *strecpy (char *des, const char *src); + +#if defined (ACE_HAS_WCHAR) + /// Copies a string, but returns a pointer to the end of the + /// copied region (wchar_t version). + static wchar_t *strecpy (wchar_t *s, const wchar_t *t); +#endif /* ACE_HAS_WCHAR */ + + /// This is a "safe" c string copy function (char version). + /** + * Unlike strncpy() this function will always add a terminating '\0' + * char if maxlen > 0. So the user doesn't has to provide an extra + * '\0' if the user wants a '\0' terminated dst. The function + * doesn't check for a 0 , because this will give problems + * anyway. When is 0 an empty string is made. We do not + * "touch" * if maxlen is 0. Returns . Care should be + * taken when replacing strncpy() calls, because in some cases a + * strncpy() user is using the "not '\0' terminating" feature from + * strncpy(). This happens most when the call to strncpy() was + * optimized by using a maxlen which is 1 smaller than the size + * because there's always written a '\0' inside this last position. + * Very seldom it's possible that the '\0' padding feature from + * strncpy() is needed. + */ + static char *strsncpy (char *dst, + const char *src, + size_t maxlen); + + /// This is a "safe" c string copy function (wchar_t version). + /** + * Unlike strncpy() this function will always add a terminating '\0' + * char if maxlen > 0. So the user doesn't has to provide an extra + * '\0' if the user wants a '\0' terminated dst. The function + * doesn't check for a 0 , because this will give problems + * anyway. When is 0 an empty string is made. We do not + * "touch" * if maxlen is 0. Returns . Care should be + * taken when replacing strncpy() calls, because in some cases a + * strncpy() user is using the "not '\0' terminating" feature from + * strncpy(). This happens most when the call to strncpy() was + * optimized by using a maxlen which is 1 smaller than the size + * because there's always written a '\0' inside this last position. + * Very seldom it's possible that the '\0' padding feature from + * strncpy() is needed. + */ + static ACE_WCHAR_T *strsncpy (ACE_WCHAR_T *dst, + const ACE_WCHAR_T *src, + size_t maxlen); + + /// Finds the first occurance of a substring in an array (const char + /// version). + static const char *strnstr (const char *s, const char *t, size_t len); + + /// Finds the first occurance of a substring in an array (const wchar_t + /// version). + static const ACE_WCHAR_T *strnstr (const ACE_WCHAR_T *s, + const ACE_WCHAR_T *t, + size_t len); + + /// Finds the first occurance of a substring in an array (char version). + static char *strnstr (char *s, const char *t, size_t len); + + /// Finds the first occurance of a substring in an array (wchar_t version). + static ACE_WCHAR_T *strnstr (ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len); + + /// Returns a malloced duplicated string (char version). + static char *strdup (const char *s); + +#if defined (ACE_HAS_WCHAR) + /// Returns a malloced duplicated string (wchar_t version). + static wchar_t *strdup (const wchar_t *s); +#endif /* ACE_HAS_WCHAR */ + + /// Finds the next token in a string (safe char version). + static char *strtok_r (char *s, const char *tokens, char **lasts); + +#if !defined (ACE_LACKS_STRTOD) + /// Converts a string to a double value (char version). + static double strtod (const char *s, char **endptr); +#endif /* !ACE_LACKS_STRTOD */ + +#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOD) + /// Converts a string to a double value (wchar_t version). + static double strtod (const wchar_t *s, wchar_t **endptr); +#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOD */ + + /// Converts a string to a long value (char version). + static long strtol (const char *s, char **ptr, int base); + +#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOL) + /// Converts a string to a long value (wchar_t version). + static long strtol (const wchar_t *s, wchar_t **ptr, int base); +#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOL */ + + /// Converts a string to an unsigned long value (char version). + static unsigned long strtoul (const char *s, char **ptr, int base); + +#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOUL) + /// Converts a string to an unsigned long value (wchar_t version). + static unsigned long strtoul (const wchar_t *s, wchar_t **ptr, int base); +#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOUL */ + + //@} + +private: + + /** @name Emulation + * + * These methods are provided for platforms that do not have a native + * implementation. + */ + //@{ + +#if !defined (ACE_HAS_ITOA) + /// Emulated itoa - Converts an integer to a string. + static char *itoa_emulation (int value, char *string, int radix); +#endif /* !ACE_HAS_ITOA */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_ITOW) + /// Emulated itow - Converts an integer to a string. + static wchar_t *itow_emulation (int value, wchar_t *string, int radix); +#endif /* ACE_HAS_WCHAR && ACE_LACKS_ITOW */ + +#if !defined (ACE_HAS_MEMCHR) + /// Emulated memchr - Finds a character in a buffer. + static const void *memchr_emulation (const void *s, int c, size_t len); +#endif /* ACE_HAS_MEMCHR */ + +#if defined (ACE_LACKS_STRCASECMP) + /// Emulated strcasecmp - Performs a case insensitive comparison of strings. + static int strcasecmp_emulation (const char *s, const char *t); + + /// Emulated strncasecmp - Performs a case insensitvie comparison of arrays. + static int strncasecmp_emulation (const char *s, const char *t, size_t len); +#endif /* ACE_LACKS_STRCASECMP */ + +#if defined (ACE_LACKS_STRCSPN) + /// Emulated strcspn - Finds a substring in a string. + static size_t strcspn_emulation (const char *s, const char *reject); +#endif /* ACE_LACKS_STRCSPN */ + +#if defined (ACE_LACKS_STRCHR) + /// Emulated strchr (char version) - Finds the first occurance of a + /// character in a string. + static char *strchr_emulation (char *s, int c); + + /// Emulated strchr (const char version) - Finds the first occurance of a + /// character in a string. + static const char *strchr_emulation (const char *s, int c); +#endif /* ACE_LACKS_STRCHR */ + +#if defined (ACE_LACKS_STRERROR) + /// Emulated strerror - Returns a system error message. + static char *strerror_emulation (int errnum); +#endif /* ACE_LACKS_STRERROR */ + +#if defined (ACE_LACKS_STRPBRK) + /// Emulated strpbrk - Searches for characters in a string. + static char *strpbrk_emulation (const char *string, + const char *charset); +#endif /* ACE_LACKS_STRPBRK */ + +#if defined (ACE_LACKS_STRRCHR) + /// Emulated strrchr (char version) - Finds the last occurance of a + /// character in a string. + static char *strrchr_emulation (char *s, int c); + + /// Emulated strrchr (const char version) - Finds the last occurance of a + /// character in a string. + static const char *strrchr_emulation (const char *s, int c); +#endif /* ACE_LACKS_STRRCHR */ + +#if !defined (ACE_HAS_REENTRANT_FUNCTIONS) + /// Emulated strtok_r. + static char *strtok_r_emulation (char *s, const char *tokens, char **lasts); +#endif /* !ACE_HAS_REENTRANT_FUNCTIONS */ + +#if defined (ACE_LACKS_STRSPN) + /// Emulated wcsspn. + static size_t strspn_emulation (const char *string, + const char *charset); +#endif /* ACE_LACKS_STRSPN */ + +#if defined (ACE_LACKS_STRTOL) + static long strtol_emulation (const char *nptr, char **endptr, int base); +#endif /* ACE_LACKS_STRTOL */ + +#if defined (ACE_LACKS_STRTOUL) + static unsigned long strtoul_emulation (const char *nptr, + char **endptr, + int base); +#endif /* ACE_LACKS_STRTOUL */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCAT) + /// Emulated wcscat - Appends a string. + static wchar_t *wcscat_emulation (wchar_t *destination, + const wchar_t *source); +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCAT */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCHR) + /// Emulated wcschr - Finds a character in a string. + static wchar_t *wcschr_emulation (const wchar_t *string, wint_t c); +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCHR */ + +#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSCMP) + /// Emulated wcscmp - Compares strings. + static int wcscmp_emulation (const ACE_WCHAR_T *string1, const ACE_WCHAR_T *string2); +#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSCMP */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCPY) + /// Emulated wcscpy - Copies a string. + static wchar_t *wcscpy_emulation (wchar_t *destination, + const wchar_t *source); +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCPY */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSICMP) + /// Emulated wcsicmp - Performs a case insensitive comparison of strings. + static int wcsicmp_emulation (const wchar_t *string1, + const wchar_t *string2); +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSICMP */ + +#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSLEN) + /// Emulated wcslen - Returns the length of a string. + static size_t wcslen_emulation (const ACE_WCHAR_T *string); +#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSLEN */ + +#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCAT) + /// Emulated wcscat - Appends a string. + static ACE_WCHAR_T *wcsncat_emulation (ACE_WCHAR_T *destination, + const ACE_WCHAR_T *source, + size_t count); +#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSCAT */ + +#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCMP) + /// Emulated wcsncmp - Compares two arrays. + static int wcsncmp_emulation (const ACE_WCHAR_T *string1, + const ACE_WCHAR_T *string2, + size_t len); +#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCMP */ + +#if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCPY) + /// Emulated wcsncpy - Copies an array. + static ACE_WCHAR_T *wcsncpy_emulation (ACE_WCHAR_T *destination, + const ACE_WCHAR_T *source, + size_t len); +#endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCPY */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSNICMP) + /// Emulated wcsnicmp - Performs a case insensitive comparison of two + /// arrays + static int wcsnicmp_emulation (const wchar_t *string1, + const wchar_t *string2, + size_t len); +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSNICMP */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSPBRK) + /// Emulated wcspbrk - Searches for characters in a string. + static wchar_t *wcspbrk_emulation (const wchar_t *string, + const wchar_t *charset); +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSPBRK */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSRCHR) + /// Emulated wcsrchr (wchar_t version) - Finds the last occurance of a + /// character in a string. + static wchar_t *wcsrchr_emulation (wchar_t *string, wint_t c); + + /// Emulated wcsrchr (const wchar_t version) - Finds the last occurance of a + /// character in a string. + static const wchar_t *wcsrchr_emulation (const wchar_t *string, wint_t c); +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSRCHR */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSCSPN) + /// Emulated wcscspn. + static size_t wcscspn_emulation (const wchar_t *string, + const wchar_t *reject); +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSCSPN */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSSPN) + /// Emulated wcsspn. + static size_t wcsspn_emulation (const wchar_t *string, + const wchar_t *charset); +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSSPN */ + +#if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSSTR) + /// Emulated wcsstr - Performs a case insensitive comparison of two strings. + static wchar_t *wcsstr_emulation (const wchar_t *string, + const wchar_t *charset); +#endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSSTR */ + + //@} +}; + +# if defined (ACE_HAS_INLINED_OSCALLS) +# if defined (ACE_INLINE) +# undef ACE_INLINE +# endif /* ACE_INLINE */ +# define ACE_INLINE inline +# include "OS_String.inl" +# endif /* ACE_HAS_INLINED_OSCALLS */ + +#include "ace/post.h" +#endif /* ACE_OS_STRING_H */ diff --git a/ace/OS/OS_String.inl b/ace/OS/OS_String.inl new file mode 100644 index 00000000000..b240c334a8b --- /dev/null +++ b/ace/OS/OS_String.inl @@ -0,0 +1,731 @@ +// -*- C++ -*- +//============================================================================= +/** + * @file OS_String.inl + * + * $Id$ + * + * @brief Contains inline definitions for class ACE_OS_String. + */ +//============================================================================= + +#if defined (ACE_HAS_PACE) +# include /**/ "pace/string.h" +# include /**/ "pace/ctype.h" +# include /**/ "pace/stdlib.h" +#endif /* ACE_HAS_PACE */ + +// Matthew Stevens 7-10-95 Fix GNU GCC 2.7 for memchr() problem. +#if defined (ACE_HAS_GNU_CSTRING_H) +// Define this file to keep /usr/include/memory.h from being included. +# include /**/ +#else +# if !defined (ACE_LACKS_MEMORY_H) +# include /**/ +# endif /* !ACE_LACKS_MEMORY_H */ +#endif /* ACE_HAS_GNU_CSTRING_H */ + +#if !defined (ACE_PSOS_DIAB_MIPS) +# include /**/ +# include /**/ +#endif /* !ACE_PSOS_DIAB_MIPS */ + +// We need strings.h on some platforms (qnx-neutrino, for example) +// to get the declaration for strcasecmp +#if defined (ACE_HAS_STRINGS) +# include /**/ +#endif /* ACE_HAS_STRINGS */ + +#include /**/ + +ACE_INLINE const void * +ACE_OS_String::memchr (const void *s, int c, size_t len) +{ +#if defined (ACE_HAS_PACE) + return pace_memchr (s, c, len); +#elif defined (ACE_HAS_MEMCHR) + return ::memchr (s, c, len); +#else /* ACE_HAS_MEMCHR */ + return ACE_OS_String::memchr_emulation (s, c, len); +#endif /* ACE_HAS_MEMCHR */ +} + +ACE_INLINE void * +ACE_OS_String::memchr (void *s, int c, size_t len) +{ + return ACE_const_cast (void *, + ACE_OS_String::memchr (ACE_static_cast (const void *, s), c, len)); +} + + +ACE_INLINE int +ACE_OS_String::memcmp (const void *t, const void *s, size_t len) +{ +#if defined (ACE_HAS_PACE) + return pace_memcmp (t, s, len); +#else + return ::memcmp (t, s, len); +#endif /* ACE_HAS_PACE */ +} + + +ACE_INLINE void * +ACE_OS_String::memcpy (void *t, const void *s, size_t len) +{ +#if defined (ACE_HAS_PACE) + return pace_memcpy (t, s, len); +#else + return ::memcpy (t, s, len); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE void * +ACE_OS_String::memmove (void *t, const void *s, size_t len) +{ +#if defined (ACE_HAS_PACE) + return pace_memmove (t, s, len); +#else + return ::memmove (t, s, len); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE void * +ACE_OS_String::memset (void *s, int c, size_t len) +{ +#if defined (ACE_HAS_PACE) + return pace_memset (s, c, len); +#else + return ::memset (s, c, len); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE char * +ACE_OS_String::strcat (char *s, const char *t) +{ +#if defined (ACE_HAS_PACE) + return pace_strcat (s, t); +#else + return ::strcat (s, t); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE wchar_t * +ACE_OS_String::strcat (wchar_t *s, const wchar_t *t) +{ +# if defined (ACE_LACKS_WCSCAT) + return ACE_OS_String::wcscat_emulation (s, t); +# else /* ACE_LACKS_WCSCAT */ + return ::wcscat (s, t); +# endif /* ACE_LACKS_WCSCAT */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE const char * +ACE_OS_String::strchr (const char *s, int c) +{ +#if defined (ACE_HAS_PACE) + return pace_strchr (s, c); +#elif defined (ACE_LACKS_STRCHR) + return ACE_OS_String::strchr_emulation (s, c); +#else /* ! ACE_LACKS_STRCHR */ + return (const char *) ::strchr (s, c); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE const wchar_t * +ACE_OS_String::strchr (const wchar_t *s, wint_t c) +{ +# if defined (ACE_LACKS_WCSCHR) + return ACE_OS_String::wcschr_emulation (s, c); +# else /* ACE_LACKS_WCSCHR */ + return ::wcschr (s, c); +# endif /* ACE_LACKS_WCSCHR */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE char * +ACE_OS_String::strchr (char *s, int c) +{ +#if defined (ACE_HAS_PACE) + return pace_strchr (s, c); +#elif defined (ACE_LACKS_STRCHR) + return ACE_OS_String::strchr_emulation (s, c); +#else /* ! ACE_LACKS_STRCHR */ + return ::strchr (s, c); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE wchar_t * +ACE_OS_String::strchr (wchar_t *s, wint_t c) +{ + return ACE_const_cast (wchar_t *, + ACE_OS_String::strchr (ACE_static_cast (const wchar_t *, s), c)); +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE int +ACE_OS_String::strcmp (const char *s, const char *t) +{ +#if defined (ACE_HAS_PACE) + return pace_strcmp (s, t); +#else + return ::strcmp (s, t); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS_String::strcmp (const ACE_WCHAR_T *s, const ACE_WCHAR_T *t) +{ +# if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSCMP) + return ACE_OS_String::wcscmp_emulation (s, t); +# else /* !ACE_HAS_WCHAR || ACE_LACKS_WCSCMP */ + return ::wcscmp (s, t); +# endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSCMP */ +} + +ACE_INLINE char * +ACE_OS_String::strcpy (char *s, const char *t) +{ +#if defined (ACE_HAS_PACE) + return pace_strcpy (s, t); +#else /* ACE_HAS_PACE */ + return ::strcpy (s, t); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE wchar_t * +ACE_OS_String::strcpy (wchar_t *s, const wchar_t *t) +{ +# if defined (ACE_LACKS_WCSCPY) + return ACE_OS_String::wcscpy_emulation (s, t); +# else /* ACE_LACKS_WCSCPY */ + return ::wcscpy (s, t); +# endif /* ACE_LACKS_WCSCPY */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE size_t +ACE_OS_String::strcspn (const char *s, const char *reject) +{ +#if defined (ACE_HAS_PACE) + return pace_strcspn (s, reject); +#elif defined (ACE_LACKS_STRCSPN) + return ACE_OS_String::strcspn_emulation (s, reject); +#else /* ACE_LACKS_STRCSPN */ + return ::strcspn (s, reject); +#endif /* ACE_LACKS_STRCSPN */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE size_t +ACE_OS_String::strcspn (const wchar_t *s, const wchar_t *reject) +{ +# if defined (ACE_LACKS_WCSCSPN) + return ACE_OS_String::wcscspn_emulation (s, reject); +# else /* ACE_LACKS_WCSCSPN */ + return ::wcscspn (s, reject); +# endif /* ACE_LACKS_WCSCSPN */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE char * +ACE_OS_String::strerror (int errnum) +{ +#if defined (ACE_LACKS_STRERROR) + return ACE_OS_String::strerror_emulation (errnum); +#else /* ACE_LACKS_STRERROR */ + return ::strerror (errnum); +#endif /* ACE_LACKS_STRERROR */ +} + +ACE_INLINE size_t +ACE_OS_String::strlen (const char *s) +{ +#if defined (ACE_HAS_PACE) + return pace_strlen (s); +#else /* ACE_HAS_PACE */ + return ::strlen (s); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE size_t +ACE_OS_String::strlen (const ACE_WCHAR_T *s) +{ +# if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSLEN) + return ACE_OS_String::wcslen_emulation (s); +# else /* !ACE_HAS_WCHAR || ACE_LACKS_WCSLEN */ + return ::wcslen (s); +# endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSLEN */ +} + +ACE_INLINE char * +ACE_OS_String::strncat (char *s, const char *t, size_t len) +{ +#if defined (ACE_HAS_PACE) + return pace_strncat (s, t, len); +#else /* ACE_HAS_PACE */ + return ::strncat (s, t, len); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE ACE_WCHAR_T * +ACE_OS_String::strncat (ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len) +{ +# if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCAT) + return ACE_OS_String::wcsncat_emulation (s, t, len); +# else /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCAT */ + return ::wcsncat (s, t, len); +# endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCAT */ +} + +ACE_INLINE int +ACE_OS_String::strncmp (const char *s, const char *t, size_t len) +{ +#if defined (ACE_HAS_PACE) + return pace_strncmp (s, t, len); +#else /* ACE_HAS_PACE */ + return ::strncmp (s, t, len); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS_String::strncmp (const ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len) +{ +# if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCMP) + return ACE_OS_String::wcsncmp_emulation (s, t, len); +# else /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCMP */ + return ::wcsncmp (s, t, len); +# endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCMP */ +} + +ACE_INLINE char * +ACE_OS_String::strncpy (char *s, const char *t, size_t len) +{ +#if defined (ACE_HAS_PACE) + return pace_strncpy (s, t, len); +#else /* ACE_HAS_PACE */ + return ::strncpy (s, t, len); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE ACE_WCHAR_T * +ACE_OS_String::strncpy (ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len) +{ +# if !defined (ACE_HAS_WCHAR) || defined (ACE_LACKS_WCSNCPY) + return ACE_OS_String::wcsncpy_emulation (s, t, len); +# else /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCPY */ + return ::wcsncpy (s, t, len); +# endif /* !ACE_HAS_WCHAR || ACE_LACKS_WCSNCPY */ +} + +ACE_INLINE const char * +ACE_OS_String::strpbrk (const char *s1, const char *s2) +{ +#if defined (ACE_HAS_PACE) + return (const char*) pace_strpbrk (s1, s2); +#elif defined (ACE_LACKS_STRPBRK) + return ACE_OS_String::strpbrk_emulation (s1, s2); +#else /* ACE_HAS_PACE */ + return (const char *) ::strpbrk (s1, s2); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE const wchar_t * +ACE_OS_String::strpbrk (const wchar_t *s, const wchar_t *t) +{ +# if defined (ACE_LACKS_WCSPBRK) + return ACE_OS_String::wcspbrk_emulation (s, t); +# else /* ACE_LACKS_WCSPBRK */ + return ::wcspbrk (s, t); +# endif /* ACE_LACKS_WCSPBRK */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE char * +ACE_OS_String::strpbrk (char *s1, const char *s2) +{ +#if defined (ACE_HAS_PACE) + return pace_strpbrk (s1, s2); +#elif defined (ACE_LACKS_STRPBRK) + return ACE_OS_String::strpbrk_emulation (s1, s2); +#else /* ACE_HAS_PACE */ + return ::strpbrk (s1, s2); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE wchar_t * +ACE_OS_String::strpbrk (wchar_t *s, const wchar_t *t) +{ + return ACE_const_cast (wchar_t *, + ACE_OS_String::strpbrk (ACE_static_cast (const wchar_t *, s), t)); +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE const char * +ACE_OS_String::strrchr (const char *s, int c) +{ +#if defined (ACE_HAS_PACE) + return (const char*) pace_strrchr (s, c); +#elif defined (ACE_LACKS_STRRCHR) + return ACE_OS_String::strrchr_emulation (s, c); +#else /* ! ACE_LACKS_STRRCHR */ + return (const char *) ::strrchr (s, c); +#endif /* ! ACE_LACKS_STRRCHR */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE const wchar_t * +ACE_OS_String::strrchr (const wchar_t *s, wint_t c) +{ +#if defined (ACE_LACKS_WCSRCHR) + return ACE_OS_String::wcsrchr_emulation (s, c); +#else /* ! ACE_LACKS_WCSRCHR */ + return (const wchar_t *) ::wcsrchr (s, c); +#endif /* ! ACE_LACKS_WCSRCHR */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE char * +ACE_OS_String::strrchr (char *s, int c) +{ +#if defined (ACE_HAS_PACE) + return pace_strrchr (s, c); +#elif defined (ACE_LACKS_STRRCHR) + return ACE_OS_String::strrchr_emulation (s, c); +#else /* ! ACE_LACKS_STRRCHR */ + return ::strrchr (s, c); +#endif /* ! ACE_LACKS_STRRCHR */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE wchar_t * +ACE_OS_String::strrchr (wchar_t *s, wint_t c) +{ + return ACE_const_cast (wchar_t *, + ACE_OS_String::strrchr (ACE_static_cast (const wchar_t *, s), c)); +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE size_t +ACE_OS_String::strspn (const char *s, const char *t) +{ +#if defined (ACE_HAS_PACE) + return pace_strspn (s, t); +#elif defined (ACE_LACKS_STRSPN) + return ACE_OS_String::strspn_emulation (s, t); +#else /* ACE_HAS_PACE */ + return ::strspn (s, t); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE size_t +ACE_OS_String::strspn (const wchar_t *s, const wchar_t *t) +{ +# if defined (ACE_LACKS_WCSSPN) + return ACE_OS_String::wcsspn_emulation (s, t); +# else /* ACE_LACKS_WCSSPN */ + return ::wcsspn (s, t); +# endif /* ACE_LACKS_WCSSPN */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE const char * +ACE_OS_String::strstr (const char *s, const char *t) +{ +#if defined (ACE_HAS_PACE) + return pace_strstr (s, t); +#else /* ACE_HAS_PACE */ + return (const char *) ::strstr (s, t); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE const wchar_t * +ACE_OS_String::strstr (const wchar_t *s, const wchar_t *t) +{ +# if defined (ACE_LACKS_WCSSTR) + return ACE_OS_String::wcsstr_emulation (s, t); +# else /* ACE_LACKS_WCSSTR */ +# if defined (ACE_HAS_XPG4_MULTIBYTE_CHAR) + return (const wchar_t *) ::wcswcs (s, t); +# else + return (const wchar_t *) ::wcsstr (s, t); +# endif /* ACE_HAS_XPG4_MULTIBYTE_CHAR */ +# endif /* ACE_LACKS_WCSSTR */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE char * +ACE_OS_String::strstr (char *s, const char *t) +{ +#if defined (ACE_HAS_PACE) + return pace_strstr (s, t); +#else /* ACE_HAS_PACE */ + return ::strstr (s, t); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE wchar_t * +ACE_OS_String::strstr (wchar_t *s, const wchar_t *t) +{ +# if defined (ACE_LACKS_WCSSTR) + return ACE_OS_String::wcsstr_emulation (s, t); +# else /* ACE_LACKS_WCSSTR */ +# if defined (ACE_HAS_XPG4_MULTIBYTE_CHAR) + return ::wcswcs (s, t); +# else + return ::wcsstr (s, t); +# endif /* ACE_HAS_XPG4_MULTIBYTE_CHAR */ +# endif /* ACE_LACKS_WCSSTR */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE char * +ACE_OS_String::strtok (char *s, const char *tokens) +{ +#if defined (ACE_HAS_PACE) + return pace_strtok (s, tokens); +#else /* ACE_HAS_PACE */ + return ::strtok (s, tokens); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOK) +ACE_INLINE wchar_t * +ACE_OS_String::strtok (wchar_t *s, const wchar_t *tokens) +{ + return ::wcstok (s, tokens); +} +#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOK */ + +ACE_INLINE int +ACE_OS_String::ace_isprint (const ACE_TCHAR c) +{ +#if defined (ACE_USES_WCHAR) + return iswprint (c); +#elif defined (ACE_HAS_PACE) + return pace_isprint (c); +#else /* ACE_USES_WCHAR */ + return isprint (c); +#endif /* ACE_USES_WCHAR */ +} + +ACE_INLINE int +ACE_OS_String::ace_isspace (const ACE_TCHAR c) +{ +#if defined (ACE_USES_WCHAR) + return iswspace (c); +#elif defined (ACE_HAS_PACE) + return pace_isspace (c); +#else /* ACE_HAS_PACE */ + return isspace (c); +#endif /* ACE_HAS_PACE */ +} + +ACE_INLINE int +ACE_OS_String::to_lower (int c) +{ +#if defined (ACE_HAS_PACE) + return pace_tolower (c); +#else /* ACE_HAS_PACE */ + return tolower (c); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_TOWLOWER) +ACE_INLINE wint_t +ACE_OS_String::to_lower (wint_t c) +{ + return towlower (c); +} +#endif /* ACE_HAS_WCHAR && !ACE_LACKS_TOWLOWER */ + +ACE_INLINE char * +ACE_OS_String::itoa (int value, char *string, int radix) +{ +#if !defined (ACE_HAS_ITOA) + return ACE_OS_String::itoa_emulation (value, string, radix); +#elif defined (ACE_ITOA_EQUIVALENT) + return ACE_ITOA_EQUIVALENT (value, string, radix); +#else /* !ACE_HAS_ITOA */ + return ::itoa (value, string, radix); +#endif /* !ACE_HAS_ITOA */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE wchar_t * +ACE_OS_String::itoa (int value, wchar_t *string, int radix) +{ +#if defined (ACE_LACKS_ITOW) + return ACE_OS_String::itow_emulation (value, string, radix); +#else /* ACE_LACKS_ITOW */ + return ::_itow (value, string, radix); +#endif /* ACE_LACKS_ITOW */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE int +ACE_OS_String::strcasecmp (const char *s, const char *t) +{ +#if defined (ACE_LACKS_STRCASECMP) + return ACE_OS_String::strcasecmp_emulation (s, t); +#elif defined (ACE_STRCASECMP_EQUIVALENT) + return ACE_STRCASECMP_EQUIVALENT (s, t); +#else /* ACE_LACKS_STRCASECMP */ + return ::strcasecmp (s, t); +#endif /* ACE_LACKS_STRCASECMP */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE int +ACE_OS_String::strcasecmp (const wchar_t *s, const wchar_t *t) +{ +# if defined (ACE_LACKS_WCSICMP) + return ACE_OS_String::wcsicmp_emulation (s, t); +# else /* ACE_LACKS_WCSICMP */ + return ::_wcsicmp (s, t); +# endif /* ACE_LACKS_WCSICMP */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE char * +ACE_OS_String::strnchr (char *s, int c, size_t len) +{ +#if defined ACE_PSOS_DIAB_PPC /* Compiler problem Diab 4.2b */ + const char *const_char_s = s; + return ACE_const_cast (char *, + ACE_OS_String::strnchr (const_char_s, c, len)); +#else + return ACE_const_cast (char *, + ACE_OS_String::strnchr (ACE_static_cast (const char *, s), c, len)); +#endif +} + +ACE_INLINE ACE_WCHAR_T * +ACE_OS_String::strnchr (ACE_WCHAR_T *s, ACE_WINT_T c, size_t len) +{ + return ACE_const_cast (ACE_WCHAR_T *, + ACE_OS_String::strnchr (ACE_static_cast (const ACE_WCHAR_T *, s), c, len)); +} + +ACE_INLINE int +ACE_OS_String::strncasecmp (const char *s, const char *t, size_t len) +{ +#if defined (ACE_LACKS_STRCASECMP) + return ACE_OS_String::strncasecmp_emulation (s, t, len); +#elif defined (ACE_STRNCASECMP_EQUIVALENT) + return ACE_STRNCASECMP_EQUIVALENT (s, t, len); +#else /* ACE_LACKS_STRCASECMP */ + return ::strncasecmp (s, t, len); +#endif /* ACE_LACKS_STRCASECMP */ +} + +#if defined (ACE_HAS_WCHAR) +ACE_INLINE int +ACE_OS_String::strncasecmp (const wchar_t *s, const wchar_t *t, size_t len) +{ +#if defined (ACE_LACKS_WCSNICMP) + return ACE_OS_String::wcsnicmp_emulation (s, t, len); +#else /* ACE_LACKS_WCSNICMP */ + return ::_wcsnicmp (s, t, len); +#endif /* ACE_LACKS_WCSNICMP */ +} +#endif /* ACE_HAS_WCHAR */ + +ACE_INLINE char * +ACE_OS_String::strnstr (char *s, const char *t, size_t len) +{ +#if defined ACE_PSOS_DIAB_PPC /* Compiler problem Diab 4.2b */ + const char *const_char_s=s; + return (char *) ACE_OS_String::strnstr (const_char_s, t, len); +#else + return (char *) ACE_OS_String::strnstr ((const char *) s, t, len); +#endif +} + +ACE_INLINE ACE_WCHAR_T * +ACE_OS_String::strnstr (ACE_WCHAR_T *s, const ACE_WCHAR_T *t, size_t len) +{ + return ACE_const_cast (ACE_WCHAR_T *, + ACE_OS_String::strnstr (ACE_static_cast (const ACE_WCHAR_T *, s), t, len)); +} + +ACE_INLINE char * +ACE_OS_String::strtok_r (char *s, const char *tokens, char **lasts) +{ +#if defined (ACE_HAS_PACE) + return pace_strtok_r (s, tokens, lasts); +#elif defined (ACE_HAS_REENTRANT_FUNCTIONS) + return ::strtok_r (s, tokens, lasts); +#else + return ACE_OS_String::strtok_r_emulation (s, tokens, lasts); +#endif /* (ACE_HAS_REENTRANT_FUNCTIONS) */ +} + +#if !defined (ACE_LACKS_STRTOD) +ACE_INLINE double +ACE_OS_String::strtod (const char *s, char **endptr) +{ +#if defined (ACE_HAS_PACE) + return pace_strtod (s, endptr); +#else /* ACE_HAS_PACE */ + return ::strtod (s, endptr); +#endif /* ACE_HAS_PACE */ +} +#endif /* !ACE_LACKS_STRTOD */ + +#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOD) +ACE_INLINE double +ACE_OS_String::strtod (const wchar_t *s, wchar_t **endptr) +{ + return ::wcstod (s, endptr); +} +#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOD */ + +ACE_INLINE long +ACE_OS_String::strtol (const char *s, char **ptr, int base) +{ +#if defined (ACE_HAS_PACE) + return pace_strtol (s, ptr, base); +#elif defined (ACE_LACKS_STRTOL) + return ACE_OS_String::strtol_emulation (s, ptr, base); +#else /* ACE_HAS_PACE */ + return ::strtol (s, ptr, base); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOL) +ACE_INLINE long +ACE_OS_String::strtol (const wchar_t *s, wchar_t **ptr, int base) +{ + return ::wcstol (s, ptr, base); +} +#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOL */ + +ACE_INLINE unsigned long +ACE_OS_String::strtoul (const char *s, char **ptr, int base) +{ +#if defined (ACE_HAS_PACE) + return pace_strtoul (s, ptr, base); +#elif defined (ACE_LACKS_STRTOUL) + return ACE_OS_String::strtoul_emulation (s, ptr, base); +#else /* ACE_HAS_PACE */ + return ::strtoul (s, ptr, base); +#endif /* ACE_HAS_PACE */ +} + +#if defined (ACE_HAS_WCHAR) && !defined (ACE_LACKS_WCSTOUL) +ACE_INLINE unsigned long +ACE_OS_String::strtoul (const wchar_t *s, wchar_t **ptr, int base) +{ + return ::wcstoul (s, ptr, base); +} +#endif /* ACE_HAS_WCHAR && !ACE_LACKS_WCSTOUL */ diff --git a/ace/OS/OS_TLI.cpp b/ace/OS/OS_TLI.cpp new file mode 100644 index 00000000000..629e6d49b3e --- /dev/null +++ b/ace/OS/OS_TLI.cpp @@ -0,0 +1,13 @@ +// $Id$ + +#include "OS_TLI.h" + +ACE_RCSID(ace, OS_TLI, "$Id$") + +#if !defined (ACE_HAS_INLINED_OSCALLS) +# include "OS_TLI.inl" +#else /* !ACE_HAS_INLINED_OSCALLS */ +#if defined (__hpux) && !defined (__GNUG__) +static int shut_up_aCC = 0; +#endif /* HPUX && !g++ */ +#endif /* !ACE_HAS_INLINED_OS_CALLS */ diff --git a/ace/OS/OS_TLI.h b/ace/OS/OS_TLI.h new file mode 100644 index 00000000000..a022f2e97cc --- /dev/null +++ b/ace/OS/OS_TLI.h @@ -0,0 +1,195 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file OS_TLI.h + * + * $Id$ + * + * @author Doug Schmidt + */ +//============================================================================= + + +#ifndef ACE_OS_TLI_H +#define ACE_OS_TLI_H +#include "ace/pre.h" + +#include "ace/config-all.h" +#include "OS_Export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +# if !defined (ACE_HAS_TLI) +// Dummies to help compilation. +struct t_call { }; +struct t_bind { }; +struct t_info { }; +struct t_optmgmt { }; +struct t_discon { }; +struct t_unitdata { }; +struct t_uderr { }; +struct netbuf { }; + +# else /* !ACE_WIN32 */ + +# if !defined (ACE_HAS_TLI_PROTOTYPES) + +// Define ACE_TLI headers for systems that don't prototype them.... +extern "C" +{ + int t_accept(int fildes, int resfd, struct t_call *call); + char *t_alloc(int fildes, int struct_type, int fields); + int t_bind(int fildes, struct t_bind *req, struct t_bind *ret); + int t_close(int fildes); + int t_connect(int fildes, struct t_call *sndcall, + struct t_call *rcvcall); + void t_error(const char *errmsg); + int t_free(char *ptr, int struct_type); + int t_getinfo(int fildes, struct t_info *info); + int t_getname (int fildes, struct netbuf *namep, int type); + int t_getstate(int fildes); + int t_listen(int fildes, struct t_call *call); + int t_look(int fildes); + int t_open(char *path, int oflag, struct t_info *info); + int t_optmgmt(int fildes, struct t_optmgmt *req, + struct t_optmgmt *ret); + int t_rcv(int fildes, char *buf, unsigned int nbytes, int *flags); + int t_rcvconnect(int fildes, struct t_call *call); + int t_rcvdis(int fildes, struct t_discon *discon); + int t_rcvrel(int fildes); + int t_rcvudata(int fildes, struct t_unitdata *unitdata, int *flags); + int t_rcvuderr(int fildes, struct t_uderr *uderr); + int t_snd(int fildes, const char *buf, unsigned int nbytes, int flags); + int t_snddis(int fildes, struct t_call *call); + int t_sndrel(int fildes); + int t_sndudata(int fildes, struct t_unitdata *unitdata); + int t_sync(int fildes); + int t_unbind(int fildes); +} +# endif /* !ACE_HAS_TLI_PROTOTYPES */ + +# if defined (ACE_HAS_TIUSER_H) || defined (ACE_HAS_XTI) || defined (ACE_HAS_FORE_ATM_XTI) +# if defined (ACE_HAS_BROKEN_XTI_MACROS) +# undef TCP_NODELAY +# undef TCP_MAXSEG +# endif /* ACE_HAS_BROKEN_XTI_MACROS */ +# if defined (ACE_HAS_TIUSER_H_BROKEN_EXTERN_C) +extern "C" { +# endif /* ACE_HAS_TIUSER_H_BROKEN_EXTERN_C */ +# if defined (ACE_HAS_FORE_ATM_XTI) +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# include /**/ +# elif defined (ACE_HAS_TIUSER_H) +# include /**/ +# elif defined (ACE_HAS_SYS_XTI_H) +# define class ace_xti_class +# include /**/ +# undef class +# else +# include /**/ +# endif /* ACE_HAS_FORE_ATM_XTI */ +# if defined (ACE_HAS_TIUSER_H_BROKEN_EXTERN_C) +} +# endif /* ACE_HAS_TIUSER_H_BROKEN_EXTERN_C */ +# endif /* ACE_HAS_TIUSER_H || ACE_HAS_XTI */ + +// Apparently this particular prototype is missing in so many +// platforms that is just better to declare it ourselves. +extern "C" int t_getname (int, struct netbuf *, int); + +# endif /* ACE_WIN32 */ + +// If the xti.h file redefines the function names, do it now, else +// when the function definitions are encountered, they won't match the +// declaration here. + +# if defined (ACE_REDEFINES_XTI_FUNCTIONS) +# include /**/ +# if defined (UNIXWARE_2_0) /* They apparently forgot one... */ +extern "C" int _xti_error(char *); +# endif /* UNIXWARE */ +# endif /* ACE_REDEFINES_XTI_FUNCTIONS */ + +/** + * @class ACE_OS_TLI + * + * @brief This class is a wrapper for the TLI operations + * + */ +class ACE_OS_Export ACE_OS_TLI +{ +public: + // = A set of wrappers for TLI. + static int t_accept (ACE_HANDLE fildes, + ACE_HANDLE resfd, + struct t_call + *call); + static char *t_alloc (ACE_HANDLE fildes, + int struct_type, + int + fields); + static int t_bind (ACE_HANDLE fildes, + struct t_bind *req, + struct + t_bind *ret); + static int t_close (ACE_HANDLE fildes); + static int t_connect (ACE_HANDLE fildes, + struct t_call *sndcall, + struct t_call *rcvcall); + static void t_error (const char *errmsg); + static int t_free (char *ptr, + int struct_type); + static int t_getinfo (ACE_HANDLE fildes, + struct t_info *info); + static int t_getname (ACE_HANDLE fildes, + struct netbuf *namep, + int type); + static int t_getstate (ACE_HANDLE fildes); + static int t_listen (ACE_HANDLE fildes, + struct t_call *call); + static int t_look (ACE_HANDLE fildes); + static ACE_HANDLE t_open (char *path, + int oflag, + struct t_info *info); + static int t_optmgmt (ACE_HANDLE fildes, + struct t_optmgmt *req, + struct t_optmgmt *ret); + static int t_rcv (ACE_HANDLE fildes, + char *buf, + unsigned int nbytes, + int *flags); + static int t_rcvdis (ACE_HANDLE fildes, + struct t_discon *discon); + static int t_rcvrel (ACE_HANDLE fildes); + static int t_rcvudata (ACE_HANDLE fildes, + struct t_unitdata *unitdata, + int *flags); + static int t_rcvuderr (ACE_HANDLE fildes, + struct t_uderr *uderr); + static int t_snd (ACE_HANDLE fildes, + const char *buf, + unsigned int nbytes, + int flags); + static int t_snddis (ACE_HANDLE fildes, + struct t_call *call); + static int t_sndrel (ACE_HANDLE fildes); + static int t_sync (ACE_HANDLE fildes); + static int t_unbind (ACE_HANDLE fildes); +}; + +# if defined (ACE_HAS_INLINED_OSCALLS) +# if defined (ACE_INLINE) +# undef ACE_INLINE +# endif /* ACE_INLINE */ +# define ACE_INLINE inline +# include "OS_TLI.inl" +# endif /* ACE_HAS_INLINED_OSCALLS */ + +#include "ace/post.h" +#endif /* ACE_OS_TLI_H */ diff --git a/ace/OS/OS_TLI.inl b/ace/OS/OS_TLI.inl new file mode 100644 index 00000000000..7fe5fa1b80a --- /dev/null +++ b/ace/OS/OS_TLI.inl @@ -0,0 +1,343 @@ +/* -*- C++ -*- */ +// $Id$ + +ACE_INLINE int +ACE_OS_TLI::t_accept (ACE_HANDLE handle, + ACE_HANDLE reshandle, + struct t_call *call) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_accept (handle, reshandle, call), int, -1); +#else + ACE_UNUSED_ARG (call); + ACE_UNUSED_ARG (reshandle); + ACE_UNUSED_ARG (handle); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE char * +ACE_OS_TLI::t_alloc (ACE_HANDLE handle, int struct_type, + int fields) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_alloc (handle, struct_type, fields), + char *, 0); +#else + ACE_UNUSED_ARG (fields); + ACE_UNUSED_ARG (struct_type); + ACE_UNUSED_ARG (handle); + + ACE_NOTSUP_RETURN (0); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_bind (ACE_HANDLE handle, struct t_bind *req, + struct t_bind *ret) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_bind (handle, req, ret), int, -1); +#else + ACE_UNUSED_ARG (ret); + ACE_UNUSED_ARG (req); + ACE_UNUSED_ARG (handle); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_close (ACE_HANDLE handle) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_close (handle), int, -1); +#else + ACE_UNUSED_ARG (handle); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_connect(ACE_HANDLE fildes, + struct t_call *sndcall, + struct t_call *rcvcall) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_connect (fildes, sndcall, rcvcall), int, -1); +#else + ACE_UNUSED_ARG (fildes); + ACE_UNUSED_ARG (sndcall); + ACE_UNUSED_ARG (rcvcall); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE void +ACE_OS_TLI::t_error (const char *errmsg) +{ +#if defined (ACE_HAS_TLI) +#if defined (ACE_HAS_BROKEN_T_ERROR) + ::t_error (ACE_const_cast (char *, errmsg)); +#else + ::t_error (errmsg); +#endif /* ACE_HAS_BROKEN_T_ERROR */ +#else + ACE_UNUSED_ARG (errmsg); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_free (char *ptr, int struct_type) +{ +#if defined (ACE_HAS_TLI) + if (ptr == 0) + return 0; + ACE_OSCALL_RETURN (::t_free (ptr, struct_type), int, -1); +#else + ACE_UNUSED_ARG (struct_type); + ACE_UNUSED_ARG (ptr); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_getinfo (ACE_HANDLE handle, struct t_info *info) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_getinfo (handle, info), int, -1); +#else + ACE_UNUSED_ARG (info); + ACE_UNUSED_ARG (handle); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_getname (ACE_HANDLE handle, + struct netbuf *namep, + int type) +{ +#if defined (ACE_HAS_SVR4_TLI) + ACE_OSCALL_RETURN (::t_getname (handle, namep, type), int, -1); +#else + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (namep); + ACE_UNUSED_ARG (type); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_SVR4_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_getstate (ACE_HANDLE handle) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_getstate (handle), int, -1); +#else + ACE_UNUSED_ARG (handle); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_listen (ACE_HANDLE handle, struct t_call *call) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_listen (handle, call), int, -1); +#else + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (call); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_look (ACE_HANDLE handle) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_look (handle), int, -1); +#else + ACE_UNUSED_ARG (handle); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE ACE_HANDLE +ACE_OS_TLI::t_open (char *path, int oflag, struct t_info *info) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_open (path, oflag, info), ACE_HANDLE, ACE_INVALID_HANDLE); +#else + ACE_UNUSED_ARG (path); + ACE_UNUSED_ARG (oflag); + ACE_UNUSED_ARG (info); + + ACE_NOTSUP_RETURN (ACE_INVALID_HANDLE); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_optmgmt (ACE_HANDLE handle, + struct t_optmgmt *req, + struct t_optmgmt *ret) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_optmgmt (handle, req, ret), int, -1); +#else + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (req); + ACE_UNUSED_ARG (ret); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_rcv (ACE_HANDLE handle, + char *buf, + unsigned int nbytes, + int *flags) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_rcv (handle, buf, nbytes, flags), + int, -1); +#else + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (nbytes); + ACE_UNUSED_ARG (flags); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_rcvdis (ACE_HANDLE handle, struct t_discon *discon) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_rcvdis (handle, discon), int, -1); +#else + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (discon); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_rcvrel (ACE_HANDLE handle) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_rcvrel (handle), int, -1); +#else + ACE_UNUSED_ARG (handle); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_rcvudata (ACE_HANDLE handle, + struct t_unitdata *unitdata, + int *flags) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_rcvudata (handle, unitdata, flags), + int, -1); +#else + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (unitdata); + ACE_UNUSED_ARG (flags); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_rcvuderr (ACE_HANDLE handle, struct t_uderr *uderr) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_rcvuderr (handle, uderr), int, -1); +#else + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (uderr); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_snd (ACE_HANDLE handle, + const char *buf, + unsigned int nbytes, + int flags) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_snd (handle, (char *) buf, nbytes, flags), int, -1); +#else + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (buf); + ACE_UNUSED_ARG (nbytes); + ACE_UNUSED_ARG (flags); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_snddis (ACE_HANDLE handle, struct t_call *call) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_snddis (handle, call), int, -1); +#else + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (call); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_sndrel (ACE_HANDLE handle) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_sndrel (handle), int, -1); +#else + ACE_UNUSED_ARG (handle); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_sync (ACE_HANDLE handle) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_sync (handle), int, -1); +#else + ACE_UNUSED_ARG (handle); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} + +ACE_INLINE int +ACE_OS_TLI::t_unbind (ACE_HANDLE handle) +{ +#if defined (ACE_HAS_TLI) + ACE_OSCALL_RETURN (::t_unbind (handle), int, -1); +#else + ACE_UNUSED_ARG (handle); + + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_TLI */ +} diff --git a/ace/OS/OS_Thread_Adapter.cpp b/ace/OS/OS_Thread_Adapter.cpp new file mode 100644 index 00000000000..82ff206147c --- /dev/null +++ b/ace/OS/OS_Thread_Adapter.cpp @@ -0,0 +1,178 @@ +// $Id$ + +#include "OS_Thread_Adapter.h" +#include "Thread_Hook.h" +#include "OS.h" + +ACE_RCSID(ace, OS_Thread_Adapter, "$Id$") + +#if !defined (ACE_HAS_INLINED_OSCALLS) +# include "OS_Thread_Adapter.inl" +#endif /* ACE_HAS_INLINED_OS_CALLS */ + +ACE_OS_Thread_Adapter::ACE_OS_Thread_Adapter ( + ACE_THR_FUNC user_func + , void *arg + , ACE_THR_C_FUNC entry_point +# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) + , ACE_SEH_EXCEPT_HANDLER selector + , ACE_SEH_EXCEPT_HANDLER handler +# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ + ) + : ACE_Base_Thread_Adapter (user_func, arg, entry_point +# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) + , 0 + , selector + , handler +# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ + ) +{ +} + +ACE_OS_Thread_Adapter::~ACE_OS_Thread_Adapter (void) +{ +} + +void * +ACE_OS_Thread_Adapter::invoke (void) +{ + // Inherit the logging features if the parent thread has an + // ACE_Log_Msg instance in thread-specific storage. + this->inherit_log_msg (); + + // Extract the arguments. + ACE_THR_FUNC_INTERNAL func = + ACE_reinterpret_cast (ACE_THR_FUNC_INTERNAL, this->user_func_); + void *arg = this->arg_; + + // Delete ourselves since we don't need anymore. Make sure + // not to access anywhere below this point. + delete this; + +#if defined (ACE_NEEDS_LWP_PRIO_SET) + // On SunOS, the LWP priority needs to be set in order to get + // preemption when running in the RT class. This is the ACE way to + // do that . . . + ACE_hthread_t thr_handle; + ACE_OS::thr_self (thr_handle); + int prio; + + // thr_getprio () on the current thread should never fail. + ACE_OS::thr_getprio (thr_handle, prio); + + // ACE_OS::thr_setprio () has the special logic to set the LWP priority, + // if running in the RT class. + ACE_OS::thr_setprio (prio); + +#endif /* ACE_NEEDS_LWP_PRIO_SET */ + + void *status = 0; + + ACE_SEH_TRY + { + ACE_SEH_TRY + { + ACE_Thread_Hook *hook = + ACE_OS_Object_Manager::thread_hook (); + + if (hook) + // Invoke the start hook to give the user a chance to + // perform some initialization processing before the + // is invoked. + status = hook->start (ACE_reinterpret_cast (ACE_THR_FUNC, func), + arg); + else + { + // Call thread entry point. +#if defined (ACE_PSOS) + (*func) (arg); +#else /* ! ACE_PSOS */ + status = ACE_reinterpret_cast (void *, (*func) (arg)); +#endif /* ACE_PSOS */ + } +#if defined (ACE_PSOS) + // pSOS task functions do not return a value. + status = 0; +#endif /* ACE_PSOS */ + } + +#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) + ACE_SEH_EXCEPT (ACE_OS_Object_Manager::seh_except_selector ()( + (void *) GetExceptionInformation ())) + { + ACE_OS_Object_Manager::seh_except_handler ()(0); + } +#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ + } + + ACE_SEH_FINALLY + { + // If we changed this to 1, change the respective if in + // Task::svc_run to 0. +#if 0 + // Call the close> hook. + if (func == ACE_reinterpret_cast (ACE_THR_FUNC_INTERNAL, + ACE_Task_Base::svc_run)) + { + ACE_Task_Base *task_ptr = (ACE_Task_Base *) arg; + ACE_Thread_Manager *thr_mgr_ptr = task_ptr->thr_mgr (); + + // This calls the Task->close () hook. + task_ptr->cleanup (task_ptr, 0); + + // This prevents a second invocation of the cleanup code + // (called later by . + thr_mgr_ptr->at_exit (task_ptr, 0, 0); + } +#endif /* 0 */ + +#if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) + // Call TSS destructors. + ACE_OS::cleanup_tss (0 /* not main thread */); + +# if defined (ACE_WIN32) + // Exit the thread. Allow CWinThread-destructor to be invoked + // from AfxEndThread. _endthreadex will be called from + // AfxEndThread so don't exit the thread now if we are running + // an MFC thread. +# if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0) + // Not spawned by ACE_Thread_Manager, use the old buggy + // version. You should seriously consider using + // ACE_Thread_Manager to spawn threads. The following code + // is know to cause some problem. + CWinThread *pThread = ::AfxGetThread (); + + if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ()) + ACE_ENDTHREADEX (status); + else + ::AfxEndThread ((DWORD)status); +# else + ACE_ENDTHREADEX (status); +# endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/ +# endif /* ACE_WIN32 */ +#endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */ + +#if defined (ACE_PSOS) + // This sequence of calls is documented by ISI as the proper way to + // clean up a pSOS task. They affect different components, so only + // try the ones for components that are built with ACE. +# if defined (SC_PREPC) && (SC_PREPC == YES) + ::fclose (0); // Return pREPC+ resources +# endif /* SC_PREPC */ +# if defined (SC_PHILE) && (SC_PHILE == YES) + ::close_f (0); // Return pHILE+ resources +# endif /* SC_PHILE */ +# if defined (SC_PNA) && (SC_PNA == YES) + ::close (0); // Return pNA+ resources +# endif /* SC_PNA */ +# if defined (SC_SC_PREPC) && (SC_PREPC == YES) + ::free (-1); // Return pREPC+ memory +# endif /* SC_PREPC */ + status = ::t_delete (0); // Suicide - only returns on error +#endif /* ACE_PSOS */ + + return status; + } + + ACE_NOTREACHED (return status); +} diff --git a/ace/OS/OS_Thread_Adapter.h b/ace/OS/OS_Thread_Adapter.h new file mode 100644 index 00000000000..9132556c18c --- /dev/null +++ b/ace/OS/OS_Thread_Adapter.h @@ -0,0 +1,78 @@ + +//============================================================================= +/** + * @file Thread_Adapter.h + * + * $Id$ + * + * @author Carlos O'Ryan + */ +//============================================================================= + +#ifndef ACE_OS_THREAD_ADAPTER_H +#define ACE_OS_THREAD_ADAPTER_H +#include "ace/pre.h" + +#include "Base_Thread_Adapter.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "OS_Export.h" + +/** + * @class ACE_OS_Thread_Adapter + * + * @brief Converts a C++ function into a function + * function that can be called from a thread creation routine + * (e.g., or <_beginthreadex>) that expects an + * extern "C" entry point. This class also makes it possible to + * transparently provide hooks to register a thread with an + * . + * + * This class is used in . In general, the + * thread that creates an object of this class is different from + * the thread that calls on this object. Therefore, + * the method is responsible for deleting itself. + */ +class ACE_OS_Export ACE_OS_Thread_Adapter : public ACE_Base_Thread_Adapter +{ +public: + ACE_OS_Thread_Adapter (ACE_THR_FUNC user_func, + void *arg, + ACE_THR_C_FUNC entry_point = (ACE_THR_C_FUNC) ace_thread_adapter +# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) + , ACE_SEH_EXCEPT_HANDLER selector = 0 + , ACE_SEH_EXCEPT_HANDLER handler = 0 +# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ + /// Constructor. + ); + + /** + * Execute the with the . This function deletes + * , thereby rendering the object useless after the call + * returns. + */ + virtual void *invoke (void); + +private: + /// Ensure that this object must be allocated on the heap. + ~ACE_OS_Thread_Adapter (void); + +private: + /// Friend declaration to avoid compiler warning: only defines a private + /// destructor and has no friends. + friend class ACE_Thread_Adapter_Has_Private_Destructor; +}; + +# if defined (ACE_HAS_INLINED_OSCALLS) +# if defined (ACE_INLINE) +# undef ACE_INLINE +# endif /* ACE_INLINE */ +# define ACE_INLINE inline +# include "OS_Thread_Adapter.inl" +# endif /* ACE_HAS_INLINED_OSCALLS */ + +#include "ace/post.h" +#endif /* ACE_THREAD_ADAPTER_H */ diff --git a/ace/OS/OS_Thread_Adapter.inl b/ace/OS/OS_Thread_Adapter.inl new file mode 100644 index 00000000000..cfa1da318d3 --- /dev/null +++ b/ace/OS/OS_Thread_Adapter.inl @@ -0,0 +1 @@ +// $Id$ diff --git a/ace/OS/Sched_Params.cpp b/ace/OS/Sched_Params.cpp new file mode 100644 index 00000000000..77c472faa54 --- /dev/null +++ b/ace/OS/Sched_Params.cpp @@ -0,0 +1,321 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ACE +// +// = FILENAME +// Sched_Params.cpp +// +// = CREATION DATE +// 28 January 1997 +// +// = AUTHOR +// David Levine +// +// ============================================================================ + +#include "Sched_Params.h" + +#if !defined (__ACE_INLINE__) +#include "Sched_Params.i" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID(ace, Sched_Params, "$Id$") + +int +ACE_Sched_Params::priority_min (const Policy policy, + const int scope) +{ +#if defined (ACE_HAS_PRIOCNTL) && defined (ACE_HAS_STHREADS) + ACE_UNUSED_ARG (scope); + + // Assume that ACE_SCHED_OTHER indicates TS class, and that other + // policies indicate RT class. + + // Call ACE_OS::priority_control only for processes (lightweight + // or otherwise). Calling ACE_OS::priority_control for thread + // priorities gives incorrect results. + if (scope == ACE_SCOPE_PROCESS || scope == ACE_SCOPE_LWP) + { + if (policy == ACE_SCHED_OTHER) + { + // Get the priority class ID and attributes. + pcinfo_t pcinfo; + // The following is just to avoid Purify warnings about unitialized + // memory reads. + ACE_OS::memset (&pcinfo, 0, sizeof pcinfo); + ACE_OS::strcpy (pcinfo.pc_clname, "TS"); + + if (ACE_OS::priority_control (P_ALL /* ignored */, + P_MYID /* ignored */, + PC_GETCID, + (char *) &pcinfo) == -1) + // Just hope that priority range wasn't configured from -1 + // .. 1 + return -1; + + // OK, now we've got the class ID in pcinfo.pc_cid. In + // addition, the maximum configured time-share priority is in + // ((tsinfo_t *) pcinfo.pc_clinfo)->ts_maxupri. The minimum + // priority is just the negative of that. + + return -((tsinfo_t *) pcinfo.pc_clinfo)->ts_maxupri; + } + else + return 0; + } + else + { + // Here we handle the case for ACE_SCOPE_THREAD. Calling + // ACE_OS::priority_control for thread scope gives incorrect + // results. + switch (policy) + { + case ACE_SCHED_FIFO: + return ACE_THR_PRI_FIFO_MIN; + case ACE_SCHED_RR: + return ACE_THR_PRI_RR_MIN; + case ACE_SCHED_OTHER: + default: + return ACE_THR_PRI_OTHER_MIN; + } + } +#elif defined (ACE_HAS_PTHREADS) && !defined(ACE_LACKS_SETSCHED) + + switch (scope) + { + case ACE_SCOPE_THREAD: + switch (policy) + { + case ACE_SCHED_FIFO: + return ACE_THR_PRI_FIFO_MIN; + case ACE_SCHED_RR: + return ACE_THR_PRI_RR_MIN; +#if !defined (CHORUS) // SCHED_OTHRE and SCHED_RR have same value + case ACE_SCHED_OTHER: +#endif /* CHORUS */ + default: + return ACE_THR_PRI_OTHER_MIN; + } + + case ACE_SCOPE_PROCESS: + default: + switch (policy) + { + case ACE_SCHED_FIFO: + return ACE_PROC_PRI_FIFO_MIN; + case ACE_SCHED_RR: + return ACE_PROC_PRI_RR_MIN; +#if !defined (CHORUS) // SCHED_OTHRE and SCHED_RR have same value + case ACE_SCHED_OTHER: +#endif /* CHORUS */ + default: + return ACE_PROC_PRI_OTHER_MIN; + } + } + +#elif defined (ACE_HAS_WTHREADS) + ACE_UNUSED_ARG (policy); + ACE_UNUSED_ARG (scope); + return THREAD_PRIORITY_IDLE; +#elif defined (VXWORKS) + ACE_UNUSED_ARG (policy); + ACE_UNUSED_ARG (scope); + return 255; +#else + ACE_UNUSED_ARG (policy); + ACE_UNUSED_ARG (scope); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PRIOCNTL && defined (ACE_HAS_STHREADS) */ +} + +int +ACE_Sched_Params::priority_max (const Policy policy, + const int scope) +{ +#if defined (ACE_HAS_PRIOCNTL) && defined (ACE_HAS_STHREADS) + ACE_UNUSED_ARG (scope); + + // Call ACE_OS::priority_control only for processes (lightweight + // or otherwise). Calling ACE_OS::priority_control for thread + // priorities gives incorrect results. + if (scope == ACE_SCOPE_PROCESS || scope == ACE_SCOPE_LWP) + { + // Assume that ACE_SCHED_OTHER indicates TS class, and that other + // policies indicate RT class. + + // Get the priority class ID and attributes. + pcinfo_t pcinfo; + // The following is just to avoid Purify warnings about unitialized + // memory reads. + ACE_OS::memset (&pcinfo, 0, sizeof pcinfo); + ACE_OS::strcpy (pcinfo.pc_clname, + policy == ACE_SCHED_OTHER ? "TS" : "RT"); + + if (ACE_OS::priority_control (P_ALL /* ignored */, + P_MYID /* ignored */, + PC_GETCID, + (char *) &pcinfo) == -1) + return -1; + + // OK, now we've got the class ID in pcinfo.pc_cid. In addition, + // the maximum configured real-time priority is in ((rtinfo_t *) + // pcinfo.pc_clinfo)->rt_maxpri, or similarly for the TS class. + + return policy == ACE_SCHED_OTHER + ? ((tsinfo_t *) pcinfo.pc_clinfo)->ts_maxupri + : ((rtinfo_t *) pcinfo.pc_clinfo)->rt_maxpri; + } + else + { + // Here we handle the case for ACE_SCOPE_THREAD. Calling + // ACE_OS::priority_control for thread scope gives incorrect + // results. + switch (policy) + { + case ACE_SCHED_FIFO: + return ACE_THR_PRI_FIFO_MAX; + case ACE_SCHED_RR: + return ACE_THR_PRI_RR_MAX; + case ACE_SCHED_OTHER: + default: + return ACE_THR_PRI_OTHER_MAX; + } + } +#elif defined(ACE_HAS_PTHREADS) && !defined(ACE_LACKS_SETSCHED) + + switch (scope) + { + case ACE_SCOPE_THREAD: + switch (policy) + { + case ACE_SCHED_FIFO: + return ACE_THR_PRI_FIFO_MAX; + case ACE_SCHED_RR: + return ACE_THR_PRI_RR_MAX; +#if !defined (CHORUS) // SCHED_OTHRE and SCHED_RR have same value + case ACE_SCHED_OTHER: +#endif /* CHORUS */ + default: + return ACE_THR_PRI_OTHER_MAX; + } + + case ACE_SCOPE_PROCESS: + default: + switch (policy) + { + case ACE_SCHED_FIFO: + return ACE_PROC_PRI_FIFO_MAX; + case ACE_SCHED_RR: + return ACE_PROC_PRI_RR_MAX; +#if !defined (CHORUS) // SCHED_OTHRE and SCHED_RR have same value + case ACE_SCHED_OTHER: +#endif /* CHORUS */ + default: + return ACE_PROC_PRI_OTHER_MAX; + } + } + +#elif defined (ACE_HAS_WTHREADS) + ACE_UNUSED_ARG (policy); + ACE_UNUSED_ARG (scope); + return THREAD_PRIORITY_TIME_CRITICAL; +#elif defined (VXWORKS) + ACE_UNUSED_ARG (policy); + ACE_UNUSED_ARG (scope); + return 0; +#else + ACE_UNUSED_ARG (policy); + ACE_UNUSED_ARG (scope); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_PRIOCNTL && defined (ACE_HAS_STHREADS) */ +} + +int +ACE_Sched_Params::next_priority (const Policy policy, + const int priority, + const int scope) +{ +#if defined (VXWORKS) + return priority > priority_max (policy, scope) + ? priority - 1 + : priority_max (policy, scope); +#elif defined (ACE_HAS_WTHREADS) + ACE_UNUSED_ARG (policy); + ACE_UNUSED_ARG (scope); + switch (priority) + { + case THREAD_PRIORITY_IDLE: + return THREAD_PRIORITY_LOWEST; + case THREAD_PRIORITY_LOWEST: + return THREAD_PRIORITY_BELOW_NORMAL; + case THREAD_PRIORITY_BELOW_NORMAL: + return THREAD_PRIORITY_NORMAL; + case THREAD_PRIORITY_NORMAL: + return THREAD_PRIORITY_ABOVE_NORMAL; + case THREAD_PRIORITY_ABOVE_NORMAL: + return THREAD_PRIORITY_HIGHEST; + case THREAD_PRIORITY_HIGHEST: + return THREAD_PRIORITY_TIME_CRITICAL; + case THREAD_PRIORITY_TIME_CRITICAL: + return THREAD_PRIORITY_TIME_CRITICAL; + default: + return priority; // unknown priority: should never get here + } +#elif defined(ACE_HAS_THREADS) && !defined(ACE_LACKS_SETSCHED) + // including STHREADS, and PTHREADS + const int max = priority_max (policy, scope); + return priority < max ? priority + 1 : max; +#else + ACE_UNUSED_ARG (policy); + ACE_UNUSED_ARG (scope); + ACE_UNUSED_ARG (priority); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +int +ACE_Sched_Params::previous_priority (const Policy policy, + const int priority, + const int scope) +{ +#if defined (VXWORKS) + return priority < priority_min (policy, scope) + ? priority + 1 + : priority_min (policy, scope); +#elif defined (ACE_HAS_WTHREADS) + ACE_UNUSED_ARG (policy); + ACE_UNUSED_ARG (scope); + switch (priority) + { + case THREAD_PRIORITY_IDLE: + return THREAD_PRIORITY_IDLE; + case THREAD_PRIORITY_LOWEST: + return THREAD_PRIORITY_IDLE; + case THREAD_PRIORITY_BELOW_NORMAL: + return THREAD_PRIORITY_LOWEST; + case THREAD_PRIORITY_NORMAL: + return THREAD_PRIORITY_BELOW_NORMAL; + case THREAD_PRIORITY_ABOVE_NORMAL: + return THREAD_PRIORITY_NORMAL; + case THREAD_PRIORITY_HIGHEST: + return THREAD_PRIORITY_ABOVE_NORMAL; + case THREAD_PRIORITY_TIME_CRITICAL: + return THREAD_PRIORITY_HIGHEST; + default: + return priority; // unknown priority: should never get here + } +#elif defined (ACE_HAS_THREADS) && !defined(ACE_LACKS_SETSCHED) + // including STHREADS and PTHREADS + const int min = priority_min (policy, scope); + + return priority > min ? priority - 1 : min; +#else + ACE_UNUSED_ARG (policy); + ACE_UNUSED_ARG (scope); + ACE_UNUSED_ARG (priority); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} diff --git a/ace/OS/Sched_Params.h b/ace/OS/Sched_Params.h new file mode 100644 index 00000000000..884c7e088d2 --- /dev/null +++ b/ace/OS/Sched_Params.h @@ -0,0 +1,225 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file Sched_Params.h + * + * $Id$ + * + * @author David Levine + * @author Carlos O'Ryan + */ +//============================================================================= + +#ifndef ACE_SCHED_PARAMS_H +#define ACE_SCHED_PARAMS_H +#include "ace/pre.h" + +#include "OS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +/** + * @class ACE_Sched_Params + * + * @brief Container for scheduling-related parameters. + * + * ACE_Sched_Params are passed via to the + * OS to specify scheduling parameters. These parameters include + * scheduling policy, such as FIFO (ACE_SCHED_FIFO), round-robin + * (ACE_SCHED_RR), or an implementation-defined "OTHER" + * (ACE_SCHED_OTHER), to which many systems default; priority; + * and a time-slice quantum for round-robin scheduling. A + * "scope" parameter specifies whether the ACE_Sched_Params + * applies to the current process, current lightweight process + * (LWP) (on Solaris), or current thread. Please see the "NOTE" + * below about not all combinations of parameters being legal on + * a particular platform. + * For the case of thread priorities, it is intended that + * usually be called from
before + * any threads have been spawned. If spawned threads inherit + * their parent's priority (I think that's the default behavior + * for all of our platforms), then this sets the default base + * priority. Individual thread priorities can be adjusted as + * usual using or via the ACE_Thread + * interface. See the parameter descriptions in the private: + * section below. + * NOTE: this class does not do any checking of parameters. It + * is just a container class. If it is constructed with values + * that are not supported on a platform, the call to + * will fail by returning -1 with EINVAL + * (available through ). + */ +class ACE_Export ACE_Sched_Params +{ + // NOTE: Solaris 2.5.x threads in the RT class must set the + // priority of their LWP. The only way to do that through ACE is + // for the RT thread itself to call with + // it's own priority. + + // OS Scheduling parameters are complicated and often confusing. + // Many thanks to Thilo Kielmann + // for his careful review of + // this class design, thoughtful comments, and assistance with + // implementation, especially for PTHREADS platforms. Please + // send any comments or corrections to the ACE developers. +public: + typedef int Policy; + + // = Initialization and termination methods. + /// Constructor. + ACE_Sched_Params (const Policy policy, + const ACE_Sched_Priority priority, + const int scope = ACE_SCOPE_THREAD, + const ACE_Time_Value &quantum = ACE_Time_Value::zero); + + /// Termination. + ~ACE_Sched_Params (void); + + // = Get/Set methods: + + // = Get/Set policy + Policy policy (void) const; + void policy (const Policy); + + // = Get/Set priority. + ACE_Sched_Priority priority (void) const; + void priority (const ACE_Sched_Priority); + + // = Get/Set scope. + int scope (void) const; + void scope(const int); + + // = Get/Set quantum. + const ACE_Time_Value &quantum (void) const; + void quantum (const ACE_Time_Value &); + + // = Accessors for OS-specific priorities. + // These return priority values for ACE_SCHED_OTHER if the Policy value + // is invalid. + static int priority_min (const Policy, + const int scope = ACE_SCOPE_THREAD); + static int priority_max (const Policy, + const int scope = ACE_SCOPE_THREAD); + + /** + * The next higher priority. "Higher" refers to scheduling priority, + * not to the priority value itself. (On some platforms, higher scheduling + * priority is indicated by a lower priority value.) If "priority" is + * already the highest priority (for the specified policy), then it is + * returned. + */ + static int next_priority (const Policy, + const int priority, + const int scope = ACE_SCOPE_THREAD); + + /** + * The previous, lower priority. "Lower" refers to scheduling priority, + * not to the priority value itself. (On some platforms, lower scheduling + * priority is indicated by a higher priority value.) If "priority" is + * already the lowest priority (for the specified policy), then it is + * returned. + */ + static int previous_priority (const Policy, + const int priority, + const int scope = ACE_SCOPE_THREAD); + +private: + /// Scheduling policy. + Policy policy_; + + /// Default : for setting the priority for the process, LWP, + /// or thread, as indicated by the scope_ parameter. + ACE_Sched_Priority priority_; + + /** + * must be one of the following: + * ACE_SCOPE_PROCESS: sets the scheduling policy for the + * process, and the process priority. On some platforms, + * such as Win32, the scheduling policy can _only_ be + * set at process scope. + * ACE_SCOPE_LWP: lightweight process scope, only used with + * Solaris threads. + * ACE_SCOPE_THREAD: sets the scheduling policy for the thread, + * if the OS supports it, such as with Posix threads, and the + * thread priority. + * NOTE: I don't think that these are the same as POSIX + * contention scope. POSIX users who are interested in, + * and understand, contention scope will have to set it + * by using system calls outside of ACE. + */ + int scope_; + + /** + * The is for time slicing. An ACE_Time_Value of 0 has + * special significance: it means time-slicing is disabled; with + * that, a thread that is running on a CPU will continue to run + * until it blocks or is preempted. Currently ignored if the OS + * doesn't directly support time slicing, such as on VxWorks, or + * setting the quantum (can that be done on Win32?). + */ + ACE_Time_Value quantum_; +}; + +/** + * @class ACE_Sched_Priority_Iterator + * + * @brief An iterator over the OS-defined scheduling priorities. + * + * The order of priorities (numeric value vs. importance) is OS + * dependant, it can be the case that the priorities are not even + * contigous. This class permits iteration over priorities using + * the iterator pattern. + */ +class ACE_Export ACE_Sched_Priority_Iterator +{ +public: + /// Initialize the iterator, the arguments define the scheduling + /// policy and scope for the priorities (see ACE_Sched_Param). + ACE_Sched_Priority_Iterator (const ACE_Sched_Params::Policy &policy, + int scope = ACE_SCOPE_THREAD); + + /// Default dtor. + ~ACE_Sched_Priority_Iterator (void); + + /// Check if there are more priorities. + int more (void) const; + + /// Return the current priority. + int priority (void) const; + + /// Move to the next priority. + /// The iteration is from lowest to highest importance. + void next (void); + + /// Accessor for the scheduling policy over which we are iterating. + const ACE_Sched_Params::Policy &policy (void) const; + + /// Accessor for the scheduling + int scope (void) const; + +private: + /// The Scheduling policy (FIFO, RR, etc.) and scheduling scope + /// (PROCESS, SYSTEM) we are iterating on. + ACE_Sched_Params::Policy policy_; + int scope_; + + /// The current priority. + int priority_; + + /** + * This is set to 1 when there are no more priorities. Cannot easily + * compare against the highest priority on platforms were priorities + * are non-contigous or descending. + */ + int done_; +}; + +#if defined (__ACE_INLINE__) +#include "Sched_Params.i" +#endif /* __ACE_INLINE__ */ + +#include "ace/post.h" +#endif /* ACE_SCHED_PARAMS_H */ diff --git a/ace/OS/Sched_Params.i b/ace/OS/Sched_Params.i new file mode 100644 index 00000000000..041f9cb1648 --- /dev/null +++ b/ace/OS/Sched_Params.i @@ -0,0 +1,136 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ACE +// +// = FILENAME +// Sched_Params.i +// +// = CREATION DATE +// 28 January 1997 +// +// = AUTHOR +// David Levine +// +// ============================================================================ + +ACE_INLINE +ACE_Sched_Params::ACE_Sched_Params ( + const Policy policy, + const ACE_Sched_Priority priority, + const int scope, + const ACE_Time_Value &quantum) + : policy_ (policy), + priority_ (priority), + scope_ (scope), + quantum_ (quantum) +{ +} + +ACE_INLINE ACE_Sched_Params::~ACE_Sched_Params (void) +{ +} + +ACE_INLINE ACE_Sched_Params::Policy +ACE_Sched_Params::policy (void) const +{ + return this->policy_; +} + +ACE_INLINE void +ACE_Sched_Params::policy (const ACE_Sched_Params::Policy policy) +{ + this->policy_ = policy; +} + +ACE_INLINE ACE_Sched_Priority +ACE_Sched_Params::priority (void) const +{ + return this->priority_; +} + +ACE_INLINE void +ACE_Sched_Params::priority (const ACE_Sched_Priority priority) +{ + this->priority_ = priority; +} + +ACE_INLINE int +ACE_Sched_Params::scope (void) const +{ + return this->scope_; +} + +ACE_INLINE void +ACE_Sched_Params::scope (const int scope) +{ + this->scope_ = scope; +} + +ACE_INLINE const ACE_Time_Value & +ACE_Sched_Params::quantum (void) const +{ + return this->quantum_; +} + +ACE_INLINE void +ACE_Sched_Params::quantum (const ACE_Time_Value &quant) +{ + this->quantum_ = quant; +} + +ACE_INLINE const ACE_Sched_Params::Policy & +ACE_Sched_Priority_Iterator::policy (void) const +{ + return this->policy_; +} + +ACE_INLINE int +ACE_Sched_Priority_Iterator::scope (void) const +{ + return this->scope_; +} + +ACE_INLINE +ACE_Sched_Priority_Iterator::ACE_Sched_Priority_Iterator (const ACE_Sched_Params::Policy &policy, + int scope) + : policy_ (policy), + scope_ (scope), + priority_ (0), + done_ (0) +{ + priority_ = ACE_Sched_Params::priority_min (this->policy (), this->scope ()); +} + +ACE_INLINE +ACE_Sched_Priority_Iterator::~ACE_Sched_Priority_Iterator (void) +{ +} + +ACE_INLINE int +ACE_Sched_Priority_Iterator::more (void) const +{ + return !this->done_; +} + +ACE_INLINE int +ACE_Sched_Priority_Iterator::priority (void) const +{ + return this->priority_; +} + +ACE_INLINE void +ACE_Sched_Priority_Iterator::next (void) +{ + if (this->done_) + return; + + int old_priority = this->priority_; + priority_ = ACE_Sched_Params::next_priority (this->policy (), + this->priority (), + this->scope ()); + this->done_ = old_priority == priority_; +} diff --git a/ace/OS/Thread_Hook.cpp b/ace/OS/Thread_Hook.cpp new file mode 100644 index 00000000000..733fa98d7b0 --- /dev/null +++ b/ace/OS/Thread_Hook.cpp @@ -0,0 +1,25 @@ +// $Id$ + +#include "Thread_Hook.h" +#include "OS.h" + +ACE_RCSID(ace, Thread_Hook, "$Id$") + +void * +ACE_Thread_Hook::start (ACE_THR_FUNC func, + void *arg) +{ + return (func) (arg); +} + +ACE_Thread_Hook * +ACE_Thread_Hook::thread_hook (ACE_Thread_Hook *hook) +{ + return ACE_OS_Object_Manager::thread_hook (hook); +} + +ACE_Thread_Hook * +ACE_Thread_Hook::thread_hook (void) +{ + return ACE_OS_Object_Manager::thread_hook (); +} diff --git a/ace/OS/Thread_Hook.h b/ace/OS/Thread_Hook.h new file mode 100644 index 00000000000..d1a9510a137 --- /dev/null +++ b/ace/OS/Thread_Hook.h @@ -0,0 +1,56 @@ + +//============================================================================= +/** + * @file Thread_Hook.h + * + * $Id$ + * + * @author Carlos O'Ryan + */ +//============================================================================= + + +#ifndef ACE_THREAD_HOOK_H +#define ACE_THREAD_HOOK_H +#include "ace/pre.h" + +#include "ace/config-all.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "OS_Export.h" + +/** + * @class ACE_Thread_Hook + * + * @brief This class makes it possible to provide user-defined "start" + * hooks that are called before the thread entry point function + * is invoked. + */ +class ACE_OS_Export ACE_Thread_Hook +{ + +public: + /** + * This method can be overridden in a subclass to customize this + * pre-function call "hook" invocation that can perform + * initialization processing before the thread entry point + * method is called back. The and passed into the + * start hook are the same as those passed by the application that + * spawned the thread. + */ + virtual void *start (ACE_THR_FUNC func, + void *arg); + + /// sets the system wide thread hook, returns the previous thread + /// hook or 0 if none is set. + static ACE_Thread_Hook *thread_hook (ACE_Thread_Hook *hook); + + /// Returns the current system thread hook. + static ACE_Thread_Hook *thread_hook (void); +}; + +#include "ace/post.h" +#endif /* ACE_THREAD_HOOK_H */ diff --git a/ace/OS/gethrtime.cpp b/ace/OS/gethrtime.cpp new file mode 100644 index 00000000000..dcad95e8b64 --- /dev/null +++ b/ace/OS/gethrtime.cpp @@ -0,0 +1,58 @@ +// $Id$ +// +// Build this file with g++. It can be linked in to a ACE application +// that was compiled with GreenHills. It wouldn't be necessary if I +// knew a way to correctly move values from registers to a 64-bit +// variable in GHS asm code. That's easy with g++ asm. + +#include "OS.h" + +ACE_RCSID(ace, gethrtime, "$Id$") + +extern "C" +ACE_hrtime_t +ACE_gethrtime (void) +{ +#if defined (ACE_HAS_PENTIUM) + // ACE_TRACE ("ACE_gethrtime"); + +#if defined (ACE_LACKS_LONGLONG_T) + double now; +#else /* ! ACE_LACKS_LONGLONG_T */ + ACE_hrtime_t now; +#endif /* ! ACE_LACKS_LONGLONG_T */ + + // See comments about the RDTSC Pentium instruction for the + // ACE_WIN32 version of ACE_OS::gethrtime () in ace/OS.i. + // + // Read the high-res tick counter directly into memory variable + // "now". The A constraint signifies a 64-bit int. +#if defined (__GNUG__) + asm volatile ("rdtsc" : "=A" (now) : : "memory"); +// #elif defined (ghs) +// The following doesn't work. For now, this file must be compile with g++. +// asm ("rdtsc"); +// asm ("movl %edx,-16(%ebp)"); +// asm ("movl %eax,-12(%ebp)"); +#else +# error unsupported compiler +#endif + +#if defined (ACE_LACKS_LONGLONG_T) + // ACE_U_LongLong doesn't have the same layout as now, so construct + // it "properly". + ACE_UINT32 least, most; + ACE_OS::memcpy (&least, &now, sizeof (ACE_UINT32)); + ACE_OS::memcpy (&most, (unsigned char *) &now + sizeof (ACE_UINT32), + sizeof (ACE_UINT32)); + + const ACE_hrtime_t ret (least, most); + return ret; +#else /* ! ACE_LACKS_LONGLONG_T */ + return now; +#endif /* ! ACE_LACKS_LONGLONG_T */ + +#else /* ! ACE_HAS_PENTIUM */ +# error This file can _only_ be compiled with ACE_HAS_PENTIUM. +#endif /* ! ACE_HAS_PENTIUM */ +} -- cgit v1.2.1