summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ace/INET_Addr.cpp15
-rw-r--r--ace/INET_Addr.i13
-rw-r--r--ace/Log_Msg.cpp27
-rw-r--r--ace/Log_Msg.h2
-rw-r--r--ace/Malloc_T.cpp23
-rw-r--r--ace/Malloc_T.h3
-rw-r--r--ace/Message_Queue.h8
-rw-r--r--ace/OS.cpp27
-rw-r--r--ace/OS.h12
-rw-r--r--ace/OS.i16
-rw-r--r--ace/Pipe.cpp18
-rw-r--r--ace/ReactorEx.cpp12
-rw-r--r--ace/SOCK_Stream.cpp11
-rw-r--r--ace/SOCK_Stream.h5
-rw-r--r--ace/Synch_T.cpp31
-rw-r--r--ace/System_Time.cpp33
-rw-r--r--ace/System_Time.h12
-rw-r--r--ace/Thread.cpp16
-rw-r--r--ace/Thread.h19
-rw-r--r--ace/Thread_Manager.cpp39
-rw-r--r--ace/Thread_Manager.h22
-rw-r--r--ace/config-irix6.2-sgic++.h12
22 files changed, 297 insertions, 79 deletions
diff --git a/ace/INET_Addr.cpp b/ace/INET_Addr.cpp
index 1f131f1b7f2..e73fc1d503a 100644
--- a/ace/INET_Addr.cpp
+++ b/ace/INET_Addr.cpp
@@ -12,6 +12,19 @@
ACE_ALLOC_HOOK_DEFINE(ACE_INET_Addr)
+// Transform the current address into string format.
+
+int
+ACE_INET_Addr::addr_to_string (char s[], size_t) const
+{
+ ACE_TRACE ("ACE_INET_Addr::addr_to_string");
+ // This should check to make sure len is long enough...
+ ACE_OS::sprintf (s, "%s:%d",
+ this->get_host_addr (),
+ this->get_port_number ());
+ return 0;
+}
+
void
ACE_INET_Addr::dump (void) const
{
@@ -68,7 +81,7 @@ ACE_INET_Addr::set (const ACE_INET_Addr &sa)
// Transform the string into the current addressing format.
-ACE_INLINE int
+int
ACE_INET_Addr::string_to_addr (const char s[])
{
ACE_TRACE ("ACE_INET_Addr::string_to_addr");
diff --git a/ace/INET_Addr.i b/ace/INET_Addr.i
index 1629dc0ecb0..81a5fa3dc6f 100644
--- a/ace/INET_Addr.i
+++ b/ace/INET_Addr.i
@@ -32,19 +32,6 @@ ACE_INET_Addr::get_host_addr (void) const
return ACE_OS::inet_ntoa (this->inet_addr_.sin_addr);
}
-// Transform the current address into string format.
-
-ACE_INLINE int
-ACE_INET_Addr::addr_to_string (char s[], size_t) const
-{
- ACE_TRACE ("ACE_INET_Addr::addr_to_string");
- // This should check to make sure len is long enough...
- ACE_OS::sprintf (s, "%s:%d",
- this->get_host_addr (),
- this->get_port_number ());
- return 0;
-}
-
// Return the 4-byte IP address, converting it into host byte order.
ACE_INLINE ACE_UINT32
diff --git a/ace/Log_Msg.cpp b/ace/Log_Msg.cpp
index d3333bd6ede..8b4cdab22a1 100644
--- a/ace/Log_Msg.cpp
+++ b/ace/Log_Msg.cpp
@@ -23,9 +23,14 @@
#include "ace/Thread.h"
#include "ace/Synch.h"
-
#include "ace/Log_Msg.h"
+#if defined (ACE_HAS_UNICODE)
+#define ACE_WSPRINTF(BUF,VALUE) ::wsprintf (BUF, "%S", VALUE)
+#else
+#define ACE_WSPRINTF(BUF,VALUE) ::sprintf (BUF, "%s", VALUE)
+#endif /* ACE_HAS_UNICODE */
+
// IPC conduit between sender and client daemon. This should be
// included in the <ACE_Log_Msg> class, but due to "order of include"
// problems it can't be...
@@ -433,6 +438,7 @@ ACE_Log_Msg::log (const char *format_str,
break;
case 'N':
{
+ // @@ UNICODE
const char *file = this->file ();
ACE_OS::sprintf (bp, "%s", file ? file : "<unknown file>");
type = SKIP_SPRINTF;
@@ -440,26 +446,27 @@ ACE_Log_Msg::log (const char *format_str,
}
case 'n': // Print the name of the program.
type = SKIP_SPRINTF;
+ // @@ UNICODE
ACE_OS::strcpy (bp, ACE_Log_Msg::program_name_ ?
- ACE_Log_Msg::program_name_ : "<unknown>");
+ ACE_Log_Msg::program_name_ : "<unknown>");
break;
- case 'P': // format the current process id
+ case 'P': // Format the current process id.
type = SKIP_SPRINTF;
ACE_OS::sprintf (bp, "%d", this->getpid ());
break;
- case 'p': // format the string assocated with the value of errno.
+ case 'p': // Format the string assocated with the value of errno.
{
type = SKIP_SPRINTF;
errno = ACE::map_errno (errno);
if (errno >= 0 && errno < sys_nerr)
ACE_OS::sprintf (bp, "%s: %s",
- va_arg (argp, char *), strerror (errno));
+ va_arg (argp, char *), strerror (errno));
else
ACE_OS::sprintf (bp, "%s: <unknown error> = %d",
- va_arg (argp, char *), errno);
+ va_arg (argp, char *), errno);
break;
}
- case 'R': // format the return status of the operation.
+ case 'R': // Format the return status of the operation.
this->op_status (va_arg (argp, int));
ACE_OS::sprintf (bp, "%d", this->op_status ());
break;
@@ -498,7 +505,7 @@ ACE_Log_Msg::log (const char *format_str,
#endif /* ACE_HAS_SYS_SIGLIST */
break;
}
- case 'T': /* format the timestamp*/
+ case 'T': // Format the timestamp.
{
type = SKIP_SPRINTF;
char day_and_time[35];
@@ -507,7 +514,7 @@ ACE_Log_Msg::log (const char *format_str,
sizeof day_and_time));
break;
}
- case 't': // format thread id.
+ case 't': // Format thread id.
type = SKIP_SPRINTF;
#if defined (ACE_WIN32)
ACE_OS::sprintf (bp, "%u", ACE_Thread::self ());
@@ -520,6 +527,8 @@ ACE_Log_Msg::log (const char *format_str,
case 's':
type = 1 + wpc; // 1, 2, 3
break;
+ case 'W':
+ // @@ UNICODE
case 'd': case 'c': case 'i': case 'o':
case 'u': case 'x': case 'X':
type = 4 + wpc; // 4, 5, 6
diff --git a/ace/Log_Msg.h b/ace/Log_Msg.h
index 6ba5604385a..b9b2ea73b5b 100644
--- a/ace/Log_Msg.h
+++ b/ace/Log_Msg.h
@@ -37,6 +37,7 @@
#define ACE_HEX_DUMP(X)
#define ACE_RETURN(ERROR, Y) do { errno = ERROR, return (Y); } while (0)
#define ACE_ERROR_RETURN(X, Y) return (Y)
+#define ACE_ERROR_BREAK(X) { break; }
#define ACE_ERROR(X)
#define ACE_DEBUG(X)
#define ACE_ERROR_INIT(VALUE, FLAGS)
@@ -77,6 +78,7 @@
ACE_Log_Msg *ace___ = ACE_Log_Msg::instance (); \
ace___->set_flags (FLAGS); ace___->op_status (VALUE); \
} while (0)
+#define ACE_ERROR_BREAK(X) { ACE_ERROR (X); break; }
#endif /* ACE_NLOGGING */
#include "ace/Log_Record.h"
diff --git a/ace/Malloc_T.cpp b/ace/Malloc_T.cpp
index ace2eb0717f..6e8d9a99132 100644
--- a/ace/Malloc_T.cpp
+++ b/ace/Malloc_T.cpp
@@ -453,6 +453,29 @@ ACE_Malloc<ACE_MEM_POOL_2, LOCK>::find (const char *name, void *&pointer)
}
}
+template <ACE_MEM_POOL_1, class LOCK> size_t
+ACE_Malloc<ACE_MEM_POOL_2, LOCK>::avail_chunks (const size_t size) const
+{
+ ACE_Read_Guard<LOCK> mon (this->lock_);
+
+ static const size_t mal_size = sizeof (ACE_Malloc_Header);
+ size_t count = 0;
+ const size_t sizeof_oversize_ = mal_size / size;
+
+ for (ACE_Malloc_Header *currp = this->cb_ptr_->freep_->s_.next_block_;
+ ; currp = currp->s_.next_block_)
+ {
+ if (currp->s_.size_ * sizeof (ACE_Malloc_Header) >= size_)
+ count += currp->s_.size_ * sizeof_oversize_;
+ // How many will fit in this block.
+
+ if (currp == this->cb_ptr_->freep_)
+ break;
+ }
+
+ return count;
+}
+
template <ACE_MEM_POOL_1, class LOCK> int
ACE_Malloc<ACE_MEM_POOL_2, LOCK>::find (const char *name)
{
diff --git a/ace/Malloc_T.h b/ace/Malloc_T.h
index dd2a9aae186..5dfe6be0ad3 100644
--- a/ace/Malloc_T.h
+++ b/ace/Malloc_T.h
@@ -126,6 +126,9 @@ public:
// Change the protection of the pages of the mapped region to <prot>
// starting at <addr> up to <len> bytes.
+ size_t avail_chunks (const size_t size) const;
+ // Returns a count of the number of available chunks.
+
ALLOCATOR &alloc (void);
// Returns the underlying allocator.
diff --git a/ace/Message_Queue.h b/ace/Message_Queue.h
index 8a84406a584..84a96159302 100644
--- a/ace/Message_Queue.h
+++ b/ace/Message_Queue.h
@@ -191,16 +191,16 @@ protected:
ACE_Message_Block *tail_;
// Pointer to tail of ACE_Message_Block list.
- int low_water_mark_;
+ size_t low_water_mark_;
// Lowest number before unblocking occurs.
- int high_water_mark_;
+ size_t high_water_mark_;
// Greatest number of bytes before blocking.
- int cur_bytes_;
+ size_t cur_bytes_;
// Current number of bytes in the queue.
- int cur_count_;
+ size_t cur_count_;
// Current number of messages in the queue.
int deactivated_;
diff --git a/ace/OS.cpp b/ace/OS.cpp
index ceb87dcd53f..ec2cee57ef8 100644
--- a/ace/OS.cpp
+++ b/ace/OS.cpp
@@ -963,6 +963,26 @@ ACE_OS::thr_keyfree (ACE_thread_key_t key)
#endif /* ACE_HAS_THREADS */
}
+int
+ACE_OS::thr_win32_tls_table_lock (void)
+{
+#if defined (ACE_WIN32)
+ return ACE_TSS_Cleanup::lock_.acquire ();
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 */
+}
+
+int
+ACE_OS::thr_win32_tls_table_release (void)
+{
+#if defined (ACE_WIN32)
+ return ACE_TSS_Cleanup::lock_.release ();
+#else
+ ACE_NOTSUP_RETURN (-1);
+#endif /* ACE_WIN32 */
+}
+
int
ACE_OS::thr_keycreate (ACE_thread_key_t *key,
void (*dest) (void *),
@@ -1239,3 +1259,10 @@ ACE_OS::socket_fini (void)
int sys_nerr = ERRMAX + 1;
#endif /* VXWORKS */
+
+#if !defined (ACE_HAS_SIGINFO_T)
+siginfo_t::siginfo_t (ACE_HANDLE handle)
+ : si_handle_ (handle)
+{
+}
+#endif /* ACE_HAS_SIGINFO_T */
diff --git a/ace/OS.h b/ace/OS.h
index 6f00c23cdd6..687ab5a263b 100644
--- a/ace/OS.h
+++ b/ace/OS.h
@@ -1774,7 +1774,13 @@ typedef LPCTSTR ACE_DL_TYPE;
#endif /* ACE_HAS_CHARPTR_DL */
#if !defined (ACE_HAS_SIGINFO_T)
-typedef int siginfo_t;
+struct siginfo_t
+{
+ siginfo_t (ACE_HANDLE handle);
+
+ ACE_HANDLE si_handle_;
+ // Win32 HANDLE that has become signaled.
+};
#endif /* ACE_HAS_SIGINFO_T */
#if !defined (ACE_HAS_UCONTEXT_T)
@@ -2182,7 +2188,7 @@ public:
static long strtol (const char *s, char **ptr, int base);
#if defined (ACE_HAS_UNICODE)
- // = A set of wrappers for non-UNICODE string operations.
+ // = A set of wrappers for UNICODE string operations.
static wchar_t *strcat (wchar_t *s, const wchar_t *t);
static wchar_t *strchr (const wchar_t *s, int c);
static wchar_t *strrchr (const wchar_t *s, int c);
@@ -2252,6 +2258,8 @@ public:
static int thr_join (ACE_thread_t waiter_id, ACE_thread_t *thr_id, void **status);
static int thr_keyfree (ACE_thread_key_t key);
static int thr_key_detach (void *inst);
+ static int thr_win32_tls_table_lock(void);
+ static int thr_win32_tls_table_release(void);
static int thr_keycreate (ACE_thread_key_t *key, void (*dest)(void *), void *inst = 0);
static int thr_key_used (ACE_thread_key_t key);
static int thr_kill (ACE_thread_t thr_id, int signum);
diff --git a/ace/OS.i b/ace/OS.i
index 8835a4023fe..a8402405d67 100644
--- a/ace/OS.i
+++ b/ace/OS.i
@@ -1125,6 +1125,10 @@ ACE_OS::cond_timedwait (ACE_cond_t *cv,
// is locked!
cv->waiters_++;
+ // 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;
@@ -1146,6 +1150,7 @@ ACE_OS::cond_timedwait (ACE_cond_t *cv,
result = ::WaitForSingleObject (cv->sema_, relative_time.msec ());
}
+ // Reacquire the lock before we decrement the count of waiters.
ACE_OS::mutex_lock (external_mutex);
cv->waiters_--;
@@ -3000,7 +3005,9 @@ ACE_OS::thr_getspecific (ACE_thread_key_t key, void **data)
}
ACE_INLINE int
-ACE_OS::thr_join (ACE_thread_t waiter_id, ACE_thread_t *thr_id, void **status)
+ACE_OS::thr_join (ACE_thread_t waiter_id,
+ ACE_thread_t *thr_id,
+ void **status)
{
// ACE_TRACE ("ACE_OS::thr_join");
#if defined (ACE_HAS_THREADS)
@@ -3032,13 +3039,18 @@ ACE_OS::thr_join (ACE_hthread_t thr_handle, void **status)
#elif defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS)
ACE_NOTSUP_RETURN (-1);
#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)
diff --git a/ace/Pipe.cpp b/ace/Pipe.cpp
index 31ab6d95d85..5979e56fb77 100644
--- a/ace/Pipe.cpp
+++ b/ace/Pipe.cpp
@@ -30,8 +30,9 @@ ACE_Pipe::open (void)
ACE_SOCK_Stream writer;
int result = 0;
- // Bind listener to any port.
- if (acceptor.open (ACE_Addr::sap_any) == -1)
+ // Bind listener to any port, make sure to enable the "reuse addr"
+ // flag.
+ if (acceptor.open (ACE_Addr::sap_any, 1) == -1)
result = -1;
else if (acceptor.get_local_addr (my_addr) == -1)
result = -1;
@@ -39,8 +40,9 @@ ACE_Pipe::open (void)
{
ACE_INET_Addr sv_addr (my_addr.get_port_number (), "localhost");
- // Establish a connection within the same process!
- if (connector.connect (writer, sv_addr) == -1)
+ // Establish a connection within the same process, make sure to
+ // enable the "reuse addr" flag.
+ if (connector.connect (writer, sv_addr, 0, ACE_Addr::sap_any, 1) == -1)
result = -1;
else if (acceptor.accept (reader) == -1)
{
@@ -49,6 +51,14 @@ ACE_Pipe::open (void)
}
}
+ int one = 1;
+ // Make sure that the TCP stack doesn't try to buffer small writes.
+ if (this->ACE_SOCK::set_option (IPPROTO_TCP,
+ TCP_NODELAY,
+ &one,
+ sizeof one) == -1)
+ return -1;
+
// Close down the acceptor endpoint since we don't need it anymore.
acceptor.close ();
if (result == -1)
diff --git a/ace/ReactorEx.cpp b/ace/ReactorEx.cpp
index 6a55493a11b..a8a2c9eb3c1 100644
--- a/ace/ReactorEx.cpp
+++ b/ace/ReactorEx.cpp
@@ -168,11 +168,15 @@ ACE_ReactorEx::handle_events (ACE_Time_Value *how_long,
{
// @@ Need to implement WAIT_ABANDONED_0 stuff.
relative_index = wait_status - WAIT_OBJECT_0;
-
- if (relative_handlers[relative_index]->handle_signal (0) == -1)
+ // Assign the ``signaled'' HANDLE so that callers can get
+ // it.
+ siginfo_t sig (relative_handles[relative_index]);
+
+ if (relative_handlers[relative_index]->handle_signal
+ (0, &sig) == -1)
// If we remove a handler, then the index should stay
- // the same, since it may have been replaced with the
- // end handle by remove_handler.
+ // the same since it may have been replaced with the end
+ // handle by remove_handler.
this->remove_handler (relative_handlers[relative_index]);
else
// If we did not remove the handler, then move the index
diff --git a/ace/SOCK_Stream.cpp b/ace/SOCK_Stream.cpp
index 0dc237200a9..2ff53e4b33a 100644
--- a/ace/SOCK_Stream.cpp
+++ b/ace/SOCK_Stream.cpp
@@ -12,5 +12,14 @@ ACE_SOCK_Stream::dump (void) const
ACE_TRACE ("ACE_SOCK_Stream::dump");
}
-
+int
+ACE_SOCK_Stream::close (void)
+{
+ // We need the following call to make things work correctly on
+ // Win32, which requires use to do a <close_writer> before doing the
+ // close in order to avoid losing data.
+ this->close_writer ();
+ // Close down the socket.
+ ACE_SOCK::close ();
+}
diff --git a/ace/SOCK_Stream.h b/ace/SOCK_Stream.h
index 826ede89c17..4111c01d12e 100644
--- a/ace/SOCK_Stream.h
+++ b/ace/SOCK_Stream.h
@@ -66,6 +66,11 @@ public:
int close_writer (void);
// Close down the writer.
+ int close (void);
+ // Close down the socket (we need this to make things work correctly
+ // on Win32, which requires use to do a <close_writer> before doing
+ // the close in order to avoid losing data).
+
// = Meta-type info
typedef ACE_INET_Addr PEER_ADDR;
diff --git a/ace/Synch_T.cpp b/ace/Synch_T.cpp
index c5c552a3204..4336dbcbfd1 100644
--- a/ace/Synch_T.cpp
+++ b/ace/Synch_T.cpp
@@ -309,22 +309,31 @@ ACE_TSS<TYPE>::ts_get (void) const
// Create and initialize thread-specific ts_obj.
if (this->once_ == 0)
{
+ // We need the lock for ACE_TSS_Cleanup as well since the
+ // ACE_Thread::keycreate() method requires access to internal
+ // tables. This is to avoid deadlocks when using ACE_TSS from
+ // the close() hook of an ACE_Task.
+ ACE_OS::thr_win32_tls_table_lock ();
+
// Insure that we are serialized!
- ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, (ACE_Thread_Mutex &) this->keylock_, 0);
+ ACE_GUARD_RETURN (ACE_Mutex, ace_mon, (ACE_Mutex &) this->keylock_, 0);
+
+ int result;
// Use the Double-Check pattern to make sure we only create the
// key once!
if (this->once_ == 0)
- {
- if (ACE_Thread::keycreate ((ACE_thread_key_t *) &this->key_,
- &ACE_TSS<TYPE>::cleanup,
- (void *) this) != 0)
- return 0; // Major problems, this should *never* happen!
-
- // This *must* come last to avoid race conditions! Note
- // that we need to "cast away const..."
- *(int *) &this->once_ = 1;
- }
+ result = ACE_Thread::keycreate ((ACE_thread_key_t *) &this->key_,
+ &ACE_TSS<TYPE>::cleanup,
+ (void *) this);
+ ACE_OS::thr_win32_tls_table_release ();
+
+ if (result != 0)
+ return 0; // Major problems, this should *never* happen!
+ else
+ // This *must* come last to avoid race conditions! Note
+ // that we need to "cast away const..."
+ *(int *) &this->once_ = 1;
}
TYPE *ts_obj = 0;
diff --git a/ace/System_Time.cpp b/ace/System_Time.cpp
index 7d606909a9a..9d2f259daaa 100644
--- a/ace/System_Time.cpp
+++ b/ace/System_Time.cpp
@@ -6,7 +6,7 @@
#include "ace/System_Time.h"
ACE_System_Time::ACE_System_Time (const char *poolname)
-: delta_time_ (0)
+ : delta_time_ (0)
{
ACE_TRACE ("ACE_System_Time::ACE_System_Time");
ACE_NEW (this->shmem_, ALLOCATOR (poolname));
@@ -24,17 +24,24 @@ int
ACE_System_Time::get_local_system_time (ACE_UINT32 &time_out)
{
ACE_TRACE ("ACE_System_Time::get_local_system_time");
- time_t t = ACE_OS::time (0);
- time_out = t;
+ time_out = ACE_OS::time (0);
return 0;
}
+int
+ACE_System_Time::get_local_system_time (ACE_Time_Value &time_out)
+{
+ ACE_TRACE ("ACE_System_Time::get_local_system_time");
+ time_out.sec (ACE_OS::time (0));
+}
+
// Get the system time of the central time server.
int
ACE_System_Time::get_master_system_time (ACE_UINT32 &time_out)
{
ACE_TRACE ("ACE_System_Time::get_master_system_time");
+
if (this->delta_time_ == 0)
{
// Try to find it
@@ -46,11 +53,10 @@ ACE_System_Time::get_master_system_time (ACE_UINT32 &time_out)
return this->get_local_system_time (time_out);
}
else
- {
- // Extract the delta time
- this->delta_time_ = (long *) temp;
- }
+ // Extract the delta time.
+ this->delta_time_ = (long *) temp;
}
+
ACE_UINT32 local_time;
// If delta_time is positive, it means that the system clock is
@@ -70,6 +76,17 @@ ACE_System_Time::get_master_system_time (ACE_UINT32 &time_out)
return 0;
}
+int
+ACE_System_Time::get_master_system_time (ACE_Time_Value &time_out)
+{
+ ACE_TRACE ("ACE_System_Time::get_master_system_time");
+ ACE_UINT32 to;
+ if (this->get_master_system_time (to) == -1)
+ return -1;
+ time_out.sec (to);
+ return 0;
+}
+
// Synchronize local system time with the central time server using
// specified mode (currently unimplemented).
@@ -77,7 +94,7 @@ int
ACE_System_Time::sync_local_system_time (ACE_System_Time::Sync_Mode)
{
ACE_TRACE ("ACE_System_Time::sync_local_system_time");
- return 0;
+ ACE_NOTSUP_RETURN (-1);
}
#if defined (ACE_TEMPLATES_REQUIRE_SPECIALIZATION)
diff --git a/ace/System_Time.h b/ace/System_Time.h
index 2e3f2cab101..8e167228ec6 100644
--- a/ace/System_Time.h
+++ b/ace/System_Time.h
@@ -49,12 +49,20 @@ public:
~ACE_System_Time (void);
// Default destructor.
- int get_local_system_time (ACE_UINT32 &time_out);
- // Get the local system time.
+ static int get_local_system_time (ACE_UINT32 &time_out);
+ // Get the local system time, i.e., the value returned by
+ // <ACE_OS::time>.
+
+ static int get_local_system_time (ACE_Time_Value &time_out);
+ // Get the local system time, i.e., the value returned by
+ // <ACE_OS::time>.
int get_master_system_time (ACE_UINT32 &time_out);
// Get the system time of the central time server.
+ int get_master_system_time (ACE_Time_Value &time_out);
+ // Get the system time of the central time server.
+
int sync_local_system_time (ACE_System_Time::Sync_Mode mode);
// synchronize local system time with the central time server using
// specified mode.
diff --git a/ace/Thread.cpp b/ace/Thread.cpp
index ad3cffca16e..a1e9ea83e8f 100644
--- a/ace/Thread.cpp
+++ b/ace/Thread.cpp
@@ -40,8 +40,9 @@ ACE_Thread::spawn_n (ACE_thread_t thread_ids[],
void *arg,
long flags,
u_int priority,
- void **stack,
- size_t stack_size[])
+ void *stack[],
+ size_t stack_size[],
+ ACE_hthread_t thread_handles[])
{
ACE_TRACE ("ACE_Thread::spawn_n");
size_t i;
@@ -49,14 +50,21 @@ ACE_Thread::spawn_n (ACE_thread_t thread_ids[],
for (i = 0; i < n; i++)
{
ACE_thread_t t_id;
+ ACE_hthread_t t_handle;
int result = ACE_OS::thr_create
- (func, arg, flags, &t_id, 0, priority,
+ (func, arg, flags,
+ &t_id, &t_handle,
+ priority,
stack == 0 ? 0 : stack[i],
stack_size == 0 ? 0 : stack_size[i]);
if (result == 0)
- thread_ids[i] = t_id;
+ {
+ thread_ids[i] = t_id;
+ if (thread_handles != 0)
+ thread_handles[i] = t_handle;
+ }
else
// Bail out if error occurs.
break;
diff --git a/ace/Thread.h b/ace/Thread.h
index 9258f4093e3..1579dc4e29f 100644
--- a/ace/Thread.h
+++ b/ace/Thread.h
@@ -63,17 +63,20 @@ public:
long flags,
u_int priority = 0,
void *stack[] = 0,
- size_t stack_size[] = 0);
+ size_t stack_size[] = 0,
+ ACE_hthread_t thread_handles[] = 0);
// Spawn N new threads, which execute <func> with argument <arg>.
// The thread_ids of successfully spawned threads will be placed
- // into the <thread_ids> buffer, which must be the same size as <n>.
- // If <stack> != 0 it is assumed to be an array of <n> pointers to
- // the base of the stacks to use for the threads being spawned.
- // Likewise, if <stack_size> != 0 it is assumed to be an array of
+ // into the <thread_ids> buffer (which must be the same size as
+ // <n>). If <stack> != 0 it is assumed to be an array of <n>
+ // pointers to the base of the stacks to use for the threads being
+ // spawned. If <stack_size> != 0 it is assumed to be an array of
// <n> values indicating how big each of the corresponding <stack>s
- // are. Returns the number of threads actually spawned (if this
- // doesn't equal the number requested then something has gone wrong
- // and <errno> will explain...).
+ // are. If <thread_handles> != 0 it is assumed to be an array of
+ // <n> thread_handles that will be assigned the values of the thread
+ // handles being spawned. Returns the number of threads actually
+ // spawned (if this doesn't equal the number requested then
+ // something has gone wrong and <errno> will explain...).
static int join (ACE_thread_t,
ACE_thread_t *,
diff --git a/ace/Thread_Manager.cpp b/ace/Thread_Manager.cpp
index 035af3bf0ec..8701b50b532 100644
--- a/ace/Thread_Manager.cpp
+++ b/ace/Thread_Manager.cpp
@@ -276,6 +276,45 @@ ACE_Thread_Manager::spawn_n (int n,
return grp_id;
}
+// Create N new threads running FUNC.
+
+int
+ACE_Thread_Manager::spawn_n (ACE_thread_t thread_ids[],
+ size_t n,
+ ACE_THR_FUNC func,
+ void *args,
+ long flags,
+ u_int priority,
+ int grp_id,
+ void *stack[],
+ size_t stack_size[],
+ ACE_hthread_t thread_handles[])
+{
+ ACE_TRACE ("ACE_Thread_Manager::spawn_n");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ if (grp_id == -1)
+ grp_id = this->grp_id_++; // Increment the group id.
+
+ for (int i = 0; i < n; i++)
+ {
+ // @@ What should happen if this fails?! e.g., should we try to
+ // cancel the other threads that we've already spawned or what?
+ if (this->spawn_i (func,
+ args,
+ flags,
+ &thread_ids[i],
+ thread_handles == 0 ? 0 : &thread_handles[i],
+ priority,
+ grp_id,
+ stack == 0 ? 0 : stack[i],
+ stack_size == 0 ? 0 : stack_size[i]) == -1)
+ return -1;
+ }
+
+ return grp_id;
+}
+
// Append a thread into the pool (does not check for duplicates).
// Must be called with locks held.
diff --git a/ace/Thread_Manager.h b/ace/Thread_Manager.h
index dfa1396f468..7cde91d5d93 100644
--- a/ace/Thread_Manager.h
+++ b/ace/Thread_Manager.h
@@ -118,6 +118,28 @@ public:
// Returns: on success a unique group id that can be used to control
// all of the threads in the same group. On failure, returns -1.
+ int spawn_n (ACE_thread_t thread_ids[],
+ size_t n,
+ ACE_THR_FUNC func,
+ void *args,
+ long flags,
+ u_int priority = 0,
+ int grp_id = -1,
+ void *stack[] = 0,
+ size_t stack_size[] = 0,
+ ACE_hthread_t thread_handles[] = 0);
+ // Spawn N new threads, which execute <func> with argument <arg>.
+ // The thread_ids of successfully spawned threads will be placed
+ // into the <thread_ids> buffer (which must be the same size as
+ // <n>). If <stack> != 0 it is assumed to be an array of <n>
+ // pointers to the base of the stacks to use for the threads being
+ // spawned. If <stack_size> != 0 it is assumed to be an array of
+ // <n> values indicating how big each of the corresponding <stack>s
+ // are. If <thread_handles> != 0 it is assumed to be an array of
+ // <n> thread_handles that will be assigned the values of the thread
+ // handles being spawned. Returns -1 on failure (<errno> will
+ // explain...), otherwise returns the group id of the threads.
+
void *exit (void *status, int do_thread_exit = 1);
// Called to clean up when a thread exits. If <do_thread_exit> is
// non-0 then <ACE_Thread::exit> is called to exit the thread, in
diff --git a/ace/config-irix6.2-sgic++.h b/ace/config-irix6.2-sgic++.h
index 8c065491dd3..db80b336940 100644
--- a/ace/config-irix6.2-sgic++.h
+++ b/ace/config-irix6.2-sgic++.h
@@ -3,12 +3,12 @@
// The following configuration file is designed to work for the SGI
// Indigo2EX running IRIX 6.2 platform using the SGI C++ Compiler.
-// Please note that the following system patches MUST be applied to
-// Irix 6.2 in order to have MT:
-//
-// patchSG0001361
-// patchSG0001367
-// patchSG0001389
+
+// In order to have support for multi-threading, several patches must
+// be applied to the stock Irix 6.2 kernel, involving changes that
+// bring this kernel up to POSIX 1003.c compatibility. These patches
+// are updated frequently, so you should ask your support contact or
+// search SGI's web site (http://www.sgi.com) for the latest version.
#if !defined (ACE_CONFIG_H)
#define ACE_CONFIG_H