diff options
-rw-r--r-- | ace/INET_Addr.cpp | 15 | ||||
-rw-r--r-- | ace/INET_Addr.i | 13 | ||||
-rw-r--r-- | ace/Log_Msg.cpp | 27 | ||||
-rw-r--r-- | ace/Log_Msg.h | 2 | ||||
-rw-r--r-- | ace/Malloc_T.cpp | 23 | ||||
-rw-r--r-- | ace/Malloc_T.h | 3 | ||||
-rw-r--r-- | ace/Message_Queue.h | 8 | ||||
-rw-r--r-- | ace/OS.cpp | 27 | ||||
-rw-r--r-- | ace/OS.h | 12 | ||||
-rw-r--r-- | ace/OS.i | 16 | ||||
-rw-r--r-- | ace/Pipe.cpp | 18 | ||||
-rw-r--r-- | ace/ReactorEx.cpp | 12 | ||||
-rw-r--r-- | ace/SOCK_Stream.cpp | 11 | ||||
-rw-r--r-- | ace/SOCK_Stream.h | 5 | ||||
-rw-r--r-- | ace/Synch_T.cpp | 31 | ||||
-rw-r--r-- | ace/System_Time.cpp | 33 | ||||
-rw-r--r-- | ace/System_Time.h | 12 | ||||
-rw-r--r-- | ace/Thread.cpp | 16 | ||||
-rw-r--r-- | ace/Thread.h | 19 | ||||
-rw-r--r-- | ace/Thread_Manager.cpp | 39 | ||||
-rw-r--r-- | ace/Thread_Manager.h | 22 | ||||
-rw-r--r-- | ace/config-irix6.2-sgic++.h | 12 |
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 */ @@ -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); @@ -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 |