summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog-97a21
-rw-r--r--README1
-rw-r--r--ace/Process.cpp25
-rw-r--r--ace/Process.h2
-rw-r--r--ace/Process_Manager.cpp131
-rw-r--r--ace/Process_Manager.h62
-rw-r--r--ace/Thread_Manager.cpp5
-rw-r--r--ace/Thread_Manager.h2
-rw-r--r--tests/Naming_Test.cpp21
-rw-r--r--tests/Timer_Queue_Test.cpp50
-rw-r--r--tests/test_config.h22
11 files changed, 211 insertions, 131 deletions
diff --git a/ChangeLog-97a b/ChangeLog-97a
index 739d500450f..924dee9db52 100644
--- a/ChangeLog-97a
+++ b/ChangeLog-97a
@@ -1,5 +1,26 @@
Sun Apr 13 11:40:26 1997 Douglas C. Schmidt <schmidt@flamenco.cs.wustl.edu>
+ * ace/Thread_Manager: Changed the 'int n' of spawn_n() to size_t n
+ since this is more appropriate because we can't spawn a negative
+ number of threads...
+
+ * ace/Thread_Manager.cpp (close): Make sure to lock the calls to
+ close() in case things get amiss.
+
+ * ace/Process.cpp (start): Updated ACE_Process::start() to that it
+ doesn't try to exec() a program if argv == 0. This allows us to
+ use ACE_Process to fork() a process without exec'ing.
+
+ * tests/Timer_Queue_Test.cpp (randomize_array): Added a new
+ "randomization" test that determines the performance of randomly
+ canceling items in the array. Thanks to Darrell Brunsch
+ <brunsch@cs.wustl.edu> for this enhancement.
+
+ * tests/test_config.h: Moved the randomize() function from
+ Naming_Test.cpp to test_config.h so that we can use it in other
+ tests (e.g., the new Timer_Queue_Test.cpp that Darrell is
+ working on).
+
* ace/OS: Added a new #define called ACE_HAS_NONCONST_MSGSND which
can be used for platforms (e.g., SCO) that don't have a const
parameter for msgsend(). Thanks to Arturo Montes
diff --git a/README b/README
index dd32c1d7319..24cc1b6bac9 100644
--- a/README
+++ b/README
@@ -499,6 +499,7 @@ Ganesh Pai <gpai@voicetek.com>
Berni Merkle <merkle@io.freinet.de>
Tom Wright <twright@gem-net.demon.co.uk>
Torbjorn Lindgren <tl@funcom.no>
+Darrell Brunsch <brunsch@cs.wustl.edu>
I would particularly like to thank Paul Stephenson, who worked with me
at Ericsson and is now at ObjectSpace. Paul devised the recursive
diff --git a/ace/Process.cpp b/ace/Process.cpp
index f97ddab6c31..76d3b5d5710 100644
--- a/ace/Process.cpp
+++ b/ace/Process.cpp
@@ -119,7 +119,7 @@ ACE_Process::set_cwd (const TCHAR *cwd)
return 0;
}
-int
+pid_t
ACE_Process::start (char *argv[], char *envp[])
{
#if defined (ACE_WIN32)
@@ -179,17 +179,20 @@ ACE_Process::start (char *argv[], char *envp[])
if (this->cwd_[0] != '\0')
::chdir (cwd_);
- // Child process executes the command.
- int result;
+ if (argv != 0)
+ {
+ // Child process executes the command.
+ int result;
- if (envp == 0)
- result = ACE_OS::execv (argv[0], argv);
- else
- result = ACE_OS::execve (argv[0], argv, envp);
-
- if (result == -1)
- // If the execv fails, this child needs to exit.
- ACE_OS::exit (errno);
+ if (envp == 0)
+ result = ACE_OS::execv (argv[0], argv);
+ else
+ result = ACE_OS::execve (argv[0], argv, envp);
+
+ if (result == -1)
+ // If the execv fails, this child needs to exit.
+ ACE_OS::exit (errno);
+ }
default:
// Server process. The fork succeeded.
return 0;
diff --git a/ace/Process.h b/ace/Process.h
index 3d5781bfe00..82cc94d4b40 100644
--- a/ace/Process.h
+++ b/ace/Process.h
@@ -66,7 +66,7 @@ public:
int set_cwd (const TCHAR *cwd);
// Set the working directory for the process.
- int start (char *argv[], char *envp[] = 0);
+ pid_t start (char *argv[], char *envp[] = 0);
// Start the new process. <argv> must be specified. It should be
// of the following form: argv = { "c:\full\path\to\foo.exe", "-a",
// "arg1", "etc", 0 }. If <envp> is specified, it is passed as the
diff --git a/ace/Process_Manager.cpp b/ace/Process_Manager.cpp
index 1ef354593f1..027e5b68fe9 100644
--- a/ace/Process_Manager.cpp
+++ b/ace/Process_Manager.cpp
@@ -1,8 +1,8 @@
-#if 0
// $Id$
// Process_Manager.cpp
#define ACE_BUILD_DLL
+#include "ace/Process.h"
#include "ace/Process_Manager.h"
#if !defined (__ACE_INLINE__)
@@ -27,7 +27,21 @@ int
ACE_Process_Manager::resize (size_t size)
{
ACE_TRACE ("ACE_Process_Manager::resize");
- return -1;
+
+ ACE_TRACE ("ACE_Thread_Manager::resize");
+ ACE_Process_Descriptor *temp;
+
+ ACE_NEW_RETURN (temp, ACE_Process_Descriptor[size], -1);
+
+ for (size_t i = 0; i < this->max_table_size_; i++)
+ temp[i] = this->proc_table_[i]; // Structure assignment.
+
+ this->max_table_size_ = size;
+
+ delete [] this->proc_table_;
+
+ this->proc_table_ = temp;
+ return 0;
}
// Create and initialize the table to keep track of the process pool.
@@ -36,14 +50,29 @@ int
ACE_Process_Manager::open (size_t size)
{
ACE_TRACE ("ACE_Process_Manager::open");
- return -1;
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ if (this->max_table_size_ < size)
+ this->resize (size);
+ return 0;
+
}
// Initialize the synchronization variables.
ACE_Process_Manager::ACE_Process_Manager (size_t size)
+ : proc_table_ (0),
+ max_table_size_ (0),
+ current_count_ (0)
+#if defined (ACE_HAS_THREADS)
+ , zero_cond_ (lock_)
+#endif /* ACE_HAS_THREADS */
{
ACE_TRACE ("ACE_Process_Manager::ACE_Process_Manager");
+
+ if (this->open (size) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Process_Manager"));
}
// Close up and release all resources.
@@ -52,7 +81,17 @@ int
ACE_Process_Manager::close (void)
{
ACE_TRACE ("ACE_Process_Manager::close");
- return -1;
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
+ if (this->proc_table_ != 0)
+ {
+ delete [] this->proc_table_;
+ this->proc_table_ = 0;
+ this->max_table_size_ = 0;
+ this->current_count_ = 0;
+ }
+ return 0;
}
ACE_Process_Manager::~ACE_Process_Manager (void)
@@ -61,61 +100,72 @@ ACE_Process_Manager::~ACE_Process_Manager (void)
this->close ();
}
-// Call the appropriate OS routine to spawn a process. Should *not*
-// be called with the lock_ held...
-
-int
-ACE_Process_Manager::spawn_i (ACE_THR_FUNC func,
- void *args,
- long flags,
- pid_t *t_id,
- u_int priority,
- void *stack,
- size_t stack_size)
-{
- ACE_TRACE ("ACE_Process_Manager::spawn_i");
- return -1;
-}
-
// Create a new process running FUNC. *Must* be called with the lock_
// held...
-int
-ACE_Process_Manager::spawn (ACE_THR_FUNC func,
- void *args,
- long flags,
- pid_t *t_id,
- u_int priority,
- void *stack,
- size_t stack_size)
-{
- ACE_TRACE ("ACE_Process_Manager::spawn");
- return -1;
+pid_t
+ACE_Process_Manager::start (char *argv[],
+ char *envp[])
+{
+ ACE_TRACE ("ACE_Process_Manager::start");
+
+ // Create a new process, potentially causing an exec(), as well.
+ // This API clearly needs to be improved to pass more information
+ // in...
+ pid_t pid = ACE_Process process (argv,
+ ACE_INVALID_HANDLE,
+ ACE_INVALID_HANDLE,
+ ACE_INVALID_HANDLE,
+ envp);
+ if (pid == -1)
+ return -1;
+ else
+ return this->append_proc (pid);
}
// Create N new processs running FUNC.
int
-ACE_Process_Manager::spawn_n (int n,
- ACE_THR_FUNC func,
- void *args,
- long flags,
- u_int priority)
+ACE_Process_Manager::start_n (size_t n,
+ char *argv[],
+ char *envp[])
{
ACE_TRACE ("ACE_Process_Manager::spawn_n");
- return -1;
+
+ for (size_t i = 0; i < n; i++)
+ if (this->start (argv, envp) == -1)
+ return -1;
+
+ return 0;
+
}
// Append a process into the pool (does not check for duplicates).
// Must be called with locks held.
int
-ACE_Process_Manager::append_proc (pid_t t_id,
- ACE_Process_Descriptor::Process_State proc_state)
+ACE_Process_Manager::append_proc (pid_t pid,
+ ACE_Process_Descriptor::Process_State proc_state)
{
ACE_TRACE ("ACE_Process_Manager::append_proc");
- return -1;
+ // Try to resize the array to twice its existing size if we run out
+ // of space...
+ if (this->current_count_ >= this->max_table_size_
+ && this->resize (this->max_table_size_ * 2) == -1)
+ return -1;
+ else
+ {
+ ACE_Thread_Descriptor &proc_desc =
+ this->proc_table_[this->current_count_];
+
+ proc_desc.proc_id_ = pid;
+ proc_desc.proc_id_ =
+ proc_desc.proc_state_ = proc_state;
+
+ this->current_count_++;
+ return 0;
+ }
}
// Insert a process into the pool (checks for duplicates and doesn't
@@ -328,4 +378,3 @@ ACE_Process_Control::exit (void *exit_status)
return 0;
}
-#endif
diff --git a/ace/Process_Manager.h b/ace/Process_Manager.h
index b2557e2522f..96896b96a4b 100644
--- a/ace/Process_Manager.h
+++ b/ace/Process_Manager.h
@@ -19,7 +19,6 @@
#include "ace/Synch.h"
-#if 0
class ACE_Export ACE_Process_Descriptor
// = Title
// Information for controlling groups of processs.
@@ -31,7 +30,6 @@ public:
IDLE,
SPAWNED,
RUNNING,
- SUSPENDED,
TERMINATED
};
private:
@@ -41,7 +39,7 @@ private:
pid_t proc_id_;
// Unique process ID.
- int grp_id_;
+ gid_t grp_id_;
// Unique group ID.
Process_State proc_state_;
@@ -76,51 +74,24 @@ public:
int close (void);
// Release all resources.
- int spawn (ACE_THR_FUNC func,
- void *args,
- long flags,
- pid_t * = 0,
- u_int priority = 0,
- void *stack = 0,
- size_t stack_size = 0);
- // Create a new process, which executes <func>.
+ pid_t start (char *argv[], char *envp[] = 0);
+ // Create a new process using <ACE_Process::start>.
// Returns: on success a unique group id that can be used to control
// other processs added to the same group. On failure, returns -1.
- int spawn_n (int n,
- ACE_THR_FUNC func,
- void *args,
- long flags,
- u_int priority = 0);
- // Create N new processs, all of which execute <func>.
+ int start_n (size_t n,
+ char *argv[],
+ char *envp[] = 0);
+ // Create N new processs.
// Returns: on success a unique group id that can be used to control
// all of the processs in the same group. On failure, returns -1.
- void *exit (void *status);
- // Called to clean up when a process exits.
-
int wait (ACE_Time_Value *timeout = 0);
// Block until there are no more processs running or <timeout>
// expires. Returns 0 on success and -1 on failure.
- // = Suspend methods.
- int suspend_all (void);
- // Suspend all processs
- int suspend (pid_t);
- // Suspend a single process.
- int suspend_grp (int grp_id);
- // Suspend a group of processs.
-
- // = Resume methods.
- int resume_all (void);
- // Resume all stopped processs
- int resume (pid_t);
- // Resume a single process.
- int resume_grp (int grp_id);
- // Resume a group of processs.
-
// = Kill methods (send signals...).
int kill_all (int signum);
// Send signum to all stopped processs
@@ -143,15 +114,6 @@ private:
int resize (size_t);
// Resize the pool of Process_Descriptors.
- int spawn_i (ACE_THR_FUNC func,
- void *args,
- long flags,
- pid_t * = 0,
- u_int priority = 0,
- void *stack = 0,
- size_t stack_size = 0);
- // Create a new process (must be called with locks held).
-
int find (pid_t p_id);
// Locate the index of the table slot occupied by <p_id>. Returns
// -1 if <p_id> is not in the table doesn't contain <p_id>.
@@ -178,12 +140,6 @@ private:
int apply_all (PROC_FUNC, int = 0);
// Apply <func> to all members of the table.
- int resume_proc (int i);
- // Resume the process at index <i>.
-
- int suspend_proc (int i);
- // Suspend the process at index <i>.
-
int kill_proc (int i, int signum);
// Send signal <signum> to the process at index <i>.
@@ -196,9 +152,6 @@ private:
size_t current_count_;
// Current number of processs we are managing.
-
- int grp_id_;
- // Keeps track of the next group id to assign.
};
class ACE_Export ACE_Process_Control
@@ -242,7 +195,6 @@ private:
#if defined (__ACE_INLINE__)
#include "ace/Process_Manager.i"
#endif /* __ACE_INLINE__ */
-#endif
#endif /* ACE_PROCESS_MANAGER_H */
diff --git a/ace/Thread_Manager.cpp b/ace/Thread_Manager.cpp
index 41fa8bf7e9d..4ea8f97baf0 100644
--- a/ace/Thread_Manager.cpp
+++ b/ace/Thread_Manager.cpp
@@ -135,6 +135,9 @@ int
ACE_Thread_Manager::close (void)
{
ACE_TRACE ("ACE_Thread_Manager::close");
+
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1));
+
if (this->thr_table_ != 0)
{
delete [] this->thr_table_;
@@ -236,7 +239,7 @@ ACE_Thread_Manager::spawn_n (int n,
if (grp_id == -1)
grp_id = this->grp_id_++; // Increment the group id.
- for (int i = 0; i < n; i++)
+ for (size_t 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?
diff --git a/ace/Thread_Manager.h b/ace/Thread_Manager.h
index afca7b8a833..83a5528d279 100644
--- a/ace/Thread_Manager.h
+++ b/ace/Thread_Manager.h
@@ -105,7 +105,7 @@ public:
// Returns: on success a unique group id that can be used to control
// other threads added to the same group. On failure, returns -1.
- int spawn_n (int n,
+ int spawn_n (size_t n,
ACE_THR_FUNC func,
void *args = 0,
long flags = THR_NEW_LWP,
diff --git a/tests/Naming_Test.cpp b/tests/Naming_Test.cpp
index 8951b2051ba..df39a4fe2f1 100644
--- a/tests/Naming_Test.cpp
+++ b/tests/Naming_Test.cpp
@@ -27,27 +27,6 @@ static char name[BUFSIZ];
static char value[BUFSIZ];
static char type[BUFSIZ];
-static void
-randomize (int array[], size_t size)
-{
- size_t i;
-
- for (i = 0; i < size; i++)
- array [i] = i;
-
- ACE_OS::srand (ACE_OS::time (0L));
-
- // Generate an array of random numbers from 0 .. size - 1.
-
- for (i = 0; i < size; i++)
- {
- int index = ACE_OS::rand() % size--;
- int temp = array [index];
- array [index] = array [size];
- array [size] = temp;
- }
-}
-
static void
print_time (ACE_Profile_Timer &timer,
const char *test)
diff --git a/tests/Timer_Queue_Test.cpp b/tests/Timer_Queue_Test.cpp
index 7cd92fc486f..d08b8518f9c 100644
--- a/tests/Timer_Queue_Test.cpp
+++ b/tests/Timer_Queue_Test.cpp
@@ -25,6 +25,24 @@
#include "ace/Timer_Heap.h"
#include "test_config.h"
+static void
+randomize_array (int array[], size_t size)
+{
+ size_t i;
+
+ ACE_OS::srand (ACE_OS::time (0L));
+
+ // Randomize the array.
+
+ for (i = 0; i < size; i++)
+ {
+ int index = ACE_OS::rand() % size--;
+ int temp = array [index];
+ array [index] = array [size];
+ array [size] = temp;
+ }
+}
+
// Number of iterations for the performance tests.
static int max_iterations = ACE_DEFAULT_TIMERS * 100 ;
@@ -200,6 +218,38 @@ test_performance (ACE_Timer_Queue *tq,
ACE_DEBUG ((LM_DEBUG,
"time per call = %f usecs\n",
(et.user_time / double (max_iterations)) * 1000000));
+
+ // Test the amount of time required to randomly expire all the
+ // timers.
+
+ for (i = 0; i < max_iterations; i++)
+ {
+ timer_ids[i] = tq->schedule (&eh, (const void *) 42,
+ ACE_OS::gettimeofday ());
+ ACE_ASSERT (timer_ids[i] != -1);
+ }
+
+ ACE_ASSERT (tq->is_empty () == 0);
+
+ randomize_array (timer_ids, max_iterations);
+
+ timer.start ();
+
+ for (i = max_iterations - 1; i >= 0; i--)
+ tq->cancel (timer_ids[i]);
+
+ ACE_ASSERT (tq->is_empty ());
+
+ timer.stop ();
+
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG, "time to randomly expire %d timers for %s\n",
+ max_iterations, test_name));
+ ACE_DEBUG ((LM_DEBUG, "real time = %f secs, user time = %f secs, system time = %f secs\n",
+ et.real_time, et.user_time, et.system_time));
+ ACE_DEBUG ((LM_DEBUG, "time per call = %f usecs\n",
+ (et.user_time / double (max_iterations)) * 1000000));
}
struct Timer_Queues
diff --git a/tests/test_config.h b/tests/test_config.h
index 4f964ccb05e..034dacb76f0 100644
--- a/tests/test_config.h
+++ b/tests/test_config.h
@@ -192,4 +192,26 @@ ACE_Test_Output::close (void)
this->output_file_.flush ();
this->output_file_.close ();
}
+
+static void
+randomize (int array[], size_t size)
+{
+ size_t i;
+
+ for (i = 0; i < size; i++)
+ array [i] = i;
+
+ ACE_OS::srand (ACE_OS::time (0L));
+
+ // Generate an array of random numbers from 0 .. size - 1.
+
+ for (i = 0; i < size; i++)
+ {
+ int index = ACE_OS::rand() % size--;
+ int temp = array [index];
+ array [index] = array [size];
+ array [size] = temp;
+ }
+}
+
#endif /* ACE_TEST_CONFIG_H */